Mercurial
diff design_system/src/styles/components.css @ 252:7a7581f040e8
[ui] Add scoped notification component
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 04 Aug 2026 11:57:16 -0700 |
| parents | 117c4d53c9a4 |
| children | fdf3816959cb |
line wrap: on
line diff
--- a/design_system/src/styles/components.css Tue Aug 04 09:14:57 2026 -0700 +++ b/design_system/src/styles/components.css Tue Aug 04 11:57:16 2026 -0700 @@ -1,4 +1,11 @@ -:where(zen-button, zen-card, zen-alert, zen-field, zen-stack) { +:where( + zen-button, + zen-card, + zen-alert, + zen-field, + zen-stack, + zen-notifications +) { box-sizing: border-box; font-family: var(--zen-font-sans); color: var(--zen-color-text); @@ -198,6 +205,136 @@ zen-stack[gap="tight"] { --zen-stack-gap: var(--zen-space-2); } zen-stack[gap="loose"] { --zen-stack-gap: var(--zen-space-6); } +zen-notifications > [data-zen-notification-stack] { + position: fixed; + z-index: var(--zen-notification-z-index, 1000); + inset-inline-end: var(--zen-notification-inset, var(--zen-space-4)); + inset-block-end: var( + --zen-notification-bottom-inset, + var(--zen-space-4) + ); + display: grid; + inline-size: min(24rem, calc(100vi - 2rem)); + gap: var(--zen-space-3); + pointer-events: none; +} + +zen-notifications > [data-zen-notification-stack] > article { + display: grid; + grid-template-columns: 1.75rem minmax(0, 1fr) 2rem; + align-items: start; + gap: var(--zen-space-3); + padding: var(--zen-space-4); + border: var(--zen-border-width) solid var(--zen-color-border); + border-radius: var(--zen-radius-lg); + box-shadow: var(--zen-shadow-md); + background: var(--zen-color-surface-raised); + color: var(--zen-color-text); + pointer-events: auto; + animation: zen-notification-enter 160ms ease-out; +} + +.zen-notification-tone { + display: grid; + width: 1.75rem; + height: 1.75rem; + place-items: center; + border-radius: 50%; + background: var(--zen-color-info); + color: var(--zen-color-on-info); + font-weight: 900; +} + +[data-tone="success"] > .zen-notification-tone { + background: var(--zen-color-success); + color: var(--zen-color-on-success); +} + +[data-tone="warning"] > .zen-notification-tone { + background: var(--zen-color-warning); + color: var(--zen-color-on-warning); +} + +[data-tone="error"] > .zen-notification-tone { + background: var(--zen-color-danger); + color: var(--zen-color-on-danger); +} + +.zen-notification-content { + display: grid; + gap: var(--zen-space-1); +} + +.zen-notification-message, +.zen-notification-description { + margin: 0; +} + +.zen-notification-message { + font-weight: 800; +} + +.zen-notification-description { + color: var(--zen-color-text-muted); + font-size: var(--zen-font-size-sm); +} + +.zen-notification-action, +.zen-notification-dismiss { + border: 0; + background: transparent; + color: inherit; + cursor: pointer; +} + +.zen-notification-action { + justify-self: start; + margin-top: var(--zen-space-2); + padding: 0; + color: var(--zen-color-info); + font-weight: 800; + text-decoration: underline; + text-underline-offset: 0.2em; +} + +.zen-notification-dismiss { + width: 2rem; + height: 2rem; + padding: 0; + border-radius: 50%; + font-size: 1.25rem; +} + +.zen-notification-action:focus-visible, +.zen-notification-dismiss:focus-visible { + outline: 3px solid var(--zen-color-focus); + outline-offset: 2px; +} + +.zen-visually-hidden { + position: absolute; + width: 1px; + height: 1px; + overflow: hidden; + clip: rect(0 0 0 0); + clip-path: inset(50%); + white-space: nowrap; +} + +@keyframes zen-notification-enter { + from { + opacity: 0; + transform: translateY(0.75rem); + } +} + +@media (forced-colors: active) { + zen-notifications > [data-zen-notification-stack] > article, + .zen-notification-tone { + border: 1px solid CanvasText; + } +} + @media (prefers-reduced-motion: reduce) { zen-button > :where(button, a), zen-card > :where(article, section) { @@ -207,4 +344,8 @@ zen-button[loading] > :where(button, a)::before { animation-duration: 1400ms; } + + zen-notifications > [data-zen-notification-stack] > article { + animation: none; + } }