@med-o/ui 0.0.0-stage → 0.1.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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/dist/index.d.ts +2021 -0
  4. package/dist/index.js +4721 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +78 -4
  7. package/src/accordion/accordion.css +184 -0
  8. package/src/alert/alert.css +147 -0
  9. package/src/avatar/avatar.css +221 -0
  10. package/src/badge/badge.css +153 -0
  11. package/src/bottom-sheet/bottom-sheet.css +202 -0
  12. package/src/breadcrumbs/breadcrumbs.css +147 -0
  13. package/src/bulk-action-bar/bulk-action-bar.css +98 -0
  14. package/src/button/button.css +319 -0
  15. package/src/card/card.css +217 -0
  16. package/src/checkbox/choice.css +196 -0
  17. package/src/combobox/combobox.css +125 -0
  18. package/src/date-time/date-time.css +474 -0
  19. package/src/dialog/dialog.css +319 -0
  20. package/src/drawer/drawer.css +156 -0
  21. package/src/empty-state/empty-state.css +161 -0
  22. package/src/field/field.css +115 -0
  23. package/src/link/link.css +103 -0
  24. package/src/list/list.css +172 -0
  25. package/src/list-view/list-view.css +473 -0
  26. package/src/listbox/listbox.css +203 -0
  27. package/src/media/media.css +298 -0
  28. package/src/menu/menu.css +183 -0
  29. package/src/navigation/navigation.css +626 -0
  30. package/src/pagination/pagination.css +132 -0
  31. package/src/popover/popover.css +166 -0
  32. package/src/progress/progress.css +225 -0
  33. package/src/search/search.css +309 -0
  34. package/src/select/select.css +229 -0
  35. package/src/slider/slider.css +212 -0
  36. package/src/styles.css +40 -0
  37. package/src/switch/switch.css +160 -0
  38. package/src/table/table.css +276 -0
  39. package/src/tabs/tabs.css +211 -0
  40. package/src/tag/tag.css +225 -0
  41. package/src/text-field/input.css +206 -0
  42. package/src/toast/toast.css +184 -0
  43. package/src/toggle-button/toggle-button.css +143 -0
  44. package/src/tooltip/tooltip.css +66 -0
  45. package/src/upload/upload.css +380 -0
  46. package/src/utils/utilities.css +14 -0
@@ -0,0 +1,309 @@
1
+ /**
2
+ * Search – med.o Design System
3
+ *
4
+ * Search field: <div class="medo-field medo-search-field" [data-empty]> label · .medo-input (icon · input · clear) </div>
5
+ * Search result: <article class="medo-search-result medo-search-result--base|aesthetic"> leading · path · title link · snippet · meta </article>
6
+ * inside <ul class="medo-search-results" role="list"><li>…</li></ul>
7
+ * Base: padding 16 · gap 16 · title label/lg text/brand · divider · radius/sm
8
+ * Aesthetic: padding 20 · gap 20 · title heading/sm text/primary · no divider · radius/lg · 8 between hits
9
+ * Matches: <mark class="medo-search-result__match"> in bold – never colour alone.
10
+ * Quick search: Dialog shell (surface/raised, radius/lg, elevation/4), 640 wide, near the top · mobile full screen.
11
+ */
12
+
13
+ /* ---------- Search field ---------- */
14
+
15
+ /* The clear button shows only when there is a term. */
16
+ .medo-search-field[data-empty] .medo-search-field__clear {
17
+ display: none;
18
+ }
19
+
20
+ /* Hide the browser's own clear button – ours is the same on every browser. */
21
+ .medo-search-field .medo-input__control::-webkit-search-cancel-button,
22
+ .medo-search-field .medo-input__control::-webkit-search-decoration {
23
+ appearance: none;
24
+ }
25
+
26
+ /* ---------- Search result ---------- */
27
+
28
+ .medo-search-results {
29
+ display: grid;
30
+ margin: 0;
31
+ padding: 0;
32
+ list-style: none;
33
+ }
34
+
35
+ .medo-search-results:has(> li > .medo-search-result--aesthetic) {
36
+ gap: var(--medo-space-2);
37
+ }
38
+
39
+ .medo-search-result {
40
+ --_pad: var(--medo-space-4);
41
+
42
+ position: relative;
43
+ box-sizing: border-box;
44
+ display: flex;
45
+ align-items: flex-start;
46
+ gap: var(--_pad);
47
+ padding: var(--_pad);
48
+ border-radius: var(--medo-radius-sm);
49
+ color: var(--medo-color-text-primary);
50
+ }
51
+
52
+ .medo-search-result--base {
53
+ border-block-end: var(--medo-border-width-thin) solid var(--medo-color-border-default);
54
+ }
55
+
56
+ .medo-search-result--aesthetic {
57
+ --_pad: var(--medo-space-5);
58
+ border-radius: var(--medo-radius-lg);
59
+ }
60
+
61
+ /* The whole result is the link's hit area; the state layer and focus ring sit on the result. */
62
+ .medo-search-result:has(.medo-search-result__link[data-hovered]) {
63
+ background-color: var(--medo-color-state-hover);
64
+ }
65
+
66
+ .medo-search-result:has(.medo-search-result__link[data-pressed]) {
67
+ background-color: var(--medo-color-state-pressed);
68
+ }
69
+
70
+ .medo-search-result:has(.medo-search-result__link[data-focus-visible]) {
71
+ box-shadow: var(--medo-shadow-focus-ring-inset);
72
+ }
73
+
74
+ .medo-search-result__leading {
75
+ display: flex;
76
+ flex: none;
77
+ }
78
+
79
+ /* Media: image 4:3, 128 wide (aesthetic 160), radius/md. */
80
+ .medo-search-result--media .medo-search-result__leading {
81
+ overflow: hidden;
82
+ inline-size: 8rem;
83
+ aspect-ratio: 4 / 3;
84
+ border-radius: var(--medo-radius-md);
85
+ background-color: var(--medo-color-surface-subtle);
86
+ }
87
+
88
+ .medo-search-result--media.medo-search-result--aesthetic .medo-search-result__leading {
89
+ inline-size: 10rem;
90
+ }
91
+
92
+ .medo-search-result--media .medo-search-result__leading > :is(img, picture, video, .medo-image) {
93
+ inline-size: 100%;
94
+ block-size: 100%;
95
+ object-fit: cover;
96
+ }
97
+
98
+ .medo-search-result__content {
99
+ display: grid;
100
+ flex: 1;
101
+ gap: var(--medo-space-1);
102
+ min-inline-size: 0;
103
+ }
104
+
105
+ .medo-search-result__path {
106
+ font: var(--medo-typography-caption);
107
+ color: var(--medo-color-text-secondary);
108
+ }
109
+
110
+ .medo-search-result__title {
111
+ margin: 0;
112
+ font: var(--medo-typography-label-lg);
113
+ color: var(--medo-color-text-brand);
114
+ }
115
+
116
+ .medo-search-result--aesthetic .medo-search-result__title {
117
+ font: var(--medo-typography-heading-sm);
118
+ color: var(--medo-color-text-primary);
119
+ }
120
+
121
+ .medo-search-result__link {
122
+ color: inherit;
123
+ text-decoration: none;
124
+ outline: none;
125
+ }
126
+
127
+ .medo-search-result__link::after {
128
+ content: '';
129
+ position: absolute;
130
+ inset: 0;
131
+ border-radius: inherit;
132
+ }
133
+
134
+ .medo-search-result__link[data-hovered] {
135
+ text-decoration: underline;
136
+ text-underline-offset: 0.2em;
137
+ }
138
+
139
+ .medo-search-result__snippet {
140
+ display: -webkit-box;
141
+ margin: 0;
142
+ overflow: hidden;
143
+ font: var(--medo-typography-body-sm);
144
+ color: var(--medo-color-text-secondary);
145
+ -webkit-box-orient: vertical;
146
+ -webkit-line-clamp: 2;
147
+ line-clamp: 2;
148
+ }
149
+
150
+ /* Matches: bold, never colour alone. */
151
+ .medo-search-result__match {
152
+ background: none;
153
+ color: inherit;
154
+ font-weight: var(--medo-font-weight-bold);
155
+ }
156
+
157
+ .medo-search-result__snippet .medo-search-result__match {
158
+ color: var(--medo-color-text-primary);
159
+ font-weight: var(--medo-font-weight-semibold);
160
+ }
161
+
162
+ .medo-search-result__meta {
163
+ display: flex;
164
+ flex-wrap: wrap;
165
+ align-items: center;
166
+ gap: var(--medo-space-2);
167
+ padding-block-start: var(--medo-space-1);
168
+ }
169
+
170
+ .medo-search-result__meta-text {
171
+ font: var(--medo-typography-caption);
172
+ color: var(--medo-color-text-secondary);
173
+ }
174
+
175
+ /* ---------- Quick search ---------- */
176
+
177
+ /* Near the top, so the list can grow downwards without the field jumping. */
178
+ .medo-dialog-overlay.medo-quick-search-overlay {
179
+ align-items: start;
180
+ padding-block-start: 12vh;
181
+ }
182
+
183
+ .medo-dialog.medo-quick-search {
184
+ --_width: 40rem; /* 640 */
185
+ max-block-size: min(36rem, 100%);
186
+ }
187
+
188
+ .medo-quick-search__dialog {
189
+ display: flex;
190
+ flex-direction: column;
191
+ min-block-size: 0;
192
+ outline: none;
193
+ }
194
+
195
+ .medo-quick-search__bar {
196
+ display: flex;
197
+ align-items: center;
198
+ gap: var(--medo-space-2);
199
+ padding: var(--medo-space-3);
200
+ border-block-end: var(--medo-border-width-thin) solid var(--medo-color-border-default);
201
+ }
202
+
203
+ .medo-quick-search__field {
204
+ flex: 1;
205
+ }
206
+
207
+ .medo-quick-search__scroll {
208
+ display: grid;
209
+ flex: 1;
210
+ align-content: start;
211
+ gap: var(--medo-space-1);
212
+ min-block-size: 0;
213
+ overflow: auto;
214
+ overscroll-behavior: contain;
215
+ padding: var(--medo-space-2);
216
+ outline: none;
217
+ }
218
+
219
+ .medo-quick-search__scroll:focus-visible {
220
+ box-shadow: var(--medo-shadow-focus-ring-inset);
221
+ }
222
+
223
+ /* Nothing to show (empty field without recent searches): no empty box. */
224
+ .medo-quick-search__scroll:not(:has([role='option'], .medo-quick-search__message)) {
225
+ display: none;
226
+ }
227
+
228
+ .medo-quick-search__message {
229
+ margin: 0;
230
+ padding: var(--medo-space-2);
231
+ font: var(--medo-typography-body-sm);
232
+ color: var(--medo-color-text-secondary);
233
+ }
234
+
235
+ .medo-quick-search__all {
236
+ display: flex;
237
+ align-items: center;
238
+ gap: var(--medo-space-2);
239
+ min-block-size: calc(var(--medo-space-8) + var(--medo-space-1)); /* 36, like Option md */
240
+ padding: var(--medo-space-2);
241
+ border: 0;
242
+ border-radius: var(--medo-radius-sm);
243
+ background: none;
244
+ color: var(--medo-color-text-primary);
245
+ font: var(--medo-typography-body-sm);
246
+ text-align: start;
247
+ cursor: pointer;
248
+ outline: none;
249
+ }
250
+
251
+ .medo-quick-search__all > svg {
252
+ flex: none;
253
+ inline-size: var(--medo-size-icon-sm);
254
+ block-size: var(--medo-size-icon-sm);
255
+ }
256
+
257
+ .medo-quick-search__all[data-hovered] {
258
+ background-color: var(--medo-color-state-hover);
259
+ }
260
+
261
+ .medo-quick-search__all[data-focus-visible] {
262
+ box-shadow: var(--medo-shadow-focus-ring-inset);
263
+ }
264
+
265
+ .medo-quick-search__footer {
266
+ display: flex;
267
+ flex-wrap: wrap;
268
+ align-items: center;
269
+ gap: var(--medo-space-4);
270
+ padding: var(--medo-space-2) var(--medo-space-4);
271
+ background-color: var(--medo-color-surface-subtle);
272
+ font: var(--medo-typography-caption);
273
+ color: var(--medo-color-text-secondary);
274
+ }
275
+
276
+ .medo-quick-search__hint {
277
+ display: inline-flex;
278
+ align-items: center;
279
+ gap: var(--medo-space-1-5);
280
+ }
281
+
282
+ .medo-quick-search__all-results {
283
+ margin-inline-start: auto;
284
+ }
285
+
286
+ /* Mobile: full screen, field + Cancel on top, list below. */
287
+ .medo-dialog-overlay.medo-quick-search-overlay--mobile {
288
+ padding: 0;
289
+ }
290
+
291
+ .medo-dialog.medo-quick-search--mobile {
292
+ --_width: 100%;
293
+ block-size: 100%;
294
+ max-block-size: none;
295
+ border: 0;
296
+ border-radius: 0;
297
+ box-shadow: none;
298
+ }
299
+
300
+ .medo-quick-search--mobile .medo-quick-search__bar {
301
+ padding: var(--medo-space-3) var(--medo-space-2) var(--medo-space-3) var(--medo-space-3);
302
+ }
303
+
304
+ /* The scroll region scrolls, not the listbox. */
305
+ .medo-quick-search .medo-quick-search__list {
306
+ max-block-size: none;
307
+ overflow: visible;
308
+ padding: 0;
309
+ }
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Select – med.o Design System
3
+ *
4
+ * Input anatomy plus a chevron; the whole field is one button that opens the Listbox.
5
+ * <div class="medo-field medo-select" data-open data-invalid data-disabled data-readonly>
6
+ * <span class="medo-field__label">Country</span>
7
+ * <div class="medo-input medo-input--md medo-select__field">
8
+ * <button class="medo-select__trigger">
9
+ * <span class="medo-input__icon">…</span>
10
+ * <span class="medo-select__value">Germany</span> (or tags for multi)
11
+ * <span class="medo-select__chevron">⌄</span>
12
+ * </button>
13
+ * <button class="medo-input__action medo-select__clear" aria-label="Clear selection">×</button>
14
+ * </div>
15
+ * …helper / error…
16
+ * </div>
17
+ * The clear button sits beside the trigger (never inside it: no button in a button).
18
+ */
19
+
20
+ .medo-select__field {
21
+ --_pad: var(--medo-space-3);
22
+ --_pad-start: var(--_pad);
23
+ --_icon: var(--medo-size-icon-sm);
24
+ --_clear: var(--medo-size-icon-lg);
25
+
26
+ position: relative;
27
+ cursor: pointer;
28
+ }
29
+
30
+ /* The trigger carries the padding (higher specificity than .medo-input, independent of CSS order). */
31
+ .medo-input.medo-select__field {
32
+ padding-inline: 0;
33
+ }
34
+
35
+ .medo-select__field.medo-input--lg {
36
+ --_pad: var(--medo-space-4);
37
+ --_icon: var(--medo-size-icon-md);
38
+ --_clear: var(--medo-size-control-sm);
39
+ }
40
+
41
+ /* Multi with values: tags start closer to the edge (sm 4 · md/lg 8). */
42
+ .medo-select--tags .medo-select__field {
43
+ --_pad-start: var(--medo-space-2);
44
+ }
45
+ .medo-select--tags .medo-select__field.medo-input--sm {
46
+ --_pad-start: var(--medo-space-1);
47
+ }
48
+
49
+ .medo-select__trigger {
50
+ box-sizing: border-box;
51
+ display: flex;
52
+ flex: 1;
53
+ align-items: center;
54
+ gap: var(--medo-space-2);
55
+ min-inline-size: 0;
56
+ block-size: 100%;
57
+ padding-block: 0;
58
+ padding-inline: var(--_pad-start) var(--_pad);
59
+ border: 0;
60
+ border-radius: inherit;
61
+ background: transparent;
62
+ color: inherit;
63
+ font: inherit;
64
+ text-align: start;
65
+ cursor: inherit;
66
+ outline: none;
67
+ }
68
+
69
+ /* Room for the clear button between value and chevron (the button itself sits beside the trigger). */
70
+ .medo-select--clearable .medo-select__chevron {
71
+ margin-inline-start: calc(var(--_clear) + var(--medo-space-2));
72
+ }
73
+
74
+ .medo-select__value {
75
+ flex: 1;
76
+ min-inline-size: 0;
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ white-space: nowrap;
80
+ }
81
+
82
+ .medo-select__value[data-placeholder] {
83
+ color: var(--medo-color-text-secondary);
84
+ }
85
+
86
+ .medo-select__chevron {
87
+ display: inline-flex;
88
+ flex: none;
89
+ inline-size: var(--_icon);
90
+ block-size: var(--_icon);
91
+ color: var(--medo-color-text-secondary);
92
+ transition: transform var(--medo-motion-spring-snappy-duration) var(--medo-motion-spring-snappy);
93
+ }
94
+
95
+ .medo-select__chevron > svg {
96
+ inline-size: 100%;
97
+ block-size: 100%;
98
+ }
99
+
100
+ .medo-select[data-open] .medo-select__chevron {
101
+ transform: rotate(180deg);
102
+ }
103
+
104
+ .medo-select__clear {
105
+ position: absolute;
106
+ inset-block-start: 50%;
107
+ inset-inline-end: calc(var(--_pad) + var(--_icon) + var(--medo-space-2));
108
+ display: flex;
109
+ translate: 0 -50%;
110
+ }
111
+
112
+ .medo-select__clear > .medo-input__action {
113
+ margin: 0;
114
+ }
115
+
116
+ /* ---------- Mobile: native picker (single) ---------- */
117
+
118
+ /* Invisible native select over the field: taps open the system picker. 16 px prevents iOS zoom. */
119
+ .medo-select__native {
120
+ position: absolute;
121
+ inset: 0;
122
+ inline-size: 100%;
123
+ block-size: 100%;
124
+ margin: 0;
125
+ border: 0;
126
+ opacity: 0;
127
+ font-size: 1rem;
128
+ cursor: pointer;
129
+ appearance: none;
130
+ }
131
+
132
+ .medo-select:has(.medo-select__native:focus-visible) .medo-select__field {
133
+ --_border: var(--medo-color-focus-ring);
134
+ box-shadow: inset 0 0 0 var(--medo-border-width-thin) var(--medo-color-focus-ring);
135
+ }
136
+
137
+ /* The clear button stays above the native select. */
138
+ .medo-select__clear {
139
+ z-index: 1;
140
+ }
141
+
142
+ /* ---------- Tags (multi) ---------- */
143
+
144
+ .medo-select__tags {
145
+ position: relative;
146
+ display: flex;
147
+ flex: 1;
148
+ align-items: center;
149
+ gap: var(--medo-space-1);
150
+ min-inline-size: 0;
151
+ overflow: hidden;
152
+ }
153
+
154
+ .medo-select__tags .medo-tag {
155
+ flex: none;
156
+ max-inline-size: 100%;
157
+ }
158
+
159
+ .medo-select__tags .medo-tag:first-child {
160
+ flex-shrink: 1;
161
+ min-inline-size: 0;
162
+ }
163
+
164
+ .medo-select__tag-label {
165
+ overflow: hidden;
166
+ text-overflow: ellipsis;
167
+ }
168
+
169
+ /* Hidden copy that measures every tag, so the visible row knows how many fit. */
170
+ .medo-select__measure {
171
+ position: absolute;
172
+ inset-inline-start: 0;
173
+ display: flex;
174
+ gap: var(--medo-space-1);
175
+ visibility: hidden;
176
+ pointer-events: none;
177
+ }
178
+
179
+ /* ---------- States ---------- */
180
+
181
+ .medo-select:is([data-open], :has(.medo-select__trigger[data-focus-visible])) .medo-select__field {
182
+ --_border: var(--medo-color-focus-ring);
183
+ box-shadow: inset 0 0 0 var(--medo-border-width-thin) var(--medo-color-focus-ring);
184
+ }
185
+
186
+ .medo-select[data-invalid] .medo-select__field {
187
+ --_border: var(--medo-color-border-danger);
188
+ }
189
+
190
+ .medo-select[data-readonly] .medo-select__field {
191
+ --_border: var(--medo-color-border-default);
192
+ background-color: var(--medo-color-surface-subtle);
193
+ cursor: default;
194
+ }
195
+
196
+ .medo-select[data-disabled] .medo-select__field {
197
+ --_border: var(--medo-color-border-default);
198
+ background-color: var(--medo-color-action-disabled);
199
+ color: var(--medo-color-text-disabled);
200
+ cursor: not-allowed;
201
+ }
202
+
203
+ .medo-select[data-disabled] :is(.medo-select__value[data-placeholder], .medo-select__chevron, .medo-input__icon) {
204
+ color: var(--medo-color-text-disabled);
205
+ }
206
+
207
+ .medo-select[data-disabled] .medo-tag {
208
+ --_bg: transparent;
209
+ --_fg: var(--medo-color-text-disabled);
210
+ }
211
+
212
+ /* Hover only when the field can change. */
213
+ @media (hover: hover) {
214
+ .medo-select:is([data-readonly], [data-disabled]) .medo-select__field:hover {
215
+ --_border: var(--medo-color-border-default);
216
+ }
217
+ }
218
+
219
+ @media (forced-colors: active) {
220
+ .medo-select:is([data-open], :has(.medo-select__trigger[data-focus-visible])) .medo-select__field {
221
+ outline: var(--medo-focus-ring-width) solid Highlight;
222
+ }
223
+ }
224
+
225
+ @media (prefers-reduced-motion: reduce) {
226
+ .medo-select__chevron {
227
+ transition: transform var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
228
+ }
229
+ }