From 9a9cb3340bb602098875da074a7dee24512545e7 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 22 May 2025 11:01:17 -0500 Subject: [PATCH 1/4] WIP --- app/assets/stylesheets/trays.css | 10 ++++------ app/views/layouts/application.html.erb | 2 +- app/views/my/pins/_tray.html.erb | 17 ++++++++++------- app/views/notifications/_tray.html.erb | 22 ++++++++++++---------- 4 files changed, 27 insertions(+), 24 deletions(-) diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index 24399ffc4..ab0872b56 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -59,6 +59,10 @@ &:nth-child(4) { --tray-item-index: 4; } &:nth-child(5) { --tray-item-index: 5; } &:nth-child(6) { --tray-item-index: 6; } + &:nth-child(7) { --tray-item-index: 7; } + &:nth-child(8) { --tray-item-index: 8; } + &:nth-child(9) { --tray-item-index: 9; } + &:nth-child(10) { --tray-item-index: 10; } .tray[open] & { --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-item-height) - var(--footer-height)); @@ -202,16 +206,11 @@ /* ------------------------------------------------------------------------ */ .tray--pins { - /* inset: auto auto var(--block-space-half) var(--inline-space); */ inset-inline: var(--inline-space) auto; .tray__item { --tray-item-z: calc(10 - var(--tray-item-index)); - &:nth-child(7) { --tray-item-index: 7; } - &:nth-child(8) { --tray-item-index: 8; } - &:nth-child(9) { --tray-item-index: 9; } - &:nth-child(10) { --tray-item-index: 10; } &:nth-child(1n + 11) { display: none; } } @@ -270,7 +269,6 @@ /* ------------------------------------------------------------------------ */ .tray--notifications { - /* inset: auto var(--inline-space) var(--block-space-half) auto; */ inset-inline: auto var(--inline-space); .tray__item:nth-child(1n + 7) { diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ba86f92e4..0e04cbca9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -48,9 +48,9 @@ <% if Current.user && !@hide_footer_frames %> <% end %> diff --git a/app/views/my/pins/_tray.html.erb b/app/views/my/pins/_tray.html.erb index 297dd12c8..b05e65239 100644 --- a/app/views/my/pins/_tray.html.erb +++ b/app/views/my/pins/_tray.html.erb @@ -1,13 +1,16 @@ <%= turbo_stream_from Current.user, :pins_tray %> -<%= tag.dialog id: "pin-tray", class: "tray tray--pins", - data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" } do %> - <%= turbo_frame_tag "pins", src: my_pins_path %> +
+ <%= tag.dialog id: "pin-tray", class: "tray__dialog", + data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" } do %> + <%= turbo_frame_tag "pins", src: my_pins_path %> + <% end %>
- +
- -<% end %> + +
diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 17b869af0..749e1bdc5 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,15 +1,17 @@ <%= turbo_stream_from Current.user, :notifications %> - - <%= turbo_frame_tag "notifications", src: tray_notifications_path, refresh: "morph" %> +
+ + <%= turbo_frame_tag "notifications", src: tray_notifications_path, refresh: "morph" %> -
- <%= link_to notifications_path, class: "card", data: { action: "click->dialog#close" } do %> - + More… - <% end %> -
+
+ <%= link_to notifications_path, class: "card", data: { action: "click->dialog#close" } do %> + + More… + <% end %> +
+
<%= button_to read_all_notifications_path, @@ -26,4 +28,4 @@
-
+ From a22c69bbc3756bbc052825c3442b5cc15eacb317 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 22 May 2025 12:30:15 -0500 Subject: [PATCH 2/4] Relative positioning for trays --- app/assets/stylesheets/reset.css | 14 ++ app/assets/stylesheets/trays.css | 202 ++++++++++-------- .../controllers/dialog_controller.js | 6 + app/views/my/pins/_tray.html.erb | 4 +- app/views/notifications/_tray.html.erb | 4 +- 5 files changed, 134 insertions(+), 96 deletions(-) diff --git a/app/assets/stylesheets/reset.css b/app/assets/stylesheets/reset.css index 1e0daadcc..039c14d90 100644 --- a/app/assets/stylesheets/reset.css +++ b/app/assets/stylesheets/reset.css @@ -67,6 +67,10 @@ font: inherit; } + button { + cursor: pointer; + } + /* Remove all animations and transitions for people that prefer not to see them */ @media (prefers-reduced-motion: reduce) { @@ -83,4 +87,14 @@ scroll-behavior: initial; } } + + dialog { + border: 0; + padding: 0; + + &:where(:focus-visible):focus, + &:where(:focus-visible):active { + outline: 0; + } + } } diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index d1d327381..05dd26acc 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -3,106 +3,97 @@ } @layer components { - .tray { - --tray-item-duration: 350ms; - --tray-item-height: 76px; /* FIXME: Magic number */ - --tray-item-offset: var(--block-space); - --tray-bottom-padding: var(--block-space-half); + /* Container + /* ------------------------------------------------------------------------ */ - background-color: transparent; - block-size: var(--footer-height); - border: 0; - display: flex; - flex-direction: column; + .tray { + --tray-action-z: 11; + --tray-bottom-padding: var(--block-space-half); + --tray-padding: var(--inline-space); + --tray-duration: 350ms; + --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-padding) * 2); + display: grid; + inset-block: auto var(--tray-padding); inline-size: var(--tray-size); - inset-block: auto 0; - justify-content: center; - padding: 0; position: fixed; z-index: var(--z-tray); - &:where(:focus-visible):focus, - &:where(:focus-visible):active { - outline: 0; + /* Make the dialog, expander, and actions inhabit the same space */ + > * { + grid-column-start: 1; + grid-row-start: 1; + } + } + + /* Dialog + /* ------------------------------------------------------------------------ */ + + .tray__dialog { + background-color: transparent; + display: flex; + flex-direction: column-reverse; + inline-size: auto; + inset: auto 0 0 0; + position: absolute; + 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; } - :where(.tray__item) { - --tray-item-delay: calc((var(--tray-item-index) - 1) * 10ms); - --tray-item-y: calc((var(--tray-item-index) - 1) * (var(--tray-item-offset) * -1) - var(--tray-bottom-padding)); - --tray-item-index: 1; - --tray-item-scale: calc(1 - var(--tray-item-index) / 30); - --tray-item-z: calc(6 - var(--tray-item-index)); + &[open] { + border-radius: var(--tray-radius); + box-shadow: 0 0 16px oklch(var(--lch-black) / 33%); + inset-block-end: calc(var(--footer-height) - var(--tray-padding)); + overflow: hidden; + } + } - display: flex; - font-size: 10px; - inline-size: var(--tray-size); - inset: auto 0 0; - outline: 0; - pointer-events: none; - position: absolute; /* tmp fix; ideally should remove the position-relative class from tray__item */ - scale: var(--tray-item-scale); - transform: translateY(var(--tray-item-y)); - transform-origin: center; - transition: - border-radius var(--tray-item-duration), - box-shadow var(--tray-item-duration), - scale var(--tray-item-duration), - transform var(--tray-item-duration); - transition-delay: var(--tray-item-delay); - transition-timing-function: cubic-bezier(0.25, 1.25, 0.5, 1); - z-index: var(--tray-item-z); - container-type: inline-size; + /* Expander & Actions + /* ------------------------------------------------------------------------ */ - &:nth-child(1) { --tray-item-index: 1; } - &:nth-child(2) { --tray-item-index: 2; } - &:nth-child(3) { --tray-item-index: 3; } - &:nth-child(4) { --tray-item-index: 4; } - &:nth-child(5) { --tray-item-index: 5; } - &:nth-child(6) { --tray-item-index: 6; } - &:nth-child(7) { --tray-item-index: 7; } - &:nth-child(8) { --tray-item-index: 8; } - &:nth-child(9) { --tray-item-index: 9; } - &:nth-child(10) { --tray-item-index: 10; } + .tray__expander { + --hover-size: 0; + --outline-size: 0; - .tray[open] & { - --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-item-height) - var(--footer-height)); - --tray-item-scale: 1; + align-self: stretch; + background: transparent; + border: 0; + margin-block: calc(-1 * var(--tray-padding)); + z-index: var(--tray-action-z); - pointer-events: unset; - } - - .tray:has(.tray__item:only-child) & { - pointer-events: unset; - } + .tray__dialog[open] ~ &, + .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ &, + .tray__dialog:has(.tray__item:not(.tray__item--overflow):only-child) ~ & { + display: none; } } .tray__actions { --hover-size: 0; + align-self: center; align-items: stretch; border: 1px dashed color-mix(in srgb, var(--color-white) 40%, var(--color-ink)); border-radius: 0.5em; color: var(--color-ink-inverted); display: flex; gap: var(--inline-space-half); - justify-content: space-between; opacity: 0; - scale: calc(1 - 1 / 30); - transform: translateY(100%); - transition: opacity 0.2s ease-out, scale 0.2s ease-out, transform 0.2s ease-out; + transition: translate var(--tray-duration) var(--tray-timing-function); + translate: 0 var(--footer-height); + z-index: var(--tray-action-z); - .tray[open] & { + .tray__dialog[open] ~ &, + .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & { opacity: 1; - scale: 1; - transform: translateY(0); - } - - .tray:not(:has(.tray__item:not(.tray__item--overflow))) & { - opacity: 1; - scale: 1; - transform: none; - transition: none; + translate: 0 0; } /* Get the circle buttons to be full-height without magic numbers */ @@ -131,22 +122,49 @@ } } - .tray__expander { - --hover-size: 0; - --outline-size: 0; + /* Item + /* ------------------------------------------------------------------------ */ - background-color: transparent; - block-size: var(--tray-item-height); - border: 0; - cursor: pointer; - inset: auto 0 0 0; - padding: 0; - position: absolute; + .tray__item { + --tray-item-delay: calc((var(--tray-item-index) - 1) * 20ms); + --tray-item-height: 76px; /* FIXME: Magic number */ + --tray-item-index: 1; + --tray-item-margin: calc(-1 * var(--tray-item-height) + var(--tray-item-offset)); + --tray-item-offset: var(--block-space-half); /* The amount they overlap */ + --tray-item-scale: calc(1 - (var(--tray-item-index) - 1) / 30); + --tray-item-y: calc((var(--tray-item-index) - 1) * (var(--tray-item-offset) * -1) - var(--tray-bottom-padding)); + --tray-item-z: calc(6 - var(--tray-item-index)); - .tray[open] &, - .tray:not(:has(.tray__item)) &, - .tray:has(.tray__item:only-child) & { - display: none; + position: relative; + + .tray__dialog & { + font-size: 10px; + transition: var(--tray-duration) var(--tray-timing-function); + transition-delay: var(--tray-item-delay); + transition-property: margin, scale; + z-index: var(--tray-item-z); + + &:not(:first-child) { + scale: var(--tray-item-scale); + margin-block-end: var(--tray-item-margin); + } + + &:nth-child(1) { --tray-item-index: 1; } + &:nth-child(2) { --tray-item-index: 2; } + &:nth-child(3) { --tray-item-index: 3; } + &:nth-child(4) { --tray-item-index: 4; } + &:nth-child(5) { --tray-item-index: 5; } + &:nth-child(6) { --tray-item-index: 6; } + &:nth-child(7) { --tray-item-index: 7; } + &:nth-child(8) { --tray-item-index: 8; } + &:nth-child(9) { --tray-item-index: 9; } + &:nth-child(10) { --tray-item-index: 10; } + } + + .tray__dialog[open] & { + --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-item-height) - var(--footer-height)); + --tray-item-margin: 0; + --tray-item-scale: 1; } } @@ -164,11 +182,11 @@ justify-content: center; } - .tray:has(.tray__item:nth-child(7)) & { + .tray__dialog:has(.tray__item:nth-child(7)) & { display: flex; } - .tray[open] & { + .tray__dialog[open] & { --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-bottom-padding)); --tray-item-scale: 1; @@ -224,7 +242,7 @@ /* ------------------------------------------------------------------------ */ .tray--pins { - inset-inline: var(--inline-space) auto; + inset-inline: var(--tray-padding) auto; .tray__item { --tray-item-z: calc(10 - var(--tray-item-index)); @@ -287,7 +305,7 @@ /* ------------------------------------------------------------------------ */ .tray--notifications { - inset-inline: auto var(--inline-space); + inset-inline: auto var(--tray-padding); .tray__item:nth-child(1n + 7) { display: none; diff --git a/app/javascript/controllers/dialog_controller.js b/app/javascript/controllers/dialog_controller.js index fd4d122e0..2092f9c9a 100644 --- a/app/javascript/controllers/dialog_controller.js +++ b/app/javascript/controllers/dialog_controller.js @@ -6,12 +6,18 @@ export default class extends Controller { modal: { type: Boolean, default: false } } + connect() { + console.log("connect") + } + open() { const modal = this.modalValue if (modal) { + console.log(modal) this.dialogTarget.showModal() } else { + console.log("NOT FOUND") this.dialogTarget.show() } } diff --git a/app/views/my/pins/_tray.html.erb b/app/views/my/pins/_tray.html.erb index b05e65239..955f34003 100644 --- a/app/views/my/pins/_tray.html.erb +++ b/app/views/my/pins/_tray.html.erb @@ -1,8 +1,8 @@ <%= turbo_stream_from Current.user, :pins_tray %> -
+
<%= tag.dialog id: "pin-tray", class: "tray__dialog", - data: { controller: "dialog", turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" } do %> + data: { turbo_permanent: true, dialog_modal_value: false, dialog_target: "dialog", action: "keydown.esc->dialog#close:stop click@document->dialog#closeOnClickOutside" } do %> <%= turbo_frame_tag "pins", src: my_pins_path %> <% end %> diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 9aa7ab726..0ff4ba6cb 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -1,8 +1,8 @@ <%= turbo_stream_from Current.user, :notifications %> -
+
<%= turbo_frame_tag "notifications", src: tray_notifications_path, refresh: "morph" %> From c3c5b38b84f5303af468c4feb7957549586e94f6 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 22 May 2025 13:36:20 -0500 Subject: [PATCH 3/4] Finishing touches --- app/assets/stylesheets/_global.css | 1 - app/assets/stylesheets/notifications.css | 6 ++++ app/assets/stylesheets/trays.css | 35 ++++++++----------- .../cards/display/common/_background.html.erb | 8 +++-- app/views/notifications/_tray.html.erb | 6 ++-- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/app/assets/stylesheets/_global.css b/app/assets/stylesheets/_global.css index 03e9fccc2..aad4508fc 100644 --- a/app/assets/stylesheets/_global.css +++ b/app/assets/stylesheets/_global.css @@ -41,7 +41,6 @@ --z-terminal: 20; --z-tray: 21; - /* OKLCH colors: Fixed */ --lch-black: 0% 0 0; --lch-white: 100% 0 0; diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index ec5034319..de22274ab 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -7,6 +7,12 @@ position: relative; } + .card { + @media (prefers-color-scheme: dark) { + box-shadow: 0 0 0 1px var(--color-ink-lighter); + } + } + &:has(.card--notification) { .notifications-list__empty-message { display: none; diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index 05dd26acc..2e1c6c108 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -7,17 +7,15 @@ /* ------------------------------------------------------------------------ */ .tray { - --tray-action-z: 11; - --tray-bottom-padding: var(--block-space-half); - --tray-padding: var(--inline-space); --tray-duration: 350ms; + --tray-margin: var(--inline-space); --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-padding) * 2); + block-size: calc(var(--footer-height) - var(--tray-margin) * 2); display: grid; - inset-block: auto var(--tray-padding); + inset-block: auto var(--tray-margin); inline-size: var(--tray-size); position: fixed; z-index: var(--z-tray); @@ -49,8 +47,10 @@ &[open] { border-radius: var(--tray-radius); - box-shadow: 0 0 16px oklch(var(--lch-black) / 33%); - inset-block-end: calc(var(--footer-height) - var(--tray-padding)); + 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)); overflow: hidden; } } @@ -65,8 +65,8 @@ align-self: stretch; background: transparent; border: 0; - margin-block: calc(-1 * var(--tray-padding)); - z-index: var(--tray-action-z); + margin-block: calc(-1 * var(--tray-margin)); + z-index: calc(var(--z-tray) + 1); .tray__dialog[open] ~ &, .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ &, @@ -80,7 +80,7 @@ align-self: center; align-items: stretch; - border: 1px dashed color-mix(in srgb, var(--color-white) 40%, var(--color-ink)); + border: 1px dashed oklch(var(--lch-white) / 50%); border-radius: 0.5em; color: var(--color-ink-inverted); display: flex; @@ -88,7 +88,6 @@ opacity: 0; transition: translate var(--tray-duration) var(--tray-timing-function); translate: 0 var(--footer-height); - z-index: var(--tray-action-z); .tray__dialog[open] ~ &, .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & { @@ -132,7 +131,6 @@ --tray-item-margin: calc(-1 * var(--tray-item-height) + var(--tray-item-offset)); --tray-item-offset: var(--block-space-half); /* The amount they overlap */ --tray-item-scale: calc(1 - (var(--tray-item-index) - 1) / 30); - --tray-item-y: calc((var(--tray-item-index) - 1) * (var(--tray-item-offset) * -1) - var(--tray-bottom-padding)); --tray-item-z: calc(6 - var(--tray-item-index)); position: relative; @@ -162,7 +160,6 @@ } .tray__dialog[open] & { - --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-item-height) - var(--footer-height)); --tray-item-margin: 0; --tray-item-scale: 1; } @@ -170,6 +167,7 @@ .tray__item--overflow { --tray-item-index: 7 !important; + --tray-item-z: 1; display: none; opacity: 0; @@ -187,11 +185,9 @@ } .tray__dialog[open] & { - --tray-item-y: calc(-100% * var(--tray-item-index) + var(--tray-bottom-padding)); --tray-item-scale: 1; opacity: 1; - pointer-events: unset; } } @@ -214,10 +210,7 @@ } @media (prefers-color-scheme: dark) { - &, - [open] & { - box-shadow: 0 0 0 1px var(--color-ink-light); - } + box-shadow: 0 0 0 1px var(--color-ink-lighter); } } @@ -242,7 +235,7 @@ /* ------------------------------------------------------------------------ */ .tray--pins { - inset-inline: var(--tray-padding) auto; + inset-inline: var(--tray-margin) auto; .tray__item { --tray-item-z: calc(10 - var(--tray-item-index)); @@ -305,7 +298,7 @@ /* ------------------------------------------------------------------------ */ .tray--notifications { - inset-inline: auto var(--tray-padding); + inset-inline: auto var(--tray-margin); .tray__item:nth-child(1n + 7) { display: none; diff --git a/app/views/cards/display/common/_background.html.erb b/app/views/cards/display/common/_background.html.erb index ac78ffa0b..cd7f996fe 100644 --- a/app/views/cards/display/common/_background.html.erb +++ b/app/views/cards/display/common/_background.html.erb @@ -1,6 +1,8 @@ -
- <%= image_tag card.image.presence || "", size: 120, data: { upload_preview_target: "image" } %> -
+<% if card.image.present? %> +
+ <%= image_tag card.image.presence || "", size: 120, data: { upload_preview_target: "image" } %> +
+<% end %> <% if card.closed? %>
diff --git a/app/views/notifications/_tray.html.erb b/app/views/notifications/_tray.html.erb index 0ff4ba6cb..03faacab3 100644 --- a/app/views/notifications/_tray.html.erb +++ b/app/views/notifications/_tray.html.erb @@ -15,18 +15,18 @@
<%= button_to read_all_notifications_path, - class: "tray__notification-read-action btn btn--reversed fill-transparent borderless flex-item-justify-start shadow txt-xx-small", + class: "tray__notification-read-action btn btn--reversed fill-transparent borderless flex-item-justify-start txt-xx-small", title: "Mark all as read", data: { action: "click->dialog#close", turbo_frame: "notifications" } do %> <%= icon_tag "check" %> <% end %> <%= link_to tag.span("Notifications"), notifications_path, - class: "btn btn--reversed borderless fill-transparent shadow center txt-uppercase txt-x-small full-width", + class: "btn btn--reversed borderless fill-transparent center txt-uppercase txt-x-small full-width", data: { action: "click->dialog#close" } %> <%= link_to settings_notifications_path, - class: "tray__notification-settings-action btn btn--reversed fill-transparent borderless flex-item-justify-start shadow txt-xx-small", + class: "tray__notification-settings-action btn btn--reversed fill-transparent borderless flex-item-justify-start txt-xx-small", title: "Notification settings", data: { action: "click->dialog#close" } do %> <%= icon_tag "settings" %> From d8ed61b08f336314d0dde7c837b90ded01f09c7f Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Thu, 22 May 2025 13:53:51 -0500 Subject: [PATCH 4/4] Handle single items better --- app/assets/stylesheets/trays.css | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index 2e1c6c108..947a4094a 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -69,8 +69,7 @@ z-index: calc(var(--z-tray) + 1); .tray__dialog[open] ~ &, - .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ &, - .tray__dialog:has(.tray__item:not(.tray__item--overflow):only-child) ~ & { + .tray__dialog:not(:has(.tray__item:not(.tray__item--overflow))) ~ & { display: none; } } @@ -237,6 +236,15 @@ .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));