@med-o/ui 0.0.0-stage → 0.3.0

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 (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/dist/index.d.ts +2237 -0
  4. package/dist/index.js +5119 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/styles.css +1 -0
  7. package/package.json +77 -4
  8. package/src/accordion/accordion.css +184 -0
  9. package/src/alert/alert.css +147 -0
  10. package/src/avatar/avatar.css +221 -0
  11. package/src/badge/badge.css +153 -0
  12. package/src/bottom-sheet/bottom-sheet.css +202 -0
  13. package/src/breadcrumbs/breadcrumbs.css +147 -0
  14. package/src/bulk-action-bar/bulk-action-bar.css +98 -0
  15. package/src/button/button.css +319 -0
  16. package/src/card/card.css +217 -0
  17. package/src/checkbox/choice.css +196 -0
  18. package/src/combobox/combobox.css +125 -0
  19. package/src/date-time/date-time.css +474 -0
  20. package/src/dialog/dialog.css +319 -0
  21. package/src/drawer/drawer.css +156 -0
  22. package/src/empty-state/empty-state.css +161 -0
  23. package/src/field/field.css +115 -0
  24. package/src/link/link.css +103 -0
  25. package/src/list/list.css +172 -0
  26. package/src/list-view/list-view.css +473 -0
  27. package/src/listbox/listbox.css +203 -0
  28. package/src/media/media.css +298 -0
  29. package/src/menu/menu.css +183 -0
  30. package/src/navigation/navigation.css +625 -0
  31. package/src/pagination/pagination.css +132 -0
  32. package/src/popover/popover.css +166 -0
  33. package/src/progress/progress.css +225 -0
  34. package/src/search/search.css +309 -0
  35. package/src/select/select.css +229 -0
  36. package/src/slider/slider.css +212 -0
  37. package/src/styles.css +48 -0
  38. package/src/switch/switch.css +160 -0
  39. package/src/table/table.css +286 -0
  40. package/src/tabs/tabs.css +211 -0
  41. package/src/tag/tag.css +225 -0
  42. package/src/text-field/input.css +206 -0
  43. package/src/toast/toast.css +184 -0
  44. package/src/toggle-button/toggle-button.css +143 -0
  45. package/src/tooltip/tooltip.css +66 -0
  46. package/src/upload/upload.css +380 -0
  47. package/src/utils/utilities.css +14 -0
@@ -0,0 +1,319 @@
1
+ /**
2
+ * Dialog – med.o Design System
3
+ *
4
+ * <div class="medo-dialog-overlay"> scrim, overlay/scrim, centers the dialog
5
+ * <div class="medo-dialog medo-dialog--md"> surface/raised, border, elevation/4, radius/lg
6
+ * <section class="medo-dialog__dialog" role="dialog" [data-scrolled]>
7
+ * <div class="medo-dialog__header"> heading (title + description) · close X </div>
8
+ * <div class="medo-dialog__body">…only this scrolls…</div>
9
+ * <div class="medo-dialog__footer"> Button group (footer) </div>
10
+ * </section>
11
+ * </div>
12
+ * </div>
13
+ * Sizes: sm 400 · md 560 · lg 720 · Alert dialog 400. Max height: viewport − 2 × 32.
14
+ * Fullscreen (mobile forms): .medo-dialog--fullscreen with .medo-dialog__bar (Cancel · title · action).
15
+ * Alert dialog: .medo-alert-dialog--{danger|warning|info} with .medo-alert-dialog__icon / __text.
16
+ * State contract: [data-entering] [data-exiting] on overlay and dialog (React Aria), [data-scrolled] on the section.
17
+ */
18
+
19
+ .medo-dialog-overlay {
20
+ position: fixed;
21
+ inset: 0;
22
+ z-index: var(--medo-layer-modal);
23
+ display: grid;
24
+ place-items: center;
25
+ padding: var(--medo-space-8);
26
+ background-color: var(--medo-color-overlay-scrim);
27
+ }
28
+
29
+ .medo-dialog {
30
+ --_width: 35rem; /* md 560 */
31
+
32
+ box-sizing: border-box;
33
+ display: flex;
34
+ flex-direction: column;
35
+ inline-size: min(var(--_width), 100%);
36
+ max-block-size: 100%;
37
+ overflow: hidden;
38
+ border: var(--medo-border-width-thin) solid var(--medo-color-border-default);
39
+ border-radius: var(--medo-radius-lg);
40
+ background-color: var(--medo-color-surface-raised);
41
+ box-shadow: var(--medo-shadow-elevation-4);
42
+ color: var(--medo-color-text-primary);
43
+ outline: none;
44
+ }
45
+
46
+ .medo-dialog--sm,
47
+ .medo-alert-dialog {
48
+ --_width: 25rem; /* 400 */
49
+ }
50
+ .medo-dialog--lg {
51
+ --_width: 45rem; /* 720 */
52
+ }
53
+
54
+ /* ---------- Motion: scrim fades, dialog scales 0.96 → 1 and fades ---------- */
55
+
56
+ /*
57
+ * Motion: the scrim fades, the dialog settles from 96 % with a smooth spring (fullscreen: slides up);
58
+ * out: everything fades quickly. Transitions – an interrupted open or close reverses smoothly.
59
+ * React Aria waits for the overlay's own transition, so the dialog's exit is never longer than the overlay's.
60
+ */
61
+ .medo-dialog-overlay {
62
+ transition: opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-enter);
63
+ }
64
+ .medo-dialog-overlay[data-entering] {
65
+ opacity: 0;
66
+ }
67
+ .medo-dialog-overlay[data-exiting] {
68
+ opacity: 0;
69
+ transition: opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-exit);
70
+ }
71
+ .medo-dialog {
72
+ transition:
73
+ scale var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth),
74
+ translate var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
75
+ }
76
+ .medo-dialog-overlay[data-entering] .medo-dialog {
77
+ scale: 0.96;
78
+ }
79
+ .medo-dialog-overlay[data-entering] .medo-dialog--fullscreen {
80
+ scale: none;
81
+ translate: 0 100%;
82
+ }
83
+ .medo-dialog-overlay[data-exiting] .medo-dialog {
84
+ scale: 0.98;
85
+ transition:
86
+ scale var(--medo-motion-duration-normal) var(--medo-motion-easing-exit),
87
+ translate var(--medo-motion-duration-normal) var(--medo-motion-easing-exit);
88
+ }
89
+ .medo-dialog-overlay[data-exiting] .medo-dialog--fullscreen {
90
+ scale: none;
91
+ translate: 0 100%;
92
+ }
93
+
94
+ /* ---------- Parts ---------- */
95
+
96
+ .medo-dialog__dialog {
97
+ display: flex;
98
+ flex: 1;
99
+ flex-direction: column;
100
+ min-block-size: 0;
101
+ outline: none;
102
+ }
103
+
104
+ .medo-dialog__header {
105
+ display: flex;
106
+ align-items: flex-start;
107
+ gap: var(--medo-space-4);
108
+ padding: var(--medo-space-6) var(--medo-space-4) var(--medo-space-4) var(--medo-space-6);
109
+ }
110
+
111
+ .medo-dialog__heading {
112
+ display: grid;
113
+ flex: 1;
114
+ gap: var(--medo-space-1);
115
+ min-inline-size: 0;
116
+ }
117
+
118
+ .medo-dialog__title {
119
+ margin: 0;
120
+ font: var(--medo-typography-heading-md);
121
+ color: var(--medo-color-text-primary);
122
+ }
123
+
124
+ .medo-dialog__description {
125
+ margin: 0;
126
+ font: var(--medo-typography-body-sm);
127
+ color: var(--medo-color-text-secondary);
128
+ }
129
+
130
+ .medo-dialog__body {
131
+ flex: 1;
132
+ min-block-size: 0;
133
+ overflow: auto;
134
+ overscroll-behavior: contain;
135
+ padding-inline: var(--medo-space-6);
136
+ font: var(--medo-typography-body-sm);
137
+ outline: none;
138
+ }
139
+
140
+ .medo-dialog__body:focus-visible {
141
+ box-shadow: var(--medo-shadow-focus-ring-inset);
142
+ }
143
+
144
+ /* Without a footer the body keeps the bottom padding. */
145
+ .medo-dialog__body:last-child {
146
+ padding-block-end: var(--medo-space-6);
147
+ }
148
+
149
+ .medo-dialog__footer {
150
+ padding: var(--medo-space-6);
151
+ }
152
+
153
+ /* Content too long: dividers keep title and actions apart from the scrolling body. */
154
+ .medo-dialog__dialog[data-scrolled] .medo-dialog__header {
155
+ border-block-end: var(--medo-border-width-thin) solid var(--medo-color-border-default);
156
+ }
157
+ .medo-dialog__dialog[data-scrolled] .medo-dialog__body {
158
+ padding-block: var(--medo-space-4);
159
+ }
160
+ .medo-dialog__dialog[data-scrolled] .medo-dialog__footer {
161
+ padding-block-start: var(--medo-space-4);
162
+ border-block-start: var(--medo-border-width-thin) solid var(--medo-color-border-default);
163
+ }
164
+
165
+ /* ---------- Fullscreen (mobile forms) ---------- */
166
+
167
+ .medo-dialog-overlay--fullscreen {
168
+ padding: 0;
169
+ }
170
+
171
+ .medo-dialog--fullscreen {
172
+ inline-size: 100%;
173
+ block-size: 100%;
174
+ border: 0;
175
+ border-radius: 0;
176
+ box-shadow: none;
177
+ padding-block-start: env(safe-area-inset-top);
178
+ padding-block-end: env(safe-area-inset-bottom);
179
+ }
180
+
181
+ .medo-dialog__bar {
182
+ display: grid;
183
+ grid-template-columns: 1fr auto 1fr;
184
+ align-items: center;
185
+ gap: var(--medo-space-2);
186
+ min-block-size: calc(var(--medo-size-control-md) + 2 * var(--medo-space-2)); /* 56 */
187
+ padding-inline: var(--medo-space-2);
188
+ border-block-end: var(--medo-border-width-thin) solid var(--medo-color-border-default);
189
+ }
190
+
191
+ .medo-dialog__bar > :first-child {
192
+ justify-self: start;
193
+ }
194
+ .medo-dialog__bar > :last-child {
195
+ justify-self: end;
196
+ }
197
+
198
+ .medo-dialog__bar-title {
199
+ min-inline-size: 0;
200
+ margin: 0;
201
+ overflow: hidden;
202
+ font: var(--medo-typography-label-lg);
203
+ text-align: center;
204
+ text-overflow: ellipsis;
205
+ white-space: nowrap;
206
+ }
207
+
208
+ .medo-dialog--fullscreen .medo-dialog__body,
209
+ .medo-dialog--fullscreen .medo-dialog__dialog[data-scrolled] .medo-dialog__body {
210
+ padding: var(--medo-space-4);
211
+ }
212
+
213
+ .medo-dialog--fullscreen .medo-dialog__body-inner,
214
+ .medo-dialog__sheet-body {
215
+ display: grid;
216
+ gap: var(--medo-space-4);
217
+ }
218
+
219
+ /* ---------- Bottom Sheet (short content on mobile) ---------- */
220
+
221
+ .medo-dialog__sheet-body {
222
+ padding: var(--medo-space-2) var(--medo-space-4) var(--medo-space-4);
223
+ font: var(--medo-typography-body-sm);
224
+ }
225
+
226
+ /* ---------- Alert dialog ---------- */
227
+
228
+ .medo-alert-dialog {
229
+ --_tone-bg: var(--medo-color-feedback-danger-surface);
230
+ --_tone-fg: var(--medo-color-feedback-danger-text);
231
+ }
232
+ .medo-alert-dialog--warning {
233
+ --_tone-bg: var(--medo-color-feedback-warning-surface);
234
+ --_tone-fg: var(--medo-color-feedback-warning-text);
235
+ }
236
+ .medo-alert-dialog--info {
237
+ --_tone-bg: var(--medo-color-feedback-info-surface);
238
+ --_tone-fg: var(--medo-color-feedback-info-text);
239
+ }
240
+
241
+ .medo-alert-dialog .medo-dialog__dialog {
242
+ gap: var(--medo-space-6);
243
+ padding: var(--medo-space-6);
244
+ }
245
+
246
+ .medo-alert-dialog__content {
247
+ display: flex;
248
+ align-items: flex-start;
249
+ gap: var(--medo-space-4);
250
+ }
251
+
252
+ .medo-alert-dialog__icon {
253
+ display: inline-grid;
254
+ flex: none;
255
+ place-items: center;
256
+ inline-size: var(--medo-space-10); /* 40 */
257
+ block-size: var(--medo-space-10);
258
+ border-radius: var(--medo-radius-full);
259
+ background-color: var(--_tone-bg);
260
+ color: var(--_tone-fg);
261
+ }
262
+
263
+ .medo-alert-dialog__icon > svg {
264
+ inline-size: var(--medo-size-icon-md);
265
+ block-size: var(--medo-size-icon-md);
266
+ }
267
+
268
+ .medo-alert-dialog__text {
269
+ display: grid;
270
+ flex: 1;
271
+ gap: var(--medo-space-2);
272
+ min-inline-size: 0;
273
+ }
274
+
275
+ .medo-alert-dialog__title {
276
+ margin: 0;
277
+ font: var(--medo-typography-heading-sm);
278
+ color: var(--medo-color-text-primary);
279
+ }
280
+
281
+ .medo-alert-dialog__description {
282
+ font: var(--medo-typography-body-sm);
283
+ color: var(--medo-color-text-secondary);
284
+ }
285
+
286
+ /* ---------- Mobile < 640 px (breakpoint/sm) ---------- */
287
+
288
+ @media (max-width: 639.98px) {
289
+ .medo-dialog-overlay {
290
+ padding: var(--medo-space-4);
291
+ }
292
+ .medo-dialog-overlay--fullscreen {
293
+ padding: 0;
294
+ }
295
+ /* Alert dialog: icon on top; the Button group stacks the buttons (main action on top). */
296
+ .medo-alert-dialog__content {
297
+ flex-direction: column;
298
+ }
299
+ }
300
+
301
+ @media (forced-colors: active) {
302
+ .medo-dialog {
303
+ border: 1px solid CanvasText;
304
+ }
305
+ .medo-alert-dialog__icon {
306
+ border: 1px solid CanvasText;
307
+ }
308
+ }
309
+
310
+ @media (prefers-reduced-motion: reduce) {
311
+ /* Reduced motion: only the cross-fade of the overlay. */
312
+ .medo-dialog-overlay {
313
+ transition: opacity var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
314
+ }
315
+ .medo-dialog-overlay:is([data-entering], [data-exiting]) .medo-dialog {
316
+ scale: none;
317
+ translate: none;
318
+ }
319
+ }
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Drawer – med.o Design System
3
+ *
4
+ * Modal panel from the side, full height. Same surface and behaviour as the Dialog.
5
+ * <div class="medo-drawer-overlay medo-drawer-overlay--right"> scrim, overlay/scrim
6
+ * <div class="medo-drawer medo-drawer--right medo-drawer--sm"> surface/raised, elevation/4, border + radius/lg on the free side
7
+ * <section class="medo-drawer__dialog" role="dialog">
8
+ * <div class="medo-drawer__header"> title (heading/md) · close </div>
9
+ * <div class="medo-drawer__body">…scrolls…</div>
10
+ * <div class="medo-drawer__footer"> Button group </div> optional
11
+ * </section>
12
+ * </div>
13
+ * </div>
14
+ * Sizes: sm 320 · md 400 · lg 560 · max viewport − 56 (the scrim strip shows a tap outside closes).
15
+ * State contract: [data-entering] [data-exiting] (React Aria), [data-dragging] while swiped.
16
+ */
17
+
18
+ .medo-drawer-overlay {
19
+ position: fixed;
20
+ inset: 0;
21
+ z-index: var(--medo-layer-modal);
22
+ display: flex;
23
+ justify-content: flex-end;
24
+ background-color: var(--medo-color-overlay-scrim);
25
+ }
26
+
27
+ .medo-drawer-overlay--left {
28
+ justify-content: flex-start;
29
+ }
30
+
31
+ .medo-drawer {
32
+ --_width: 20rem; /* sm 320 */
33
+ --_from: 100%;
34
+
35
+ box-sizing: border-box;
36
+ display: flex;
37
+ inline-size: min(var(--_width), 100vw - (var(--medo-space-12) + var(--medo-space-2))); /* viewport − 56 */
38
+ block-size: 100%;
39
+ border-start-start-radius: var(--medo-radius-lg);
40
+ border-end-start-radius: var(--medo-radius-lg);
41
+ border-inline-start: var(--medo-border-width-thin) solid var(--medo-color-border-default);
42
+ background-color: var(--medo-color-surface-raised);
43
+ box-shadow: var(--medo-shadow-elevation-4);
44
+ color: var(--medo-color-text-primary);
45
+ outline: none;
46
+ touch-action: pan-y;
47
+ /* Slides with a smooth spring – also back when a swipe is too short. */
48
+ transition: transform var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
49
+ }
50
+
51
+ /* Left: radius and border on the free (right) side. */
52
+ .medo-drawer--left {
53
+ --_from: -100%;
54
+ border-radius: 0;
55
+ border-inline-start: 0;
56
+ border-start-end-radius: var(--medo-radius-lg);
57
+ border-end-end-radius: var(--medo-radius-lg);
58
+ border-inline-end: var(--medo-border-width-thin) solid var(--medo-color-border-default);
59
+ }
60
+
61
+ .medo-drawer--md {
62
+ --_width: 25rem; /* 400 */
63
+ }
64
+ .medo-drawer--lg {
65
+ --_width: 35rem; /* 560 */
66
+ }
67
+
68
+ .medo-drawer[data-dragging] {
69
+ transition: none;
70
+ }
71
+
72
+ /* ---------- Motion: slide in from the side, scrim fades ---------- */
73
+
74
+ .medo-drawer-overlay {
75
+ transition: opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-enter);
76
+ }
77
+ .medo-drawer-overlay[data-entering] {
78
+ opacity: 0;
79
+ }
80
+ .medo-drawer-overlay[data-exiting] {
81
+ opacity: 0;
82
+ transition: opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-exit);
83
+ }
84
+ .medo-drawer-overlay[data-entering] .medo-drawer {
85
+ transform: translateX(var(--_from));
86
+ }
87
+ .medo-drawer-overlay[data-exiting] .medo-drawer {
88
+ transform: translateX(var(--_from));
89
+ transition: transform var(--medo-motion-duration-normal) var(--medo-motion-easing-exit);
90
+ }
91
+
92
+ /* ---------- Parts ---------- */
93
+
94
+ .medo-drawer__dialog {
95
+ display: flex;
96
+ flex: 1;
97
+ flex-direction: column;
98
+ min-inline-size: 0;
99
+ outline: none;
100
+ }
101
+
102
+ .medo-drawer__header {
103
+ display: flex;
104
+ flex: none;
105
+ align-items: center;
106
+ justify-content: space-between;
107
+ gap: var(--medo-space-2);
108
+ padding: var(--medo-space-4) var(--medo-space-3) var(--medo-space-4) var(--medo-space-6);
109
+ }
110
+
111
+ .medo-drawer__title {
112
+ display: flex;
113
+ flex: 1;
114
+ align-items: center;
115
+ min-inline-size: 0;
116
+ margin: 0;
117
+ font: var(--medo-typography-heading-md);
118
+ color: var(--medo-color-text-primary);
119
+ }
120
+
121
+ .medo-drawer__body {
122
+ flex: 1;
123
+ min-block-size: 0;
124
+ overflow: auto;
125
+ overscroll-behavior: contain;
126
+ /* A scroll container starts its own touch-action: keep horizontal drags for the swipe. */
127
+ touch-action: pan-y;
128
+ padding: var(--medo-space-2) var(--medo-space-4) var(--medo-space-4);
129
+ font: var(--medo-typography-body-sm);
130
+ }
131
+
132
+ .medo-drawer__footer {
133
+ flex: none;
134
+ padding: var(--medo-space-4) var(--medo-space-6) var(--medo-space-6);
135
+ padding-block-end: calc(var(--medo-space-6) + env(safe-area-inset-bottom));
136
+ border-block-start: var(--medo-border-width-thin) solid var(--medo-color-border-default);
137
+ }
138
+
139
+ @media (forced-colors: active) {
140
+ .medo-drawer {
141
+ border: 1px solid CanvasText;
142
+ }
143
+ }
144
+
145
+ @media (prefers-reduced-motion: reduce) {
146
+ /* Reduced motion: the panel fades with the scrim instead of sliding. */
147
+ .medo-drawer-overlay {
148
+ transition: opacity var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
149
+ }
150
+ .medo-drawer {
151
+ transition: none;
152
+ }
153
+ .medo-drawer-overlay:is([data-entering], [data-exiting]) .medo-drawer {
154
+ transform: none;
155
+ }
156
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Empty state – med.o Design System
3
+ *
4
+ * <section class="medo-empty-state medo-empty-state--page|section|inline" aria-labelledby="…">
5
+ * <span class="medo-icon-tile medo-icon-tile--lg medo-icon-tile--neutral" aria-hidden="true"><svg/></span>
6
+ * <div class="medo-empty-state__content"><h2 class="medo-empty-state__title">…</h2><p class="medo-empty-state__description">…</p></div>
7
+ * <div class="medo-empty-state__actions">…</div>
8
+ * </section>
9
+ * Page 480 · padding 48 · gap 16 · heading/md · body/md · Button md
10
+ * Section 400 · padding 32 · gap 12 · heading/sm · body/sm · Button sm
11
+ * Inline 320 · padding 24 · gap 8 · label/md · body/sm · Button sm
12
+ */
13
+
14
+ .medo-empty-state {
15
+ --_max: 30rem; /* 480 */
16
+ --_gap: var(--medo-space-4);
17
+
18
+ box-sizing: border-box;
19
+ display: flex;
20
+ flex-direction: column;
21
+ align-items: center;
22
+ gap: var(--_gap);
23
+ inline-size: 100%;
24
+ max-inline-size: var(--_max);
25
+ margin-inline: auto;
26
+ padding-block: var(--medo-space-12);
27
+ text-align: center;
28
+ }
29
+
30
+ .medo-empty-state--section {
31
+ --_max: 25rem; /* 400 */
32
+ --_gap: var(--medo-space-3);
33
+ padding-block: var(--medo-space-8);
34
+ }
35
+
36
+ .medo-empty-state--inline {
37
+ --_max: 20rem; /* 320 */
38
+ --_gap: var(--medo-space-2);
39
+ padding-block: var(--medo-space-6);
40
+ }
41
+
42
+ .medo-empty-state__content {
43
+ display: grid;
44
+ gap: var(--medo-space-1);
45
+ inline-size: 100%;
46
+ overflow-wrap: anywhere;
47
+ }
48
+
49
+ .medo-empty-state__title {
50
+ margin: 0;
51
+ font: var(--medo-typography-heading-md);
52
+ color: var(--medo-color-text-primary);
53
+ }
54
+
55
+ .medo-empty-state__description {
56
+ margin: 0;
57
+ font: var(--medo-typography-body-md);
58
+ color: var(--medo-color-text-secondary);
59
+ }
60
+
61
+ .medo-empty-state--section .medo-empty-state__title {
62
+ font: var(--medo-typography-heading-sm);
63
+ }
64
+
65
+ .medo-empty-state--inline .medo-empty-state__title {
66
+ font: var(--medo-typography-label-md);
67
+ }
68
+
69
+ .medo-empty-state:is(.medo-empty-state--section, .medo-empty-state--inline) .medo-empty-state__description {
70
+ font: var(--medo-typography-body-sm);
71
+ }
72
+
73
+ .medo-empty-state__actions {
74
+ display: flex;
75
+ flex-wrap: wrap;
76
+ align-items: center;
77
+ justify-content: center;
78
+ gap: var(--medo-space-2);
79
+ padding-block-start: var(--medo-space-2);
80
+ }
81
+
82
+ .medo-empty-state--inline .medo-empty-state__actions {
83
+ padding-block-start: 0;
84
+ }
85
+
86
+ /* Illustration slot: 240 × 160 · 160 × 120 · 120 × 88, radius/lg. */
87
+ .medo-empty-state__illustration {
88
+ display: block;
89
+ overflow: hidden;
90
+ inline-size: 15rem;
91
+ block-size: 10rem;
92
+ border-radius: var(--medo-radius-lg);
93
+ }
94
+
95
+ .medo-empty-state--section .medo-empty-state__illustration {
96
+ inline-size: 10rem;
97
+ block-size: 7.5rem;
98
+ }
99
+
100
+ .medo-empty-state--inline .medo-empty-state__illustration {
101
+ inline-size: 7.5rem;
102
+ block-size: 5.5rem;
103
+ }
104
+
105
+ .medo-empty-state__illustration > :is(img, svg) {
106
+ display: block;
107
+ inline-size: 100%;
108
+ block-size: 100%;
109
+ object-fit: contain;
110
+ }
111
+
112
+ /* ---------- Icon tile – sm 40/20 · md 48/24 · lg 64/32 ---------- */
113
+
114
+ .medo-icon-tile {
115
+ --_tile: var(--medo-size-control-lg);
116
+ --_icon: var(--medo-size-icon-lg);
117
+
118
+ display: inline-grid;
119
+ flex: none;
120
+ place-items: center;
121
+ inline-size: var(--_tile);
122
+ block-size: var(--_tile);
123
+ border-radius: var(--medo-radius-full);
124
+ background-color: var(--medo-color-surface-subtle);
125
+ color: var(--medo-color-text-secondary);
126
+ }
127
+
128
+ .medo-icon-tile--sm {
129
+ --_tile: var(--medo-size-control-md);
130
+ --_icon: var(--medo-size-icon-md);
131
+ }
132
+
133
+ .medo-icon-tile--lg {
134
+ --_tile: var(--medo-space-16);
135
+ --_icon: var(--medo-space-8);
136
+ }
137
+
138
+ .medo-icon-tile > svg {
139
+ inline-size: var(--_icon);
140
+ block-size: var(--_icon);
141
+ }
142
+
143
+ .medo-icon-tile--raised {
144
+ background-color: var(--medo-color-surface-default);
145
+ }
146
+
147
+ .medo-icon-tile--danger {
148
+ background-color: var(--medo-color-feedback-danger-surface);
149
+ color: var(--medo-color-feedback-danger-text);
150
+ }
151
+
152
+ .medo-icon-tile--success {
153
+ background-color: var(--medo-color-feedback-success-surface);
154
+ color: var(--medo-color-feedback-success-text);
155
+ }
156
+
157
+ @media (forced-colors: active) {
158
+ .medo-icon-tile {
159
+ outline: 1px solid CanvasText;
160
+ }
161
+ }