@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
package/package.json CHANGED
@@ -1,6 +1,80 @@
1
1
  {
2
2
  "name": "@med-o/ui",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "React components of the med.o Design System. Styles are plain CSS on top of @med-o/design-tokens and can be reused by other frameworks.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "@med-o/source": "./src/index.ts",
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "./styles.css": "./src/styles.css",
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "src/**/*.css"
21
+ ],
22
+ "sideEffects": [
23
+ "*.css"
24
+ ],
25
+ "dependencies": {
26
+ "@internationalized/date": "^3.12.4",
27
+ "@med-o/design-tokens": "0.1.0",
28
+ "lucide-react": "^1.59.0",
29
+ "react-aria-components": "^1.22.1"
30
+ },
31
+ "peerDependencies": {
32
+ "react": "^19.0.0",
33
+ "react-dom": "^19.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "tsup": "^8.5.1"
37
+ },
38
+ "scripts": {
39
+ "build": "tsup",
40
+ "prepack": "npm run build"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/ahmeeedo/medo-design_system.git",
45
+ "directory": "packages/ui"
46
+ },
47
+ "homepage": "https://design.med-o.de",
48
+ "bugs": {
49
+ "url": "https://github.com/ahmeeedo/medo-design_system/issues"
50
+ },
51
+ "keywords": [
52
+ "design-system",
53
+ "react",
54
+ "react-aria",
55
+ "components",
56
+ "accessibility",
57
+ "wcag"
58
+ ],
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "tsup": {
63
+ "entry": [
64
+ "src/index.ts"
65
+ ],
66
+ "format": [
67
+ "esm"
68
+ ],
69
+ "target": "es2022",
70
+ "dts": true,
71
+ "sourcemap": true,
72
+ "clean": true,
73
+ "banner": {
74
+ "js": "\"use client\";"
75
+ },
76
+ "loader": {
77
+ ".css": "empty"
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Accordion – med.o Design System
3
+ *
4
+ * <div class="medo-accordion medo-accordion--md"> surface/default · border/default · radius/lg · clips
5
+ * <div class="medo-accordion__item" [data-expanded] [data-disabled]> 1 px divider between items, none after the last
6
+ * <h3 class="medo-accordion__heading"><button class="medo-accordion__trigger" aria-expanded>icon · title/description · badge · chevron</button></h3>
7
+ * <div class="medo-accordion__panel" role="group"><div class="medo-accordion__content">…</div></div>
8
+ * </div>
9
+ * </div>
10
+ * md: header min 48 · padding 12/16 · title label/md · icon 20 · panel padding 12 16 16
11
+ * lg: header min 64 · padding 20/24 · title heading/sm · icon 24 · panel padding 16 24 24
12
+ * Motion: height + chevron with spring/smooth, the content fades; reduced motion: content cross-fade only. Closed panels: hidden="until-found" (React Aria).
13
+ */
14
+
15
+ .medo-accordion-wrap {
16
+ display: grid;
17
+ gap: var(--medo-space-2);
18
+ }
19
+
20
+ .medo-accordion__toolbar {
21
+ display: flex;
22
+ justify-content: flex-end;
23
+ }
24
+
25
+ .medo-accordion {
26
+ --_pad-y: var(--medo-space-3);
27
+ --_pad-x: var(--medo-space-4);
28
+ --_min: var(--medo-space-12); /* 48 */
29
+ --_icon: var(--medo-size-icon-md);
30
+ --_title: var(--medo-typography-label-md);
31
+ --_desc: var(--medo-typography-body-sm);
32
+ --_panel: var(--medo-space-3) var(--medo-space-4) var(--medo-space-4);
33
+
34
+ overflow: hidden;
35
+ border: var(--medo-border-width-thin) solid var(--medo-color-border-default);
36
+ border-radius: var(--medo-radius-lg);
37
+ background-color: var(--medo-color-surface-default);
38
+ color: var(--medo-color-text-primary);
39
+ }
40
+
41
+ .medo-accordion--lg {
42
+ --_pad-y: var(--medo-space-5);
43
+ --_pad-x: var(--medo-space-6);
44
+ --_min: var(--medo-space-16); /* 64 */
45
+ --_icon: var(--medo-size-icon-lg);
46
+ --_title: var(--medo-typography-heading-sm);
47
+ --_desc: var(--medo-typography-body-md);
48
+ --_panel: var(--medo-space-4) var(--medo-space-6) var(--medo-space-6);
49
+ }
50
+
51
+ .medo-accordion__item + .medo-accordion__item {
52
+ border-block-start: var(--medo-border-width-thin) solid var(--medo-color-border-default);
53
+ }
54
+
55
+ .medo-accordion__heading {
56
+ margin: 0;
57
+ font: inherit;
58
+ }
59
+
60
+ /* The whole header is the target. */
61
+ .medo-accordion__trigger {
62
+ box-sizing: border-box;
63
+ display: flex;
64
+ align-items: center;
65
+ gap: var(--medo-space-3);
66
+ inline-size: 100%;
67
+ min-block-size: var(--_min);
68
+ padding: var(--_pad-y) var(--_pad-x);
69
+ border: 0;
70
+ background: none;
71
+ color: inherit;
72
+ font: inherit;
73
+ text-align: start;
74
+ cursor: pointer;
75
+ outline: none;
76
+ -webkit-tap-highlight-color: transparent;
77
+ }
78
+
79
+ .medo-accordion__trigger[data-hovered] {
80
+ background-color: var(--medo-color-state-hover);
81
+ }
82
+
83
+ .medo-accordion__trigger[data-pressed] {
84
+ background-color: var(--medo-color-state-pressed);
85
+ }
86
+
87
+ .medo-accordion__trigger[data-focus-visible] {
88
+ box-shadow: inset 0 0 0 var(--medo-focus-ring-width) var(--medo-color-focus-ring);
89
+ }
90
+
91
+ .medo-accordion__item[data-disabled] .medo-accordion__trigger {
92
+ opacity: 0.5;
93
+ cursor: not-allowed;
94
+ }
95
+
96
+ .medo-accordion__icon {
97
+ display: inline-flex;
98
+ flex: none;
99
+ align-self: flex-start;
100
+ /* Centred on the title's first line. */
101
+ margin-block-start: calc((1lh - var(--_icon)) / 2);
102
+ color: var(--medo-color-text-secondary);
103
+ font: var(--_title);
104
+ }
105
+
106
+ .medo-accordion__icon > svg {
107
+ inline-size: var(--_icon);
108
+ block-size: var(--_icon);
109
+ }
110
+
111
+ .medo-accordion__text {
112
+ display: grid;
113
+ flex: 1;
114
+ min-inline-size: 0;
115
+ }
116
+
117
+ .medo-accordion__title {
118
+ font: var(--_title);
119
+ color: var(--medo-color-text-primary);
120
+ }
121
+
122
+ .medo-accordion__description {
123
+ font: var(--_desc);
124
+ color: var(--medo-color-text-secondary);
125
+ }
126
+
127
+ .medo-accordion__badge {
128
+ display: inline-flex;
129
+ flex: none;
130
+ }
131
+
132
+ .medo-accordion__chevron {
133
+ flex: none;
134
+ inline-size: var(--_icon);
135
+ block-size: var(--_icon);
136
+ color: var(--medo-color-text-secondary);
137
+ transition: rotate var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
138
+ }
139
+
140
+ .medo-accordion__item[data-expanded] .medo-accordion__chevron {
141
+ rotate: 180deg;
142
+ }
143
+
144
+ /* Panel: React Aria measures the height into --disclosure-panel-height, so it can animate. */
145
+ .medo-accordion__panel {
146
+ block-size: var(--disclosure-panel-height);
147
+ overflow: clip;
148
+ transition: block-size var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
149
+ }
150
+
151
+ /* The content fades with the height, so it never pops in or is cut off hard. */
152
+ .medo-accordion__content {
153
+ padding: var(--_panel);
154
+ transition: opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-standard);
155
+ }
156
+
157
+ .medo-accordion__item:not([data-expanded]) .medo-accordion__content {
158
+ opacity: 0;
159
+ }
160
+
161
+ /* The content lines up with the title when an icon is shown. */
162
+ .medo-accordion__item--icon .medo-accordion__content {
163
+ padding-inline-start: calc(var(--_pad-x) + var(--_icon) + var(--medo-space-3));
164
+ }
165
+
166
+ @media (prefers-reduced-motion: reduce) {
167
+ /* Reduced motion: no growing height – the content cross-fades. */
168
+ .medo-accordion__panel {
169
+ transition: none;
170
+ }
171
+ .medo-accordion__chevron {
172
+ transition: rotate var(--medo-motion-duration-fast) var(--medo-motion-easing-standard);
173
+ }
174
+ .medo-accordion__content {
175
+ transition-duration: var(--medo-motion-duration-fast);
176
+ }
177
+ }
178
+
179
+ @media (forced-colors: active) {
180
+ .medo-accordion__trigger[data-focus-visible] {
181
+ outline: 2px solid Highlight;
182
+ outline-offset: -2px;
183
+ }
184
+ }
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Alert – med.o Design System
3
+ *
4
+ * Persistent message inside the page. Plain markup:
5
+ * <div class="medo-alert medo-alert--info">
6
+ * <svg class="medo-alert__icon" aria-hidden="true">…</svg>
7
+ * <div class="medo-alert__content">
8
+ * <p class="medo-alert__title">Title</p>
9
+ * <div class="medo-alert__description">Description</div>
10
+ * <div class="medo-alert__actions">…text buttons…</div>
11
+ * </div>
12
+ * <button class="medo-alert__close">…</button>
13
+ * </div>
14
+ * Tones: info · success · warning · danger. Variants: inline (default) · banner (full width).
15
+ */
16
+
17
+ .medo-alert {
18
+ --_bg: var(--medo-color-feedback-info-surface);
19
+ --_border: var(--medo-color-feedback-info-border);
20
+ --_icon: var(--medo-color-feedback-info-text);
21
+
22
+ box-sizing: border-box;
23
+ display: flex;
24
+ align-items: flex-start;
25
+ gap: var(--medo-space-3);
26
+ padding: var(--medo-space-4);
27
+ padding-inline-end: var(--medo-space-3);
28
+ border: var(--medo-border-width-thin) solid var(--_border);
29
+ border-radius: var(--medo-radius-md);
30
+ background-color: var(--_bg);
31
+ color: var(--medo-color-text-primary);
32
+ }
33
+
34
+ .medo-alert--success {
35
+ --_bg: var(--medo-color-feedback-success-surface);
36
+ --_border: var(--medo-color-feedback-success-border);
37
+ --_icon: var(--medo-color-feedback-success-text);
38
+ }
39
+ .medo-alert--warning {
40
+ --_bg: var(--medo-color-feedback-warning-surface);
41
+ --_border: var(--medo-color-feedback-warning-border);
42
+ --_icon: var(--medo-color-feedback-warning-text);
43
+ }
44
+ .medo-alert--danger {
45
+ --_bg: var(--medo-color-feedback-danger-surface);
46
+ --_border: var(--medo-color-feedback-danger-border);
47
+ --_icon: var(--medo-color-feedback-danger-text);
48
+ }
49
+
50
+ .medo-alert__icon {
51
+ flex-shrink: 0;
52
+ inline-size: var(--medo-size-icon-md);
53
+ block-size: var(--medo-size-icon-md);
54
+ color: var(--_icon);
55
+ stroke-width: 2; /* 1.67 px at 20 px */
56
+ }
57
+
58
+ .medo-alert__content {
59
+ display: grid;
60
+ gap: var(--medo-space-1);
61
+ flex: 1;
62
+ min-inline-size: 0;
63
+ /* Centre the first line with the 20 px icon (label/md has a 20 px line). */
64
+ padding-block-start: 0;
65
+ }
66
+
67
+ .medo-alert__title {
68
+ margin: 0;
69
+ font: var(--medo-typography-label-md);
70
+ color: var(--medo-color-text-primary);
71
+ }
72
+
73
+ .medo-alert__description {
74
+ font: var(--medo-typography-body-sm);
75
+ color: var(--medo-color-text-secondary);
76
+ }
77
+
78
+ .medo-alert__description > :first-child {
79
+ margin-block-start: 0;
80
+ }
81
+ .medo-alert__description > :last-child {
82
+ margin-block-end: 0;
83
+ }
84
+
85
+ .medo-alert__actions {
86
+ display: flex;
87
+ flex-wrap: wrap;
88
+ gap: var(--medo-space-4);
89
+ margin-block-start: var(--medo-space-2);
90
+ }
91
+
92
+ /* The close button (Icon Button ghost sm) sits in the top-right corner. */
93
+ .medo-alert__close {
94
+ flex-shrink: 0;
95
+ margin-block: calc(-1 * var(--medo-space-1-5));
96
+ }
97
+
98
+ /* ---------- Banner: full width, bottom border only, one line ---------- */
99
+
100
+ .medo-alert--banner {
101
+ align-items: center;
102
+ padding: var(--medo-space-2) var(--medo-space-6);
103
+ border-width: 0 0 var(--medo-border-width-thin);
104
+ border-radius: 0;
105
+ }
106
+
107
+ .medo-alert--banner .medo-alert__content {
108
+ display: flex;
109
+ flex-wrap: wrap;
110
+ align-items: baseline;
111
+ column-gap: var(--medo-space-3);
112
+ }
113
+
114
+ .medo-alert--banner .medo-alert__actions {
115
+ margin-block-start: 0;
116
+ }
117
+
118
+ .medo-alert--banner .medo-alert__close {
119
+ margin-block: 0;
120
+ }
121
+
122
+ @media (forced-colors: active) {
123
+ .medo-alert {
124
+ border-color: CanvasText;
125
+ }
126
+ }
127
+
128
+ /* An alert that appears (after an action) fades in and settles 4 px with a smooth spring. */
129
+ .medo-alert {
130
+ transition:
131
+ opacity var(--medo-motion-duration-normal) var(--medo-motion-easing-enter),
132
+ translate var(--medo-motion-spring-smooth-duration) var(--medo-motion-spring-smooth);
133
+ }
134
+ @starting-style {
135
+ .medo-alert {
136
+ opacity: 0;
137
+ translate: 0 calc(-1 * var(--medo-space-1));
138
+ }
139
+ }
140
+
141
+ @media (prefers-reduced-motion: reduce) {
142
+ @starting-style {
143
+ .medo-alert {
144
+ translate: none;
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Avatar – med.o Design System
3
+ *
4
+ * Fallback chain: image → initials → icon. Circle = person, square = organization.
5
+ * <span class="medo-avatar medo-avatar--md medo-avatar--circle medo-avatar--teal" role="img" aria-label="Lea M.">
6
+ * <span class="medo-avatar__initials" aria-hidden="true">LM</span>
7
+ * <img class="medo-avatar__image" src="…" alt="">
8
+ * </span>
9
+ *
10
+ * Sizes xs 20 · sm 24 · md 32 · lg 40 · xl 56 · 2xl 80
11
+ * Colours: blue · violet · pink · amber · green · teal (from the user id) · neutral (icon)
12
+ */
13
+
14
+ .medo-avatar {
15
+ --_size: var(--medo-space-8);
16
+ --_bg: var(--medo-color-surface-subtle);
17
+ --_fg: var(--medo-color-text-secondary);
18
+ --_radius: var(--medo-radius-md);
19
+ --_status: calc(var(--medo-space-2) + var(--medo-space-0-5)); /* 10 */
20
+
21
+ position: relative;
22
+ box-sizing: border-box;
23
+ display: inline-grid;
24
+ place-items: center;
25
+ flex-shrink: 0;
26
+ inline-size: var(--_size);
27
+ block-size: var(--_size);
28
+ border-radius: var(--medo-radius-full);
29
+ background-color: var(--_bg);
30
+ color: var(--_fg);
31
+ vertical-align: middle;
32
+ user-select: none;
33
+ }
34
+
35
+ /* Initials, image and icon share one grid cell: the image covers the initials once loaded. */
36
+ .medo-avatar > * {
37
+ grid-area: 1 / 1;
38
+ }
39
+
40
+ .medo-avatar--square {
41
+ border-radius: var(--_radius);
42
+ }
43
+
44
+ /* Sizes. Initials use the avatar text styles. */
45
+ .medo-avatar--xs {
46
+ --_size: var(--medo-space-5);
47
+ --_radius: var(--medo-radius-sm);
48
+ --_status: var(--medo-space-2);
49
+ font: var(--medo-typography-avatar-xs);
50
+ }
51
+ .medo-avatar--sm {
52
+ --_size: var(--medo-space-6);
53
+ --_radius: var(--medo-radius-sm);
54
+ --_status: var(--medo-space-2);
55
+ font: var(--medo-typography-avatar-sm);
56
+ }
57
+ .medo-avatar--md {
58
+ font: var(--medo-typography-avatar-md);
59
+ }
60
+ .medo-avatar--lg {
61
+ --_size: var(--medo-space-10);
62
+ font: var(--medo-typography-avatar-lg);
63
+ }
64
+ .medo-avatar--xl {
65
+ --_size: calc(var(--medo-space-12) + var(--medo-space-2)); /* 56 */
66
+ --_radius: var(--medo-radius-lg);
67
+ --_status: calc(var(--medo-space-3) + var(--medo-space-0-5)); /* 14 */
68
+ font: var(--medo-typography-avatar-xl);
69
+ }
70
+ .medo-avatar--2xl {
71
+ --_size: var(--medo-space-20);
72
+ --_radius: var(--medo-radius-lg);
73
+ --_status: calc(var(--medo-space-3) + var(--medo-space-0-5));
74
+ font: var(--medo-typography-avatar-2xl);
75
+ }
76
+
77
+ /* Tones: same person, same colour (picked from the id). */
78
+ .medo-avatar--blue {
79
+ --_bg: var(--medo-color-avatar-blue-surface);
80
+ --_fg: var(--medo-color-avatar-blue-text);
81
+ }
82
+ .medo-avatar--violet {
83
+ --_bg: var(--medo-color-avatar-violet-surface);
84
+ --_fg: var(--medo-color-avatar-violet-text);
85
+ }
86
+ .medo-avatar--pink {
87
+ --_bg: var(--medo-color-avatar-pink-surface);
88
+ --_fg: var(--medo-color-avatar-pink-text);
89
+ }
90
+ .medo-avatar--amber {
91
+ --_bg: var(--medo-color-avatar-amber-surface);
92
+ --_fg: var(--medo-color-avatar-amber-text);
93
+ }
94
+ .medo-avatar--green {
95
+ --_bg: var(--medo-color-avatar-green-surface);
96
+ --_fg: var(--medo-color-avatar-green-text);
97
+ }
98
+ .medo-avatar--teal {
99
+ --_bg: var(--medo-color-avatar-teal-surface);
100
+ --_fg: var(--medo-color-avatar-teal-text);
101
+ }
102
+
103
+ .medo-avatar__initials {
104
+ text-transform: uppercase;
105
+ line-height: 1;
106
+ }
107
+
108
+ .medo-avatar__icon {
109
+ display: inline-flex;
110
+ }
111
+
112
+ /* Icon: 12 / 14 / 16 / 20 / 28 / 40 px = 60 % at xs, 58 % at sm, 50 % from md. */
113
+ .medo-avatar__icon > svg {
114
+ inline-size: calc(var(--_size) * 0.5);
115
+ block-size: calc(var(--_size) * 0.5);
116
+ }
117
+ .medo-avatar--xs .medo-avatar__icon > svg {
118
+ inline-size: calc(var(--_size) * 0.6);
119
+ block-size: calc(var(--_size) * 0.6);
120
+ }
121
+ .medo-avatar--sm .medo-avatar__icon > svg {
122
+ inline-size: calc(var(--_size) * 7 / 12);
123
+ block-size: calc(var(--_size) * 7 / 12);
124
+ }
125
+
126
+ .medo-avatar__image {
127
+ inline-size: 100%;
128
+ block-size: 100%;
129
+ object-fit: cover;
130
+ border-radius: inherit;
131
+ }
132
+
133
+ /* 1 px inner border so light photos don't blend into the page. */
134
+ .medo-avatar--has-image::after {
135
+ content: '';
136
+ grid-area: 1 / 1;
137
+ inline-size: 100%;
138
+ block-size: 100%;
139
+ border-radius: inherit;
140
+ box-shadow: inset 0 0 0 1px var(--medo-color-avatar-image-border);
141
+ pointer-events: none;
142
+ }
143
+
144
+ /* ---------- Status (bottom right, 2 px ring in the surface colour) ---------- */
145
+
146
+ .medo-avatar__status {
147
+ position: absolute;
148
+ inset-block-end: 0;
149
+ inset-inline-end: 0;
150
+ box-sizing: border-box;
151
+ inline-size: var(--_status);
152
+ block-size: var(--_status);
153
+ border-radius: var(--medo-radius-full);
154
+ box-shadow: 0 0 0 2px var(--medo-color-surface-default);
155
+ }
156
+
157
+ .medo-avatar__status--online {
158
+ background-color: var(--medo-color-feedback-success-solid);
159
+ }
160
+ .medo-avatar__status--away {
161
+ background-color: var(--medo-color-feedback-warning-solid);
162
+ }
163
+ .medo-avatar__status--busy {
164
+ background-color: var(--medo-color-feedback-danger-solid);
165
+ }
166
+ .medo-avatar__status--offline {
167
+ background-color: var(--medo-color-border-strong);
168
+ }
169
+
170
+ /* ---------- Group: max 4 + „+N“, 25 % overlap, 2 px ring ---------- */
171
+
172
+ .medo-avatar-group {
173
+ display: inline-flex;
174
+ align-items: center;
175
+ isolation: isolate;
176
+ }
177
+
178
+ .medo-avatar-group > .medo-avatar {
179
+ box-shadow: 0 0 0 2px var(--medo-color-surface-default);
180
+ }
181
+
182
+ .medo-avatar-group > .medo-avatar + .medo-avatar {
183
+ margin-inline-start: calc(var(--_size) * -0.25);
184
+ }
185
+
186
+ .medo-avatar--more {
187
+ font: var(--medo-typography-label-sm);
188
+ padding: 0;
189
+ border: 0;
190
+ }
191
+
192
+ .medo-avatar-group--xs .medo-avatar--more,
193
+ .medo-avatar-group--sm .medo-avatar--more {
194
+ font: var(--medo-typography-label-xs);
195
+ }
196
+
197
+ button.medo-avatar--more {
198
+ cursor: pointer;
199
+ outline: none;
200
+ }
201
+ button.medo-avatar--more[data-hovered] {
202
+ background-image: linear-gradient(var(--medo-color-state-hover), var(--medo-color-state-hover));
203
+ }
204
+ button.medo-avatar--more[data-pressed] {
205
+ background-image: linear-gradient(var(--medo-color-state-pressed), var(--medo-color-state-pressed));
206
+ }
207
+ .medo-avatar-group > button.medo-avatar--more[data-focus-visible] {
208
+ box-shadow:
209
+ 0 0 0 2px var(--medo-color-surface-default),
210
+ var(--medo-shadow-focus-ring);
211
+ }
212
+
213
+ @media (forced-colors: active) {
214
+ .medo-avatar {
215
+ border: var(--medo-border-width-thin) solid CanvasText;
216
+ }
217
+ .medo-avatar__status {
218
+ forced-color-adjust: none;
219
+ background-color: CanvasText;
220
+ }
221
+ }