@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.
- package/LICENSE +21 -0
- package/README.md +38 -2
- package/dist/index.d.ts +2021 -0
- package/dist/index.js +4721 -0
- package/dist/index.js.map +1 -0
- package/package.json +78 -4
- package/src/accordion/accordion.css +184 -0
- package/src/alert/alert.css +147 -0
- package/src/avatar/avatar.css +221 -0
- package/src/badge/badge.css +153 -0
- package/src/bottom-sheet/bottom-sheet.css +202 -0
- package/src/breadcrumbs/breadcrumbs.css +147 -0
- package/src/bulk-action-bar/bulk-action-bar.css +98 -0
- package/src/button/button.css +319 -0
- package/src/card/card.css +217 -0
- package/src/checkbox/choice.css +196 -0
- package/src/combobox/combobox.css +125 -0
- package/src/date-time/date-time.css +474 -0
- package/src/dialog/dialog.css +319 -0
- package/src/drawer/drawer.css +156 -0
- package/src/empty-state/empty-state.css +161 -0
- package/src/field/field.css +115 -0
- package/src/link/link.css +103 -0
- package/src/list/list.css +172 -0
- package/src/list-view/list-view.css +473 -0
- package/src/listbox/listbox.css +203 -0
- package/src/media/media.css +298 -0
- package/src/menu/menu.css +183 -0
- package/src/navigation/navigation.css +626 -0
- package/src/pagination/pagination.css +132 -0
- package/src/popover/popover.css +166 -0
- package/src/progress/progress.css +225 -0
- package/src/search/search.css +309 -0
- package/src/select/select.css +229 -0
- package/src/slider/slider.css +212 -0
- package/src/styles.css +40 -0
- package/src/switch/switch.css +160 -0
- package/src/table/table.css +276 -0
- package/src/tabs/tabs.css +211 -0
- package/src/tag/tag.css +225 -0
- package/src/text-field/input.css +206 -0
- package/src/toast/toast.css +184 -0
- package/src/toggle-button/toggle-button.css +143 -0
- package/src/tooltip/tooltip.css +66 -0
- package/src/upload/upload.css +380 -0
- package/src/utils/utilities.css +14 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast – med.o Design System
|
|
3
|
+
*
|
|
4
|
+
* Short, temporary feedback after an action. Inverted surface, no icon, no tone.
|
|
5
|
+
* <div class="medo-toast-region" role="region"> desktop bottom right · mobile full width
|
|
6
|
+
* <div class="medo-toast" role="alertdialog"> surface/inverse, radius/md, elevation/3
|
|
7
|
+
* <div class="medo-toast__content" role="alert">
|
|
8
|
+
* <span class="medo-toast__message">Q3-Report.pdf deleted</span>
|
|
9
|
+
* </div>
|
|
10
|
+
* <button class="medo-toast__button medo-toast__action">Undo</button>
|
|
11
|
+
* <button class="medo-toast__button medo-toast__close">×</button>
|
|
12
|
+
* </div>
|
|
13
|
+
* </div>
|
|
14
|
+
* Max 3, newest closest to the edge. Region offset for a bottom navigation: --medo-toast-offset.
|
|
15
|
+
* State contract: [data-hovered] [data-pressed] [data-focus-visible] (React Aria).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
.medo-toast-region {
|
|
19
|
+
--medo-toast-offset: 0px;
|
|
20
|
+
|
|
21
|
+
position: fixed;
|
|
22
|
+
inset-block-end: calc(var(--medo-space-6) + var(--medo-toast-offset));
|
|
23
|
+
inset-inline-end: var(--medo-space-6);
|
|
24
|
+
z-index: var(--medo-layer-toast);
|
|
25
|
+
display: flex;
|
|
26
|
+
/* The queue is newest first: the newest toast sits at the edge, older ones above. */
|
|
27
|
+
flex-direction: column-reverse;
|
|
28
|
+
gap: var(--medo-space-2);
|
|
29
|
+
outline: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.medo-toast-region[data-focus-visible] {
|
|
33
|
+
border-radius: var(--medo-radius-md);
|
|
34
|
+
box-shadow: var(--medo-shadow-focus-ring);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.medo-toast {
|
|
38
|
+
box-sizing: border-box;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
gap: var(--medo-space-2);
|
|
42
|
+
inline-size: 25rem; /* 400 */
|
|
43
|
+
min-inline-size: 18rem; /* 288 */
|
|
44
|
+
max-inline-size: min(35rem, 100vw - 2 * var(--medo-space-6)); /* 560 */
|
|
45
|
+
min-block-size: var(--medo-size-control-lg); /* 48 */
|
|
46
|
+
padding: var(--medo-space-2);
|
|
47
|
+
padding-inline-start: var(--medo-space-4);
|
|
48
|
+
border-radius: var(--medo-radius-md);
|
|
49
|
+
background-color: var(--medo-color-surface-inverse);
|
|
50
|
+
box-shadow: var(--medo-shadow-elevation-3);
|
|
51
|
+
color: var(--medo-color-text-inverse);
|
|
52
|
+
outline: none;
|
|
53
|
+
view-transition-class: medo-toast;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.medo-toast[data-focus-visible] {
|
|
57
|
+
box-shadow: var(--medo-shadow-focus-ring), var(--medo-shadow-elevation-3);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.medo-toast__content {
|
|
61
|
+
flex: 1;
|
|
62
|
+
min-inline-size: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* One line; longer text is cut (write shorter). */
|
|
66
|
+
.medo-toast__message {
|
|
67
|
+
display: block;
|
|
68
|
+
overflow: hidden;
|
|
69
|
+
font: var(--medo-typography-body-sm);
|
|
70
|
+
text-overflow: ellipsis;
|
|
71
|
+
white-space: nowrap;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ---------- _Toast button (Action · Close) – inverse state layers ---------- */
|
|
75
|
+
|
|
76
|
+
.medo-toast__button {
|
|
77
|
+
display: inline-flex;
|
|
78
|
+
flex: none;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
block-size: var(--medo-size-control-sm); /* 32 */
|
|
82
|
+
border: 0;
|
|
83
|
+
border-radius: var(--medo-radius-sm);
|
|
84
|
+
background-color: transparent;
|
|
85
|
+
color: var(--medo-color-text-inverse);
|
|
86
|
+
font: var(--medo-typography-label-md);
|
|
87
|
+
cursor: pointer;
|
|
88
|
+
outline: none;
|
|
89
|
+
-webkit-tap-highlight-color: transparent;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.medo-toast__action {
|
|
93
|
+
padding-inline: var(--medo-space-3);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.medo-toast__close {
|
|
97
|
+
inline-size: var(--medo-size-control-sm);
|
|
98
|
+
color: var(--medo-color-text-inverse-secondary);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.medo-toast__close > svg {
|
|
102
|
+
inline-size: var(--medo-size-icon-sm);
|
|
103
|
+
block-size: var(--medo-size-icon-sm);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.medo-toast__button[data-hovered] {
|
|
107
|
+
background-color: var(--medo-color-state-hover-inverse);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.medo-toast__button[data-pressed] {
|
|
111
|
+
background-color: var(--medo-color-state-pressed-inverse);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.medo-toast__button[data-focus-visible] {
|
|
115
|
+
box-shadow: var(--medo-shadow-focus-ring);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* ---------- Mobile < 640 px: full width, 16 px margin, above the safe area ---------- */
|
|
119
|
+
|
|
120
|
+
@media (max-width: 639.98px) {
|
|
121
|
+
.medo-toast-region {
|
|
122
|
+
inset-inline: var(--medo-space-4);
|
|
123
|
+
inset-block-end: calc(var(--medo-space-4) + var(--medo-toast-offset) + env(safe-area-inset-bottom));
|
|
124
|
+
}
|
|
125
|
+
.medo-toast {
|
|
126
|
+
inline-size: 100%;
|
|
127
|
+
min-inline-size: 0;
|
|
128
|
+
max-inline-size: none;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ---------- Motion (View Transitions, iOS): in slides up with a smooth spring, out fades and shrinks a little;
|
|
133
|
+
* the other toasts glide to their new place with the same spring. ---------- */
|
|
134
|
+
|
|
135
|
+
::view-transition-group(.medo-toast) {
|
|
136
|
+
animation-duration: var(--medo-motion-spring-smooth-duration);
|
|
137
|
+
animation-timing-function: var(--medo-motion-spring-smooth);
|
|
138
|
+
}
|
|
139
|
+
::view-transition-new(.medo-toast):only-child {
|
|
140
|
+
animation: medo-toast-in var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
|
|
141
|
+
}
|
|
142
|
+
::view-transition-old(.medo-toast):only-child {
|
|
143
|
+
animation: medo-toast-out var(--medo-motion-duration-fast) var(--medo-motion-easing-exit) forwards;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@keyframes medo-toast-in {
|
|
147
|
+
from {
|
|
148
|
+
opacity: 0;
|
|
149
|
+
transform: translateY(var(--medo-space-6)) scale(0.96);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
@keyframes medo-toast-out {
|
|
153
|
+
to {
|
|
154
|
+
opacity: 0;
|
|
155
|
+
transform: scale(0.96);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
@keyframes medo-toast-fade {
|
|
159
|
+
from {
|
|
160
|
+
opacity: 0;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@media (prefers-reduced-motion: reduce) {
|
|
165
|
+
/* Reduced motion: toasts cross-fade, nothing slides. */
|
|
166
|
+
::view-transition-group(.medo-toast) {
|
|
167
|
+
animation-duration: var(--medo-motion-duration-fast);
|
|
168
|
+
}
|
|
169
|
+
::view-transition-new(.medo-toast):only-child {
|
|
170
|
+
animation: medo-toast-fade var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
|
|
171
|
+
}
|
|
172
|
+
::view-transition-old(.medo-toast):only-child {
|
|
173
|
+
animation: medo-toast-fade var(--medo-motion-duration-fast) var(--medo-motion-easing-standard) reverse forwards;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@media (forced-colors: active) {
|
|
178
|
+
.medo-toast {
|
|
179
|
+
border: 1px solid CanvasText;
|
|
180
|
+
}
|
|
181
|
+
.medo-toast__button[data-focus-visible] {
|
|
182
|
+
outline: 2px solid Highlight;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toggle Button – med.o Design System
|
|
3
|
+
*
|
|
4
|
+
* A button that stays pressed. Builds on the Button classes (sizes, icon, focus, motion):
|
|
5
|
+
* <button class="medo-button medo-button--md medo-toggle" aria-pressed="true" data-selected>Bold</button>
|
|
6
|
+
* Off looks like a ghost button (text/secondary). On: action/selected + text/brand – fill and colour together.
|
|
7
|
+
*
|
|
8
|
+
* Groups:
|
|
9
|
+
* <div class="medo-toggle-group medo-toggle-group--segmented medo-toggle-group--md">…</div> single select, container
|
|
10
|
+
* <div class="medo-toggle-group medo-toggle-group--toolbar">…</div> multiple, no container
|
|
11
|
+
* <div class="medo-toolbar">group <hr class="medo-toolbar__separator"> group</div> several groups
|
|
12
|
+
*
|
|
13
|
+
* State contract: [data-selected] [data-hovered] [data-pressed] [data-focus-visible] [data-disabled]
|
|
14
|
+
* (plain HTML: aria-pressed="true" counts as selected).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
.medo-toggle {
|
|
18
|
+
--_bg-hover: var(--medo-color-state-hover);
|
|
19
|
+
--_bg-pressed: var(--medo-color-state-pressed);
|
|
20
|
+
--_fg: var(--medo-color-text-secondary);
|
|
21
|
+
--_fg-hover: var(--medo-color-text-primary);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.medo-toggle:is([data-selected], [aria-pressed='true']) {
|
|
25
|
+
--_bg: var(--medo-color-action-selected);
|
|
26
|
+
--_bg-hover: var(--medo-color-action-selected-hover);
|
|
27
|
+
--_bg-pressed: var(--medo-color-action-selected-pressed);
|
|
28
|
+
--_fg: var(--medo-color-text-brand);
|
|
29
|
+
--_fg-hover: var(--medo-color-text-brand);
|
|
30
|
+
--_fg-pressed: var(--medo-color-text-brand-hover);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Disabled: off without fill, on keeps a neutral fill so the state stays visible. */
|
|
34
|
+
.medo-toggle:is(:disabled, [data-disabled]) {
|
|
35
|
+
--_bg: transparent;
|
|
36
|
+
--_bg-hover: var(--_bg);
|
|
37
|
+
--_bg-pressed: var(--_bg);
|
|
38
|
+
--_fg: var(--medo-color-text-disabled);
|
|
39
|
+
--_fg-hover: var(--_fg);
|
|
40
|
+
--_fg-pressed: var(--_fg);
|
|
41
|
+
}
|
|
42
|
+
.medo-toggle:is(:disabled, [data-disabled]):is([data-selected], [aria-pressed='true']) {
|
|
43
|
+
--_bg: var(--medo-color-action-disabled);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* ---------- Groups ---------- */
|
|
47
|
+
|
|
48
|
+
.medo-toggle-group {
|
|
49
|
+
display: inline-flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: var(--medo-space-1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Segmented: one container; items one size smaller, so the group has the control height (md 40, lg 48). */
|
|
55
|
+
.medo-toggle-group--segmented {
|
|
56
|
+
box-sizing: border-box;
|
|
57
|
+
gap: var(--medo-space-0-5);
|
|
58
|
+
padding: var(--medo-space-1);
|
|
59
|
+
border-radius: var(--medo-radius-md);
|
|
60
|
+
background-color: var(--medo-color-surface-default);
|
|
61
|
+
/* Inside stroke: the border does not add to the height. */
|
|
62
|
+
box-shadow: inset 0 0 0 var(--medo-border-width-thin) var(--medo-color-border-default);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.medo-toggle-group--segmented .medo-toggle {
|
|
66
|
+
position: relative;
|
|
67
|
+
isolation: isolate;
|
|
68
|
+
border-radius: var(--medo-radius-sm);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/* The selected fill is an indicator that slides between the items with a snappy spring (iOS segmented control). */
|
|
72
|
+
.medo-toggle-group--segmented .medo-toggle:is([data-selected], [aria-pressed='true']) {
|
|
73
|
+
--_bg: transparent;
|
|
74
|
+
}
|
|
75
|
+
.medo-toggle__indicator {
|
|
76
|
+
position: absolute;
|
|
77
|
+
inset: 0;
|
|
78
|
+
z-index: -1;
|
|
79
|
+
border-radius: inherit;
|
|
80
|
+
background-color: var(--medo-color-action-selected);
|
|
81
|
+
transition:
|
|
82
|
+
translate var(--medo-motion-spring-snappy-duration) var(--medo-motion-spring-snappy),
|
|
83
|
+
width var(--medo-motion-spring-snappy-duration) var(--medo-motion-spring-snappy),
|
|
84
|
+
background-color var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
|
|
85
|
+
}
|
|
86
|
+
.medo-toggle[data-hovered] > .medo-toggle__indicator {
|
|
87
|
+
background-color: var(--medo-color-action-selected-hover);
|
|
88
|
+
}
|
|
89
|
+
.medo-toggle[data-pressed] > .medo-toggle__indicator {
|
|
90
|
+
background-color: var(--medo-color-action-selected-pressed);
|
|
91
|
+
}
|
|
92
|
+
.medo-toggle:is(:disabled, [data-disabled]) > .medo-toggle__indicator {
|
|
93
|
+
background-color: var(--medo-color-action-disabled);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@media (prefers-reduced-motion: reduce) {
|
|
97
|
+
.medo-toggle__indicator {
|
|
98
|
+
transition: background-color var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* Full width (mobile): items share the space equally. */
|
|
103
|
+
.medo-toggle-group--full {
|
|
104
|
+
display: flex;
|
|
105
|
+
inline-size: 100%;
|
|
106
|
+
}
|
|
107
|
+
.medo-toggle-group--full .medo-toggle {
|
|
108
|
+
flex: 1 1 0;
|
|
109
|
+
min-inline-size: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* ---------- Toolbar: several groups ---------- */
|
|
113
|
+
|
|
114
|
+
.medo-toolbar {
|
|
115
|
+
display: flex;
|
|
116
|
+
flex-wrap: wrap;
|
|
117
|
+
align-items: center;
|
|
118
|
+
gap: var(--medo-space-1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.medo-toolbar__separator {
|
|
122
|
+
flex: none;
|
|
123
|
+
align-self: center;
|
|
124
|
+
inline-size: var(--medo-border-width-thin);
|
|
125
|
+
block-size: var(--medo-size-icon-lg);
|
|
126
|
+
margin: 0 var(--medo-space-1);
|
|
127
|
+
border: 0;
|
|
128
|
+
background-color: var(--medo-color-border-default);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@media (forced-colors: active) {
|
|
132
|
+
.medo-toggle:is([data-selected], [aria-pressed='true']) {
|
|
133
|
+
forced-color-adjust: none;
|
|
134
|
+
background-color: Highlight;
|
|
135
|
+
color: HighlightText;
|
|
136
|
+
}
|
|
137
|
+
.medo-toggle-group--segmented {
|
|
138
|
+
border: 1px solid CanvasText;
|
|
139
|
+
}
|
|
140
|
+
.medo-toolbar__separator {
|
|
141
|
+
background-color: CanvasText;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tooltip – med.o Design System
|
|
3
|
+
*
|
|
4
|
+
* Short label on hover (after 500 ms) or keyboard focus (instantly). Never interactive.
|
|
5
|
+
* <div class="medo-tooltip" role="tooltip">Copy link<kbd class="medo-tooltip__shortcut">⌘C</kbd></div>
|
|
6
|
+
*
|
|
7
|
+
* State contract: [data-entering] [data-exiting] [data-placement] (set by React Aria).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.medo-tooltip {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: baseline;
|
|
14
|
+
gap: var(--medo-space-2);
|
|
15
|
+
max-inline-size: 15rem; /* 240 px, then wraps */
|
|
16
|
+
padding: var(--medo-space-1) var(--medo-space-2);
|
|
17
|
+
border-radius: var(--medo-radius-sm);
|
|
18
|
+
background-color: var(--medo-color-surface-inverse);
|
|
19
|
+
color: var(--medo-color-text-inverse);
|
|
20
|
+
box-shadow: var(--medo-shadow-elevation-2);
|
|
21
|
+
font: var(--medo-typography-caption);
|
|
22
|
+
overflow-wrap: break-word;
|
|
23
|
+
z-index: var(--medo-layer-tooltip);
|
|
24
|
+
pointer-events: auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.medo-tooltip__shortcut {
|
|
28
|
+
font: inherit;
|
|
29
|
+
color: var(--medo-color-text-inverse-secondary);
|
|
30
|
+
white-space: nowrap;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Motion (iOS): fades in and settles from 96 % at the trigger; out: a quick fade without movement. */
|
|
34
|
+
.medo-tooltip {
|
|
35
|
+
transform-origin: var(--trigger-anchor-point, top);
|
|
36
|
+
transition:
|
|
37
|
+
opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-enter),
|
|
38
|
+
scale var(--medo-motion-spring-snappy-duration) var(--medo-motion-spring-snappy);
|
|
39
|
+
}
|
|
40
|
+
.medo-tooltip[data-entering] {
|
|
41
|
+
opacity: 0;
|
|
42
|
+
scale: 0.96;
|
|
43
|
+
}
|
|
44
|
+
.medo-tooltip[data-exiting] {
|
|
45
|
+
opacity: 0;
|
|
46
|
+
scale: 1;
|
|
47
|
+
transition:
|
|
48
|
+
opacity var(--medo-motion-duration-fast) var(--medo-motion-easing-exit),
|
|
49
|
+
scale var(--medo-motion-duration-fast) var(--medo-motion-easing-exit);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@media (forced-colors: active) {
|
|
53
|
+
.medo-tooltip {
|
|
54
|
+
border: var(--medo-border-width-thin) solid CanvasText;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@media (prefers-reduced-motion: reduce) {
|
|
59
|
+
/* Reduced motion: a short cross-fade, no scaling. */
|
|
60
|
+
.medo-tooltip {
|
|
61
|
+
transition: opacity var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
|
|
62
|
+
}
|
|
63
|
+
.medo-tooltip:is([data-entering], [data-exiting]) {
|
|
64
|
+
scale: none;
|
|
65
|
+
}
|
|
66
|
+
}
|