572 lines
13 KiB
CSS
572 lines
13 KiB
CSS
@layer components {
|
|
/* Container
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray {
|
|
--tray-duration: 350ms;
|
|
--tray-margin: 0.5rem;
|
|
--tray-radius: 0.25rem;
|
|
--tray-item-height: 76px; /* FIXME: Magic number */
|
|
|
|
align-items: end;
|
|
block-size: var(--footer-height);
|
|
display: grid;
|
|
inset-block: auto env(safe-area-inset-bottom);
|
|
inline-size: var(--tray-size);
|
|
position: fixed;
|
|
transition: inset var(--tray-duration) var(--ease-out-overshoot-subtle);
|
|
z-index: var(--z-tray);
|
|
|
|
/* Make the dialog, expander, and actions inhabit the same space */
|
|
> * {
|
|
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
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.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(--ease-out-overshoot-subtle);
|
|
transition-property: background-color, box-shadow, inset-block-end;
|
|
|
|
&[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) - 0.75ch);
|
|
}
|
|
|
|
&:not([open]) {
|
|
block-size: var(--footer-height);
|
|
pointer-events: none;
|
|
|
|
/* On desktop, when there aren't items, tweak the hat so it doesn't look
|
|
like it's coming from the bottom of the viewport */
|
|
@media (min-width: 800px) {
|
|
&:not(:has(.tray__item--notification)) {
|
|
.tray__item--hat {
|
|
margin-block-end: 0;
|
|
opacity: 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Expander
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray__toggle {
|
|
align-self: stretch;
|
|
background: none;
|
|
border: 0;
|
|
display: block;
|
|
padding: 0;
|
|
transition: opacity 100ms ease-out;
|
|
|
|
.icon {
|
|
color: var(--color-ink);
|
|
display: none;
|
|
}
|
|
|
|
.tray__toggle-text {
|
|
display: contents;
|
|
}
|
|
|
|
@media (max-width: 799px) {
|
|
/* When collapsed on mobile, make it small */
|
|
.tray__dialog:not([open]) ~ & {
|
|
inline-size: var(--footer-height);
|
|
|
|
.tray__toggle-btn {
|
|
border: 0;
|
|
}
|
|
|
|
.icon {
|
|
display: block;
|
|
}
|
|
|
|
.tray__toggle-text {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
/* Show a red dot if there are items to show */
|
|
.tray__dialog:not([open]):has(.tray__item--notification) ~ &: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… */
|
|
@media (min-width: 800px) {
|
|
.tray__dialog:not([open]):has(.tray__item:not(.tray__item--hat)) ~ & {
|
|
block-size: var(--tray-item-height);
|
|
translate: 0 -1.85rem;
|
|
}
|
|
|
|
/* Hide the UI when collapsed, but only if there are items */
|
|
.tray__dialog:not([open]):has(.tray__item--notification) ~ & {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
.tray__toggle-btn {
|
|
--btn-background: transparent;
|
|
--btn-border-size: 0;
|
|
--btn-color: var(--color-ink);
|
|
|
|
inline-size: 100%;
|
|
opacity: 0.66;
|
|
}
|
|
|
|
/* Item
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray__item {
|
|
--tray-item-delay: calc((var(--tray-item-index) - 1) * 20ms);
|
|
--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-z: calc(6 - var(--tray-item-index));
|
|
|
|
position: relative;
|
|
|
|
.tray__dialog & {
|
|
font-size: 10px;
|
|
margin-block-end: var(--tray-item-margin);
|
|
transition: var(--tray-duration) var(--ease-out-overshoot-subtle);
|
|
transition-delay: var(--tray-item-delay);
|
|
transition-property: margin, opacity, scale;
|
|
|
|
|
|
&:not(.tray__item--hat) {
|
|
z-index: var(--tray-item-z);
|
|
}
|
|
|
|
&:has(*:focus-visible) {
|
|
z-index: calc(var(--tray-item-z) + 1);
|
|
}
|
|
|
|
&:first-child {
|
|
--tray-item-margin: var(--tray-margin);
|
|
}
|
|
|
|
&:not(:first-child) {
|
|
scale: var(--tray-item-scale);
|
|
}
|
|
|
|
&: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-margin: 0;
|
|
--tray-item-scale: 1;
|
|
}
|
|
|
|
.tray__dialog:not([open]) & {
|
|
@media (max-width: 799px) {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
|
|
.bubble {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
.tray__item--hat {
|
|
--tray-hat-bg: var(--color-canvas);
|
|
--tray-item-scale: 1;
|
|
|
|
background-color: var(--tray-hat-bg);
|
|
border-block-end: 1px solid var(--color-ink-lighter);
|
|
border-radius: var(--tray-radius) var(--tray-radius) 0 0;
|
|
block-size: var(--tray-item-height);
|
|
display: flex;
|
|
opacity: 0;
|
|
padding: 0.5ch;
|
|
|
|
.btn {
|
|
--btn-background: var(--tray-hat-bg);
|
|
--btn-border-radius: 0.5ch;
|
|
--btn-padding: 1.25ch 0.5ch 1ch;
|
|
|
|
block-size: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
font-weight: normal;
|
|
gap: 0.25ch;
|
|
inline-size: 100%;
|
|
|
|
&:focus-visible {
|
|
z-index: 1;
|
|
}
|
|
|
|
@media (max-width: 1060px) {
|
|
> span:not(.icon) {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
.tray__dialog:not([open]) & {
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
> *:is(:first-child, :last-child) {
|
|
inline-size: 128px;
|
|
}
|
|
|
|
.tray__dialog[open] & {
|
|
opacity: 1;
|
|
}
|
|
|
|
.tray__new-notifications {
|
|
display: none;
|
|
position: relative;
|
|
}
|
|
|
|
.tray__dialog:has(.tray__item:nth-child(1n + 7)) & {
|
|
.tray__old-notifications { display: none; }
|
|
.tray__new-notifications { display: flex; }
|
|
|
|
.btn:has(.tray__new-notifications) { /* Red dot */
|
|
&:after {
|
|
background-color: oklch(var(--lch-red-medium));
|
|
block-size: 1ch;
|
|
border-radius: 50%;
|
|
box-shadow: 0 0 0 1px var(--tray-hat-bg);
|
|
content: "";
|
|
inline-size: 1ch;
|
|
inset: 25% auto auto 50%;
|
|
position: absolute;
|
|
translate: 25% -75%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Tray cards
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray {
|
|
.card {
|
|
--card-padding-block: 1.5ch;
|
|
--card-padding-inline: 1.5ch;
|
|
--text-xx-large: 2em;
|
|
|
|
block-size: var(--tray-item-height);
|
|
view-transition-name: unset !important;
|
|
|
|
[open] & {
|
|
box-shadow: 0 0 0 1px var(--color-ink-lighter);
|
|
border: 0;
|
|
border-radius: 0;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
box-shadow: 0 0 0 1px var(--color-ink-lighter);
|
|
}
|
|
}
|
|
|
|
.card__background {
|
|
display: none;
|
|
}
|
|
|
|
.card__body {
|
|
margin-block-start: 0.2em;
|
|
padding-block-end: 0;
|
|
}
|
|
|
|
.card__board {
|
|
padding-block: 0.25ch;
|
|
}
|
|
|
|
.card__title {
|
|
--lines: 1;
|
|
|
|
font-size: var(--text-small);
|
|
font-weight: bold;
|
|
min-block-size: 0;
|
|
}
|
|
}
|
|
|
|
/* Pin-specific styles
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray--pins {
|
|
inset-inline: var(--tray-margin) auto;
|
|
view-transition-name: tray-pins;
|
|
|
|
#footer:has(.bar__placeholder[hidden]) & {
|
|
inset-inline-start: -100%;
|
|
}
|
|
|
|
.tray__item {
|
|
--tray-item-z: calc(10 - var(--tray-item-index));
|
|
|
|
position: relative;
|
|
|
|
[open] &[aria-selected] {
|
|
outline: 0;
|
|
z-index: calc(var(--tray-item-z) + 2);
|
|
|
|
.card__link {
|
|
border-radius: 0.25ch;
|
|
outline: var(--focus-ring-size) solid var(--focus-ring-color);
|
|
outline-offset: var(--focus-ring-offset);
|
|
z-index: 1;
|
|
}
|
|
}
|
|
|
|
/* Show 6 max items on smallest devices */
|
|
@media (max-height: 578px) {
|
|
&:nth-child(1n + 7) { display: none; }
|
|
}
|
|
|
|
/* 7 max */
|
|
@media (min-height: 578px) and (max-height: 656px) {
|
|
&:nth-child(1n + 8) { display: none; }
|
|
}
|
|
|
|
/* 8 max */
|
|
@media (min-height: 656px) and (max-height: 734px) {
|
|
&:nth-child(1n + 9) { display: none; }
|
|
}
|
|
|
|
/* 9 max */
|
|
@media (min-height: 734px) and (max-height: 812px) {
|
|
&:nth-child(1n + 10) { display: none; }
|
|
}
|
|
|
|
/* 10 max on larger screens */
|
|
@media (min-height: 812px) {
|
|
&:nth-child(1n + 11) { display: none; }
|
|
}
|
|
|
|
&:not([aria-selected]) .card__link:focus-visible,
|
|
.tray__dialog:not([open]) & .card__link:focus-visible {
|
|
--focus-ring-size: 0;
|
|
}
|
|
}
|
|
|
|
.tray__remove-pin-btn {
|
|
--btn-icon-size: 1.25em;
|
|
--btn-size: 2em;
|
|
|
|
background-color: var(--card-bg-color);
|
|
inset: 0 0 auto auto;
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
position: absolute;
|
|
z-index: 1;
|
|
|
|
.tray__dialog[open] & {
|
|
opacity: 0.66;
|
|
pointer-events: unset;
|
|
|
|
&:hover {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
.avatar,
|
|
.card__tags,
|
|
.card__meta .btn,
|
|
.card__meta-text:not(.card__meta-text--updated),
|
|
.card__stages,
|
|
.card__steps,
|
|
.card__closed {
|
|
display: none;
|
|
}
|
|
|
|
.card__header {
|
|
margin-block-start: calc(var(--card-padding-block) * -1.1);
|
|
margin-inline: calc(-1 * var(--card-padding-inline));
|
|
max-inline-size: unset;
|
|
}
|
|
|
|
.card__body {
|
|
display: block;
|
|
margin-block-start: 0.3em;
|
|
}
|
|
|
|
.card__column-name--current {
|
|
--btn-padding: 0.1em 0.5em;
|
|
|
|
background: none !important;
|
|
border: 1px solid currentColor;
|
|
color: var(--color-ink);
|
|
display: inline-flex;
|
|
flex: 0 1 auto;
|
|
inline-size: fit-content;
|
|
margin: 0 0 0 auto;
|
|
transition: translate 150ms ease-out;
|
|
|
|
[open] & {
|
|
translate: -2em;
|
|
}
|
|
}
|
|
|
|
.card__link {
|
|
z-index: 1;
|
|
}
|
|
|
|
.card__footer {
|
|
margin-block: -0.2em 2em;
|
|
|
|
.icon { display: none; }
|
|
}
|
|
|
|
.card__meta {
|
|
grid-template-areas: "text-updated";
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.card__meta-text {
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.card__meta-text--updated {
|
|
border: 0;
|
|
font-size: var(--text-x-small);
|
|
opacity: 0.66;
|
|
padding: 0;
|
|
text-transform: none;
|
|
|
|
.local-time-value {
|
|
font-weight: inherit;
|
|
}
|
|
}
|
|
|
|
.card__bubble {
|
|
display: none;
|
|
}
|
|
|
|
/* Disable the expander if there aren't items to show */
|
|
.tray__dialog:not(:has(.tray__item)) ~ .tray__toggle {
|
|
opacity: 0.5;
|
|
|
|
&, .tray__toggle-btn {
|
|
pointer-events: none;
|
|
}
|
|
}
|
|
|
|
/* Add a border on mobile */
|
|
@media (max-width: 799px) {
|
|
.tray__dialog:not([open]) ~ .tray__toggle {
|
|
border-inline-end: 1px dashed var(--color-ink-light);
|
|
translate: calc(-1 * var(--tray-margin)) 0;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
::view-transition-group(tray-pins) {
|
|
z-index: 100;
|
|
}
|
|
|
|
/* Notification-specific styles
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
.tray--notifications {
|
|
inset-inline: auto var(--tray-margin);
|
|
view-transition-name: tray-notifications;
|
|
|
|
#footer:has(.bar__placeholder[hidden]) & {
|
|
inset-inline-end: -100%;
|
|
}
|
|
|
|
.tray__item,
|
|
[data-navigable-list-target~=item] {
|
|
[open] &[aria-selected] {
|
|
outline: 0;
|
|
z-index: calc(var(--tray-item-z) + 2);
|
|
|
|
.card,
|
|
.tray__item--hat & .btn {
|
|
border-radius: 0.25ch;
|
|
outline: var(--focus-ring-size) solid var(--focus-ring-color);
|
|
outline-offset: var(--focus-ring-offset);
|
|
}
|
|
}
|
|
|
|
&:nth-child(1n + 7) {
|
|
display: none;
|
|
pointer-events: none;
|
|
visibility: hidden;
|
|
}
|
|
|
|
&:not([aria-selected]) .card:focus-visible,
|
|
.tray__dialog:not([open]) & .card:focus-visible {
|
|
--focus-ring-size: 0;
|
|
}
|
|
|
|
.btn:focus-visible {
|
|
outline: 0;
|
|
}
|
|
}
|
|
|
|
&:not(:has(.card--notification)) {
|
|
.tray__notification-read-action {
|
|
visibility: hidden;
|
|
}
|
|
}
|
|
|
|
.card__notification-unread-indicator {
|
|
--btn-icon-size: 1.25em;
|
|
--btn-size: 2em;
|
|
}
|
|
|
|
/* On mobile… */
|
|
@media (max-width: 799px) {
|
|
/* …add a border */
|
|
.tray__dialog:not([open]) ~ .tray__toggle {
|
|
border-inline-start: 1px dashed var(--color-ink-light);
|
|
translate: var(--tray-margin) 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
::view-transition-group(tray-notifications) {
|
|
z-index: 100;
|
|
}
|
|
}
|