diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css
index 6861d229e..c7e4cedd0 100644
--- a/app/assets/stylesheets/_global.css
+++ b/app/assets/stylesheets/_global.css
@@ -31,6 +31,11 @@
/* Components */
--btn-size: 2.65em;
--footer-height: 3.5rem;
+ --tray-size: clamp(12rem, 25dvw, 24rem);
+
+ @media (max-width: 799px) {
+ --tray-size: var(--footer-height);
+ }
/* Z-index */
--z-events-column-header: 1;
@@ -278,6 +283,7 @@
--lch-pink-lighter: 30% 0.03 346;
--lch-pink-lightest: 25% 0.011 348;
+ --color-terminal-bg: var(--color-black);
--color-terminal-text-light: oklch(var(--lch-green-dark));
--shadow: 0 0 0 1px oklch(var(--lch-black) / 0.42),
diff --git a/app/assets/stylesheets/terminals.css b/app/assets/stylesheets/terminals.css
index f5a97bf0a..e0902fd49 100644
--- a/app/assets/stylesheets/terminals.css
+++ b/app/assets/stylesheets/terminals.css
@@ -12,7 +12,6 @@
z-index: var(--z-terminal);
@media (prefers-color-scheme: dark) {
- background-color: var(--color-black);
border-block-start: 1px solid var(--color-ink-lighter);
}
}
diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css
index 07f7e6f2d..71ff46a94 100644
--- a/app/assets/stylesheets/trays.css
+++ b/app/assets/stylesheets/trays.css
@@ -1,21 +1,17 @@
-:root {
- --tray-size: max(20dvw, 18rem);
-}
-
@layer components {
/* Container
/* ------------------------------------------------------------------------ */
.tray {
--tray-duration: 350ms;
- --tray-margin: var(--inline-space);
+ --tray-margin: 0.5rem;
--tray-radius: 0.25rem;
--tray-timing-function: cubic-bezier(0.25, 1.25, 0.5, 1);
align-items: end;
- block-size: calc(var(--footer-height) - var(--tray-margin) * 2);
+ block-size: var(--footer-height);
display: grid;
- inset-block: auto var(--tray-margin);
+ inset-block: auto 0;
inline-size: var(--tray-size);
position: fixed;
z-index: var(--z-tray);
@@ -25,6 +21,15 @@
grid-column-start: 1;
grid-row-start: 1;
}
+
+ @media (max-width: 799px) {
+ &:has(.tray__dialog[open]) {
+ background-color: var(--color-terminal-bg);
+ inline-size: calc(100% - var(--tray-margin) * 2);
+ inset-inline-start: var(--tray-margin);
+ z-index: calc(var(--z-tray) + 2);
+ }
+ }
}
/* Dialog
@@ -40,22 +45,22 @@
transition: var(--tray-duration) var(--tray-timing-function);
transition-property: background-color, box-shadow, inset-block-end;
- &:not([open]) {
- block-size: var(--footer-height);
- pointer-events: none;
- }
-
&[open] {
border-radius: var(--tray-radius);
box-shadow:
0 0 0 1px var(--color-ink-lighter),
0 0 16px oklch(var(--lch-black) / 33%);
- inset-block-end: calc(var(--footer-height) - var(--tray-margin));
+ inset-block-end: var(--footer-height);
overflow: hidden;
}
+
+ &:not([open]) {
+ block-size: var(--footer-height);
+ pointer-events: none;
+ }
}
- /* Expander & Actions
+ /* Expander
/* ------------------------------------------------------------------------ */
.tray__expander {
@@ -65,15 +70,50 @@
align-self: stretch;
background: transparent;
border: 0;
- margin-block: calc(-1 * var(--tray-margin));
+ display: grid;
+ place-content: center;
z-index: calc(var(--z-tray) + 1);
- .tray__dialog[open] ~ &,
- .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & {
+ .icon {
+ color: var(--color-white);
display: none;
}
+
+ .tray__dialog[open] ~ & {
+ display: none;
+ }
+
+ /* On mobile, add an icon to the expander button */
+ @media (max-width: 799px) {
+ inline-size: var(--footer-height);
+
+ .icon {
+ display: block;
+ }
+
+ /* Show a red dot if there are items to show */
+ .tray__dialog:has(.tray__item:not(.tray__item--overflow)) ~ &:after {
+ background: oklch(var(--lch-red-medium));
+ block-size: 1ch;
+ border-radius: 50%;
+ content: "";
+ inline-size: 1ch;
+ inset: 25% 25% auto auto;
+ position: absolute;
+ }
+ }
+
+ /* On desktop, hide if there aren't any items to show */
+ @media (min-width: 800px) {
+ .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & {
+ display: none
+ }
+ }
}
+ /* Actions
+ /* ------------------------------------------------------------------------ */
+
.tray__actions {
--hover-size: 0;
@@ -88,12 +128,6 @@
transition: translate var(--tray-duration) var(--tray-timing-function);
translate: 0 var(--footer-height);
- .tray__dialog[open] ~ &,
- .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & {
- opacity: 1;
- translate: 0 0;
- }
-
/* Get the circle buttons to be full-height without magic numbers */
form {
aspect-ratio: 1;
@@ -113,6 +147,19 @@
}
}
+ .tray__dialog[open] ~ & {
+ opacity: 1;
+ translate: 0 0;
+ }
+
+ /* On desktop, show actions when there aren't items */
+ @media (min-width: 800px) {
+ .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & {
+ opacity: 1;
+ translate: 0 0;
+ }
+ }
+
@media (prefers-color-scheme: dark) {
.btn--reversed {
color: var(--color-ink);
@@ -136,14 +183,18 @@
.tray__dialog & {
font-size: 10px;
+ margin-block-end: var(--tray-item-margin);
transition: var(--tray-duration) var(--tray-timing-function);
transition-delay: var(--tray-item-delay);
transition-property: margin, scale;
z-index: var(--tray-item-z);
+ &:first-child {
+ --tray-item-margin: var(--tray-margin);
+ }
+
&:not(:first-child) {
scale: var(--tray-item-scale);
- margin-block-end: var(--tray-item-margin);
}
&:nth-child(1) { --tray-item-index: 1; }
@@ -163,6 +214,12 @@
--tray-item-scale: 1;
}
+ .tray__dialog:not([open]) & {
+ @media (max-width: 799px) {
+ opacity: 0;
+ }
+ }
+
.bubble {
display: none;
}
@@ -183,6 +240,7 @@
justify-content: center;
}
+ /* Only show when there are 7+ items */
.tray__dialog:has(.tray__item:nth-child(7)) & {
display: flex;
}
@@ -238,21 +296,12 @@
}
}
- /* Pins tray
+ /* Pin-specific styles
/* ------------------------------------------------------------------------ */
.tray--pins {
inset-inline: var(--tray-margin) auto;
- /* Don't expand if there's only one pin */
- .tray__dialog:has(.tray__item:only-child) {
- pointer-events: unset;
-
- ~ .tray__expander {
- display: none;
- }
- }
-
.tray__item {
--tray-item-z: calc(10 - var(--tray-item-index));
@@ -308,9 +357,38 @@
.card__bubble {
display: none;
}
+
+ /* On mobile… */
+ @media (max-width: 799px) {
+ /* …add a border */
+ .tray__expander {
+ border-inline-end: 1px dashed oklch(var(--lch-white) / 50%);
+ translate: calc(-1 * var(--tray-margin)) 0;
+ }
+
+ /* …and disable the expander if there aren't items to show */
+ .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ .tray__expander {
+ pointer-events: none;
+
+ .icon {
+ opacity: 0.5;
+ }
+ }
+ }
+
+ /* On desktop, don't expand if there's only one pin */
+ @media (min-width: 800px) {
+ .tray__dialog:has(.tray__item:only-child) {
+ pointer-events: unset;
+
+ ~ .tray__expander {
+ display: none;
+ }
+ }
+ }
}
- /* Notifications tray
+ /* Notification-specific styles
/* ------------------------------------------------------------------------ */
.tray--notifications {
@@ -334,5 +412,19 @@
.card__notification-meta {
font-size: var(--text-x-small);
}
+
+ /* On mobile… */
+ @media (max-width: 799px) {
+ /* …add a border */
+ .tray__expander {
+ border-inline-start: 1px dashed oklch(var(--lch-white) / 50%);
+ translate: var(--tray-margin) 0;
+ }
+
+ /* …and hide the dialog if there aren't items to show */
+ .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) {
+ display: none;
+ }
+ }
}
}
diff --git a/app/views/my/pins/_tray.html.erb b/app/views/my/pins/_tray.html.erb
index 955f34003..615b61e96 100644
--- a/app/views/my/pins/_tray.html.erb
+++ b/app/views/my/pins/_tray.html.erb
@@ -12,5 +12,7 @@
-
+
diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb
index 03faacab3..ad5275251 100644
--- a/app/views/notifications/_tray.html.erb
+++ b/app/views/notifications/_tray.html.erb
@@ -23,6 +23,7 @@
<%= link_to tag.span("Notifications"), notifications_path,
class: "btn btn--reversed borderless fill-transparent center txt-uppercase txt-x-small full-width",
+ title: "See all notifications",
data: { action: "click->dialog#close" } %>
<%= link_to settings_notifications_path,
@@ -33,5 +34,7 @@
<% end %>
-
+