@adamarant/designsystem 0.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +101 -0
  2. package/dist/designsystem.css +13494 -0
  3. package/dist/designsystem.js +67 -0
  4. package/dist/designsystem.min.css +2 -0
  5. package/package.json +111 -0
  6. package/src/base/index.css +2 -0
  7. package/src/base/reset.css +119 -0
  8. package/src/base/typography.css +172 -0
  9. package/src/components/accordion.css +166 -0
  10. package/src/components/admin-layout.css +371 -0
  11. package/src/components/alert.css +159 -0
  12. package/src/components/avatar.css +109 -0
  13. package/src/components/badge.css +80 -0
  14. package/src/components/bottom-nav.css +125 -0
  15. package/src/components/bottom-sheet.css +146 -0
  16. package/src/components/breadcrumb.css +102 -0
  17. package/src/components/button.css +250 -0
  18. package/src/components/card.css +117 -0
  19. package/src/components/chip.css +79 -0
  20. package/src/components/collapsible.css +112 -0
  21. package/src/components/color-picker.css +82 -0
  22. package/src/components/combobox.css +420 -0
  23. package/src/components/command.css +210 -0
  24. package/src/components/context-menu.css +162 -0
  25. package/src/components/copy-button.css +106 -0
  26. package/src/components/custom-select.css +446 -0
  27. package/src/components/datepicker.css +301 -0
  28. package/src/components/description-list.css +100 -0
  29. package/src/components/divider.css +66 -0
  30. package/src/components/drawer.css +234 -0
  31. package/src/components/drop-zone.css +166 -0
  32. package/src/components/dropdown.css +169 -0
  33. package/src/components/empty-state.css +75 -0
  34. package/src/components/field.css +112 -0
  35. package/src/components/gallery.css +257 -0
  36. package/src/components/hero.css +111 -0
  37. package/src/components/icon-btn.css +103 -0
  38. package/src/components/index.css +74 -0
  39. package/src/components/input.css +311 -0
  40. package/src/components/kbd.css +54 -0
  41. package/src/components/media-library.css +230 -0
  42. package/src/components/modal.css +136 -0
  43. package/src/components/nav.css +198 -0
  44. package/src/components/number-input.css +163 -0
  45. package/src/components/pagination.css +175 -0
  46. package/src/components/pin-input.css +136 -0
  47. package/src/components/popover.css +111 -0
  48. package/src/components/progress.css +217 -0
  49. package/src/components/prose.css +337 -0
  50. package/src/components/result.css +80 -0
  51. package/src/components/scroll-area.css +73 -0
  52. package/src/components/search.css +311 -0
  53. package/src/components/segmented-control.css +94 -0
  54. package/src/components/skeleton.css +100 -0
  55. package/src/components/slider.css +133 -0
  56. package/src/components/sortable.css +70 -0
  57. package/src/components/spinner.css +60 -0
  58. package/src/components/star-rating.css +121 -0
  59. package/src/components/stat-card.css +44 -0
  60. package/src/components/table.css +359 -0
  61. package/src/components/tabs.css +215 -0
  62. package/src/components/tag.css +188 -0
  63. package/src/components/timeline.css +130 -0
  64. package/src/components/toast.css +90 -0
  65. package/src/components/toggle.css +173 -0
  66. package/src/components/toolbar.css +206 -0
  67. package/src/components/tooltip.css +167 -0
  68. package/src/components/truncated-text.css +75 -0
  69. package/src/index.css +21 -0
  70. package/src/js/theme.js +67 -0
  71. package/src/tokens/colors.css +256 -0
  72. package/src/tokens/index.css +11 -0
  73. package/src/tokens/shadows.css +55 -0
  74. package/src/tokens/spacing.css +82 -0
  75. package/src/tokens/tokens.json +413 -0
  76. package/src/tokens/typography.css +90 -0
  77. package/src/utilities/a11y.css +102 -0
  78. package/src/utilities/index.css +7 -0
  79. package/src/utilities/interactive.css +121 -0
  80. package/src/utilities/layout.css +273 -0
  81. package/src/utilities/sizing.css +85 -0
  82. package/src/utilities/spacing.css +204 -0
  83. package/src/utilities/states.css +182 -0
  84. package/src/utilities/text.css +381 -0
@@ -0,0 +1,215 @@
1
+ /* ==========================================================================
2
+ Component: Tabs
3
+ Horizontal/vertical tab navigation with pill, small, and full-width variants.
4
+
5
+ ARIA requirements (consumer responsibility):
6
+ - Tab list: role="tablist", aria-label="[description]"
7
+ - Tab: role="tab", aria-selected="true|false", aria-controls="[panel-id]"
8
+ - Tab panel: role="tabpanel", id matching aria-controls, aria-labelledby="[tab-id]"
9
+ - Keyboard: ArrowLeft/Right (horizontal) or ArrowUp/Down (vertical) to navigate
10
+ - Active tab: only the active tab should be in tab order (tabindex="0"), others tabindex="-1"
11
+ ========================================================================== */
12
+
13
+ .ds-tabs {
14
+ display: flex;
15
+ flex-direction: row;
16
+ align-items: stretch;
17
+ border-block-end: 1px solid var(--ds-color-border);
18
+ gap: var(--ds-space-0);
19
+
20
+ /* --- Pill variant --- */
21
+
22
+ &--pills {
23
+ border-block-end: none;
24
+ gap: var(--ds-space-1);
25
+ background-color: var(--ds-color-surface-muted);
26
+ border-radius: var(--ds-radius-lg);
27
+ padding: var(--ds-space-1);
28
+
29
+ & .ds-tab {
30
+ border-block-end: none;
31
+ border-radius: var(--ds-radius-md);
32
+ padding: var(--ds-space-1-5) var(--ds-space-3);
33
+ margin-block-end: 0;
34
+
35
+ @media (hover: hover) {
36
+ &:hover {
37
+ background-color: var(--ds-color-surface-hover);
38
+ }
39
+ }
40
+
41
+ &--active,
42
+ &--active:hover {
43
+ background-color: var(--ds-color-surface-elevated);
44
+ color: var(--ds-color-text);
45
+ box-shadow: var(--ds-shadow-sm);
46
+ border-block-end: none;
47
+ }
48
+ }
49
+ }
50
+
51
+ /* --- Pills flat variant (pills without container background) --- */
52
+
53
+ &--pills-flat {
54
+ border-block-end: none;
55
+ align-items: center;
56
+ gap: var(--ds-space-1);
57
+ background: none;
58
+ padding: 0;
59
+
60
+ & .ds-tab {
61
+ border-block-end: none;
62
+ border-radius: var(--ds-radius-md);
63
+ padding: var(--ds-space-1-5) var(--ds-space-3);
64
+ margin-block-end: 0;
65
+
66
+ @media (hover: hover) {
67
+ &:hover {
68
+ background-color: var(--ds-color-surface-hover);
69
+ }
70
+ }
71
+
72
+ &--active,
73
+ &--active:hover {
74
+ background-color: var(--ds-color-surface);
75
+ color: var(--ds-color-text);
76
+ box-shadow: var(--ds-shadow-sm);
77
+ border-block-end: none;
78
+ }
79
+ }
80
+ }
81
+
82
+ /* --- Vertical variant --- */
83
+
84
+ &--vertical {
85
+ flex-direction: column;
86
+ border-block-end: none;
87
+ border-inline-end: 1px solid var(--ds-color-border);
88
+ gap: var(--ds-space-0-5);
89
+
90
+ & .ds-tab {
91
+ border-block-end: none;
92
+ border-inline-end: 2px solid transparent;
93
+ padding: var(--ds-space-2) var(--ds-space-4);
94
+ text-align: start;
95
+
96
+ &--active {
97
+ border-block-end: none;
98
+ border-inline-end-color: var(--ds-color-interactive);
99
+ color: var(--ds-color-text);
100
+ }
101
+ }
102
+ }
103
+
104
+ /* --- Small variant --- */
105
+
106
+ &--sm .ds-tab {
107
+ padding: var(--ds-space-1-5) var(--ds-space-3);
108
+ font-size: var(--ds-text-xs);
109
+ }
110
+
111
+ /* --- Large variant --- */
112
+
113
+ &--lg .ds-tab {
114
+ padding: var(--ds-space-3) var(--ds-space-5);
115
+ font-size: var(--ds-text-base);
116
+ }
117
+
118
+ /* --- Full width variant --- */
119
+
120
+ &--full {
121
+ width: 100%;
122
+
123
+ & .ds-tab {
124
+ flex: 1;
125
+ justify-content: center;
126
+ }
127
+ }
128
+ }
129
+
130
+ /* --- Individual Tab --- */
131
+
132
+ .ds-tab {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ gap: var(--ds-space-2);
136
+ padding: var(--ds-space-2) var(--ds-space-4);
137
+ font-family: var(--ds-font-sans);
138
+ font-size: var(--ds-text-sm);
139
+ font-weight: var(--ds-weight-medium);
140
+ line-height: var(--ds-leading-snug);
141
+ color: var(--ds-color-text-secondary);
142
+ cursor: pointer;
143
+ border-block-end: 2px solid transparent;
144
+ background: none;
145
+ border-block-start: none;
146
+ border-inline-start: none;
147
+ border-inline-end: none;
148
+ white-space: nowrap;
149
+ transition: all var(--ds-duration-fast) var(--ds-ease-default);
150
+ margin-block-end: -1px;
151
+
152
+ @media (hover: hover) {
153
+ &:hover {
154
+ color: var(--ds-color-text);
155
+ }
156
+ }
157
+
158
+ &:focus-visible {
159
+ outline: none;
160
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
161
+ border-radius: var(--ds-radius-sm);
162
+ scroll-margin-block: var(--ds-space-16, 4rem);
163
+ }
164
+
165
+ &--active {
166
+ color: var(--ds-color-text);
167
+ border-block-end-color: var(--ds-color-interactive);
168
+ }
169
+
170
+ &:disabled,
171
+ &[aria-disabled="true"] {
172
+ opacity: var(--ds-opacity-disabled);
173
+ cursor: not-allowed;
174
+ pointer-events: none;
175
+ }
176
+
177
+ /* --- Tab Icon --- */
178
+
179
+ &__icon {
180
+ display: inline-flex;
181
+ align-items: center;
182
+ justify-content: center;
183
+ width: 1rem;
184
+ height: 1rem;
185
+ flex-shrink: 0;
186
+ color: currentColor;
187
+ }
188
+
189
+ /* --- Tab Count Badge --- */
190
+
191
+ &__count {
192
+ display: inline-flex;
193
+ align-items: center;
194
+ justify-content: center;
195
+ padding: var(--ds-space-0) var(--ds-space-1-5);
196
+ font-size: var(--ds-text-xs);
197
+ font-weight: var(--ds-weight-medium);
198
+ line-height: var(--ds-leading-snug);
199
+ color: var(--ds-color-text-tertiary);
200
+ background-color: var(--ds-color-surface-muted);
201
+ border-radius: var(--ds-radius-full);
202
+ min-width: 1.25rem;
203
+ }
204
+
205
+ &--active &__count {
206
+ color: var(--ds-color-text-secondary);
207
+ background-color: var(--ds-color-surface-elevated);
208
+ }
209
+ }
210
+
211
+ /* --- Tab Panel --- */
212
+
213
+ .ds-tab-panel {
214
+ padding-block-start: var(--ds-space-5);
215
+ }
@@ -0,0 +1,188 @@
1
+ /* ==========================================================================
2
+ Tag / Chip Component
3
+ ==========================================================================
4
+ Interactive, optionally removable tag for categorisation and filtering.
5
+
6
+ ARIA requirements (consumer responsibility):
7
+ - Remove button: add aria-label="Remove [tag name]"
8
+ - Selectable tags (as <button>): use aria-pressed="true|false"
9
+ - Tag list: wrap in role="list" with aria-label
10
+
11
+ Usage:
12
+ <span class="ds-tag">Default</span>
13
+ <span class="ds-tag ds-tag--success">Approved</span>
14
+ <span class="ds-tag ds-tag--removable">
15
+ Removable
16
+ <button class="ds-tag__remove" aria-label="Remove">&times;</button>
17
+ </span>
18
+ ========================================================================== */
19
+
20
+ /* ---------------------------------------------------------------------------
21
+ Base
22
+ --------------------------------------------------------------------------- */
23
+
24
+ .ds-tag {
25
+ display: inline-flex;
26
+ align-items: center;
27
+ gap: var(--ds-space-1);
28
+ padding: var(--ds-space-1) var(--ds-space-2-5, 0.625rem);
29
+ font-size: var(--ds-text-xs);
30
+ font-weight: var(--ds-weight-medium);
31
+ font-family: var(--ds-font-sans);
32
+ line-height: var(--ds-leading-none);
33
+ border-radius: var(--ds-radius-full);
34
+ background-color: var(--ds-color-surface-muted);
35
+ border: 1px solid var(--ds-color-border);
36
+ color: var(--ds-color-text-secondary);
37
+ white-space: nowrap;
38
+ transition:
39
+ border-color var(--ds-duration-fast) var(--ds-ease-out),
40
+ background-color var(--ds-duration-fast) var(--ds-ease-out);
41
+
42
+ &:hover {
43
+ border-color: var(--ds-color-border-hover);
44
+ }
45
+
46
+ /* ---------------------------------------------------------------------------
47
+ Color variants — subtle background + vivid text + subtle border
48
+ --------------------------------------------------------------------------- */
49
+
50
+ &--primary {
51
+ background-color: var(--ds-color-interactive-subtle, var(--ds-color-surface-muted));
52
+ color: var(--ds-color-interactive);
53
+ border-color: var(--ds-color-interactive-border, var(--ds-color-interactive));
54
+ }
55
+
56
+ &--success {
57
+ background-color: var(--ds-color-success-subtle, var(--ds-color-surface-muted));
58
+ color: var(--ds-color-success);
59
+ border-color: var(--ds-color-success-border, var(--ds-color-success));
60
+ }
61
+
62
+ &--warning {
63
+ background-color: var(--ds-color-warning-subtle, var(--ds-color-surface-muted));
64
+ color: var(--ds-color-warning);
65
+ border-color: var(--ds-color-warning-border, var(--ds-color-warning));
66
+ }
67
+
68
+ &--error {
69
+ background-color: var(--ds-color-error-subtle, var(--ds-color-surface-muted));
70
+ color: var(--ds-color-error);
71
+ border-color: var(--ds-color-error-border, var(--ds-color-error));
72
+ }
73
+
74
+ &--info {
75
+ background-color: var(--ds-color-info-subtle, var(--ds-color-surface-muted));
76
+ color: var(--ds-color-info);
77
+ border-color: var(--ds-color-info-border, var(--ds-color-info));
78
+ }
79
+
80
+ &--purple {
81
+ background-color: var(--ds-color-accent-purple-subtle, var(--ds-color-surface-muted));
82
+ color: var(--ds-color-accent-purple, var(--ds-color-interactive));
83
+ border-color: var(--ds-color-accent-purple-border, var(--ds-color-accent-purple, var(--ds-color-interactive)));
84
+ }
85
+
86
+ /* ---------------------------------------------------------------------------
87
+ Removable — tighter right padding for the close button
88
+ --------------------------------------------------------------------------- */
89
+
90
+ &--removable {
91
+ padding-inline-end: var(--ds-space-1);
92
+ }
93
+
94
+ /* ---------------------------------------------------------------------------
95
+ Remove button
96
+ --------------------------------------------------------------------------- */
97
+
98
+ &__remove {
99
+ display: inline-flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ width: 1rem;
103
+ height: 1rem;
104
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
105
+ min-height: 1.5rem;
106
+ padding: 0;
107
+ border: none;
108
+ border-radius: var(--ds-radius-full);
109
+ background: transparent;
110
+ color: currentColor;
111
+ font-size: inherit;
112
+ line-height: var(--ds-leading-none);
113
+ opacity: 0.6;
114
+ cursor: pointer;
115
+ transition:
116
+ opacity var(--ds-duration-fast) var(--ds-ease-out),
117
+ background-color var(--ds-duration-fast) var(--ds-ease-out);
118
+ -webkit-appearance: none;
119
+ appearance: none;
120
+
121
+ &:hover {
122
+ opacity: 1;
123
+ background-color: var(--ds-color-surface-hover);
124
+ }
125
+
126
+ &:focus-visible {
127
+ outline: none;
128
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
129
+ opacity: 1;
130
+ }
131
+ }
132
+
133
+ /* ---------------------------------------------------------------------------
134
+ Variant: Outline
135
+ --------------------------------------------------------------------------- */
136
+
137
+ &--outline {
138
+ background-color: transparent;
139
+ }
140
+
141
+ /* ---------------------------------------------------------------------------
142
+ Variant: Inverted — uses the theme-swapping inverted token pair so the
143
+ tag reads as dark-on-light in light mode and light-on-dark in dark mode.
144
+ --------------------------------------------------------------------------- */
145
+
146
+ &--inverted {
147
+ background-color: var(--ds-color-inverted);
148
+ color: var(--ds-color-on-inverted);
149
+ border-color: var(--ds-color-inverted);
150
+
151
+ &:hover {
152
+ border-color: var(--ds-color-inverted);
153
+ }
154
+ }
155
+
156
+ /* ---------------------------------------------------------------------------
157
+ Size: Small
158
+ --------------------------------------------------------------------------- */
159
+
160
+ &--sm {
161
+ padding: var(--ds-space-0-5, 0.125rem) var(--ds-space-2, 0.5rem);
162
+ font-size: var(--ds-text-2xs);
163
+
164
+ &.ds-tag--removable {
165
+ padding-inline-end: var(--ds-space-0-5, 0.125rem);
166
+ }
167
+ }
168
+
169
+ /* ---------------------------------------------------------------------------
170
+ Size: Large
171
+ --------------------------------------------------------------------------- */
172
+
173
+ &--lg {
174
+ padding: var(--ds-space-1-5, 0.375rem) var(--ds-space-3);
175
+ font-size: var(--ds-text-sm);
176
+
177
+ &.ds-tag--removable {
178
+ padding-inline-end: var(--ds-space-1-5, 0.375rem);
179
+ }
180
+ }
181
+ }
182
+
183
+ /* Tags used as <button> for selection — no focus ring on click */
184
+ .ds-tag:focus-visible {
185
+ outline: none;
186
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
187
+ scroll-margin-block: var(--ds-space-16, 4rem);
188
+ }
@@ -0,0 +1,130 @@
1
+ /* ==========================================================================
2
+ Timeline
3
+ ==========================================================================
4
+ Vertical timeline component for roadmaps, activity feeds, and step-based
5
+ flows. Each item has a dot indicator on a vertical line with support for
6
+ completed, current, and error states.
7
+
8
+ Usage:
9
+ <div class="ds-timeline">
10
+ <div class="ds-timeline__item ds-timeline__item--completed">
11
+ <div class="ds-timeline__dot"></div>
12
+ <div class="ds-timeline__content">
13
+ <div class="ds-timeline__title">Step one</div>
14
+ <div class="ds-timeline__description">Details here.</div>
15
+ <div class="ds-timeline__time">2 hours ago</div>
16
+ </div>
17
+ </div>
18
+ </div>
19
+
20
+ Modifiers:
21
+ .ds-timeline__item--completed — Green dot (success)
22
+ .ds-timeline__item--current — Inverted dot (active)
23
+ .ds-timeline__item--error — Red dot (error)
24
+ .ds-timeline--compact — Tighter spacing, smaller dots
25
+ ========================================================================== */
26
+
27
+ .ds-timeline {
28
+ position: relative;
29
+ padding-inline-start: var(--ds-space-8);
30
+
31
+ /* Vertical line */
32
+ &::before {
33
+ content: "";
34
+ position: absolute;
35
+ inset-inline-start: 0.9rem;
36
+ inset-block-start: 0;
37
+ inset-block-end: 0;
38
+ width: 2px;
39
+ background-color: var(--ds-color-border);
40
+ }
41
+
42
+ /* Item */
43
+ &__item {
44
+ position: relative;
45
+ padding-block-end: var(--ds-space-6);
46
+
47
+ &:last-child {
48
+ padding-block-end: 0;
49
+ }
50
+
51
+ /* Dot state: completed */
52
+ &--completed .ds-timeline__dot {
53
+ background-color: var(--ds-color-success);
54
+ border-color: var(--ds-color-success);
55
+ }
56
+
57
+ /* Dot state: current */
58
+ &--current .ds-timeline__dot {
59
+ background-color: var(--ds-color-inverted);
60
+ border-color: var(--ds-color-inverted);
61
+ }
62
+
63
+ /* Dot state: error */
64
+ &--error .ds-timeline__dot {
65
+ background-color: var(--ds-color-error);
66
+ border-color: var(--ds-color-error);
67
+ }
68
+ }
69
+
70
+ /* Dot */
71
+ &__dot {
72
+ position: absolute;
73
+ inset-inline-start: calc(-1 * var(--ds-space-8) + 0.5rem);
74
+ width: 1rem;
75
+ height: 1rem;
76
+ border-radius: var(--ds-radius-full);
77
+ background-color: var(--ds-color-surface-muted);
78
+ border: 2px solid var(--ds-color-border);
79
+ z-index: 1;
80
+ }
81
+
82
+ /* Content area */
83
+ &__content {
84
+ /* no additional layout needed; flows naturally after the dot */
85
+ }
86
+
87
+ /* Title */
88
+ &__title {
89
+ font-size: var(--ds-text-sm);
90
+ font-weight: var(--ds-weight-medium);
91
+ color: var(--ds-color-text);
92
+ }
93
+
94
+ /* Description */
95
+ &__description {
96
+ font-size: var(--ds-text-sm);
97
+ color: var(--ds-color-text-secondary);
98
+ margin-block-start: var(--ds-space-1);
99
+ }
100
+
101
+ /* Timestamp */
102
+ &__time {
103
+ font-size: var(--ds-text-xs);
104
+ color: var(--ds-color-text-tertiary);
105
+ margin-block-start: var(--ds-space-0-5);
106
+ }
107
+
108
+ /* Compact variant */
109
+ &--compact {
110
+ padding-inline-start: var(--ds-space-6);
111
+
112
+ &::before {
113
+ inset-inline-start: 0.6rem;
114
+ }
115
+
116
+ & .ds-timeline__item {
117
+ padding-block-end: var(--ds-space-4);
118
+
119
+ &:last-child {
120
+ padding-block-end: 0;
121
+ }
122
+ }
123
+
124
+ & .ds-timeline__dot {
125
+ inset-inline-start: calc(-1 * var(--ds-space-6) + 0.25rem);
126
+ width: 0.75rem;
127
+ height: 0.75rem;
128
+ }
129
+ }
130
+ }
@@ -0,0 +1,90 @@
1
+ /* ==========================================================================
2
+ Component: Toast
3
+
4
+ ARIA requirements (consumer responsibility):
5
+ - Container: role="status", aria-live="polite" (or role="alert" for errors)
6
+ - Close button: aria-label="Dismiss notification"
7
+ - Auto-dismiss: provide enough time (minimum 5s), or let user control
8
+ - Toast region: wrap container in aria-label="Notifications"
9
+ ========================================================================== */
10
+
11
+ .ds-toast-container {
12
+ position: fixed;
13
+ z-index: var(--ds-z-toast);
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--ds-space-2);
17
+ padding: var(--ds-space-4);
18
+ pointer-events: none;
19
+
20
+ &--top-right { inset-block-start: 0; inset-inline-end: 0; }
21
+ &--bottom-right { inset-block-end: 0; inset-inline-end: 0; }
22
+ &--bottom-center {
23
+ inset-block-end: 0; inset-inline-start: 50%;
24
+ transform: translateX(-50%);
25
+ align-items: center;
26
+ }
27
+ }
28
+
29
+ .ds-toast {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: var(--ds-space-3);
33
+ padding: var(--ds-space-3) var(--ds-space-4);
34
+ background-color: var(--ds-color-surface);
35
+ border: 1px solid var(--ds-color-border);
36
+ border-radius: var(--ds-radius-lg);
37
+ box-shadow: var(--ds-shadow-lg);
38
+ pointer-events: auto;
39
+ min-width: 18rem;
40
+ max-width: 28rem;
41
+ animation: ds-toast-in var(--ds-duration-slow) var(--ds-ease-out-expo) forwards;
42
+
43
+ &--info { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-info); }
44
+ &--success { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-success); }
45
+ &--warning { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-warning); }
46
+ &--error { border-inline-start: var(--ds-accent-border-width) solid var(--ds-color-error); }
47
+
48
+ &__message {
49
+ flex: 1;
50
+ font-size: var(--ds-text-sm);
51
+ color: var(--ds-color-text);
52
+ }
53
+
54
+ &__close {
55
+ color: var(--ds-color-text-tertiary);
56
+ padding: var(--ds-space-1);
57
+ border-radius: var(--ds-radius-sm);
58
+ transition: color var(--ds-duration-fast) var(--ds-ease-default);
59
+ min-width: 1.5rem; /* WCAG 2.5.8: minimum 24px target */
60
+ min-height: 1.5rem;
61
+
62
+ &:hover {
63
+ color: var(--ds-color-text);
64
+ }
65
+
66
+ &:focus-visible {
67
+ outline: none;
68
+ box-shadow: 0 0 0 var(--ds-ring-width) var(--ds-ring-color);
69
+ scroll-margin-block: var(--ds-space-16, 4rem);
70
+ }
71
+ }
72
+
73
+ &--exit {
74
+ animation: ds-toast-out var(--ds-duration-normal) var(--ds-ease-default) forwards;
75
+ }
76
+ }
77
+
78
+ @keyframes ds-toast-in {
79
+ from { opacity: 0; transform: translateY(-8px); }
80
+ to { opacity: 1; transform: translateY(0); }
81
+ }
82
+
83
+ @keyframes ds-toast-out {
84
+ to { opacity: 0; transform: translateX(100%); }
85
+ }
86
+
87
+ @media (prefers-reduced-motion: reduce) {
88
+ .ds-toast { animation: none; }
89
+ .ds-toast--exit { animation: none; opacity: 0; }
90
+ }