@gratiaos/ui 1.0.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 +243 -0
- package/README.md +170 -0
- package/dist/hooks/index.d.ts +2 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +2 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useMissingScrew.d.ts +40 -0
- package/dist/hooks/useMissingScrew.d.ts.map +1 -0
- package/dist/hooks/useMissingScrew.js +76 -0
- package/dist/hooks/useMissingScrew.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/pad/Button.d.ts +10 -0
- package/dist/pad/Button.d.ts.map +1 -0
- package/dist/pad/Button.js +7 -0
- package/dist/pad/Button.js.map +1 -0
- package/dist/pad/Card.d.ts +8 -0
- package/dist/pad/Card.d.ts.map +1 -0
- package/dist/pad/Card.js +3 -0
- package/dist/pad/Card.js.map +1 -0
- package/dist/primitives/badge.d.ts +66 -0
- package/dist/primitives/badge.d.ts.map +1 -0
- package/dist/primitives/badge.js +23 -0
- package/dist/primitives/badge.js.map +1 -0
- package/dist/primitives/button.d.ts +60 -0
- package/dist/primitives/button.d.ts.map +1 -0
- package/dist/primitives/button.js +39 -0
- package/dist/primitives/button.js.map +1 -0
- package/dist/primitives/card.d.ts +54 -0
- package/dist/primitives/card.d.ts.map +1 -0
- package/dist/primitives/card.js +11 -0
- package/dist/primitives/card.js.map +1 -0
- package/dist/primitives/field.d.ts +107 -0
- package/dist/primitives/field.d.ts.map +1 -0
- package/dist/primitives/field.js +154 -0
- package/dist/primitives/field.js.map +1 -0
- package/dist/primitives/pill.d.ts +59 -0
- package/dist/primitives/pill.d.ts.map +1 -0
- package/dist/primitives/pill.js +26 -0
- package/dist/primitives/pill.js.map +1 -0
- package/dist/primitives/slot.d.ts +7 -0
- package/dist/primitives/slot.d.ts.map +1 -0
- package/dist/primitives/slot.js +9 -0
- package/dist/primitives/slot.js.map +1 -0
- package/dist/primitives/toast.d.ts +125 -0
- package/dist/primitives/toast.d.ts.map +1 -0
- package/dist/primitives/toast.js +462 -0
- package/dist/primitives/toast.js.map +1 -0
- package/package.json +87 -0
- package/styles/badge.css +175 -0
- package/styles/base.css +7 -0
- package/styles/button.css +257 -0
- package/styles/card.css +195 -0
- package/styles/field.css +195 -0
- package/styles/pad.css +140 -0
- package/styles/pill.css +167 -0
- package/styles/theme.css +492 -0
- package/styles/toast.css +286 -0
package/styles/field.css
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
Garden UI — Field skin (opt‑in)
|
|
3
|
+
Whisper: "clarity first; comfort follows." 🌬️
|
|
4
|
+
|
|
5
|
+
Purpose
|
|
6
|
+
• Selector-only skin for the headless Field primitive.
|
|
7
|
+
• Driven by Garden tokens; no hardcoded hex.
|
|
8
|
+
|
|
9
|
+
Data API
|
|
10
|
+
• [data-ui='field'] — root
|
|
11
|
+
• [data-part='label|hint|description|error|control|optional']
|
|
12
|
+
• [data-state='error|disabled'] — this skin handles these; 'invalid' may map to 'error' upstream
|
|
13
|
+
• [data-required] on label — calm bullet (•) suffix
|
|
14
|
+
• [data-disabled] on root when control is disabled (preferred over data-state)
|
|
15
|
+
|
|
16
|
+
Notes
|
|
17
|
+
• Focus ring uses --ring-accent (falls back to accent mix).
|
|
18
|
+
• Control shell holds visuals; native input/textarea/select are reset inside it.
|
|
19
|
+
• Keep motion subtle; avoid intrusive animations in forms.
|
|
20
|
+
• Back-compat: this skin also honors [data-state='disabled'] and [data-state='error'] in addition to 'invalid'.
|
|
21
|
+
──────────────────────────────────────────────────────────── */
|
|
22
|
+
@layer components {
|
|
23
|
+
[data-ui='field'] {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: 0.375rem;
|
|
27
|
+
color: var(--text);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* parts */
|
|
31
|
+
[data-ui='field'] [data-part='label'] {
|
|
32
|
+
font-size: 0.875rem;
|
|
33
|
+
font-weight: 600;
|
|
34
|
+
color: var(--text);
|
|
35
|
+
}
|
|
36
|
+
[data-ui='field'] [data-part='label'] {
|
|
37
|
+
display: inline-flex;
|
|
38
|
+
align-items: baseline;
|
|
39
|
+
gap: 0.25rem;
|
|
40
|
+
}
|
|
41
|
+
[data-ui='field'] [data-part='optional'] {
|
|
42
|
+
margin-left: 0.375rem;
|
|
43
|
+
font-size: 0.75rem;
|
|
44
|
+
font-weight: 500;
|
|
45
|
+
color: var(--text-faint);
|
|
46
|
+
}
|
|
47
|
+
[data-ui='field'] [data-part='hint'] {
|
|
48
|
+
font-size: 0.75rem;
|
|
49
|
+
color: var(--text-faint);
|
|
50
|
+
}
|
|
51
|
+
[data-ui='field'] [data-part='description'] {
|
|
52
|
+
font-size: 0.875rem;
|
|
53
|
+
color: var(--text-subtle);
|
|
54
|
+
}
|
|
55
|
+
[data-ui='field'] [data-part='error'] {
|
|
56
|
+
font-size: 0.875rem;
|
|
57
|
+
color: var(--color-danger);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* input shell (when you wrap a native input inside) */
|
|
61
|
+
[data-ui='field'] [data-part='control'] {
|
|
62
|
+
/* control shell (keeps visuals on container; native element stays clean) */
|
|
63
|
+
display: block;
|
|
64
|
+
width: 100%;
|
|
65
|
+
border: 1px solid var(--color-border);
|
|
66
|
+
background: var(--color-surface);
|
|
67
|
+
color: var(--text);
|
|
68
|
+
border-radius: var(--radius-md, 0.375rem);
|
|
69
|
+
padding: 0.5rem 0.75rem;
|
|
70
|
+
transition: border-color 0.15s ease, background-color 0.15s ease, box-shadow 0.15s ease, outline-color 0.15s ease;
|
|
71
|
+
position: relative;
|
|
72
|
+
--_ring-size: var(--ring-size, 1px);
|
|
73
|
+
--_ring-color: var(--ring-accent, color-mix(in oklab, var(--color-accent) 85%, white 15%));
|
|
74
|
+
}
|
|
75
|
+
[data-ui='field'] [data-part='control']:hover {
|
|
76
|
+
border-color: color-mix(in oklab, var(--color-accent) 28%, var(--color-border));
|
|
77
|
+
}
|
|
78
|
+
[data-ui='field'] [data-part='control']:focus-within {
|
|
79
|
+
outline: none;
|
|
80
|
+
border-color: var(--color-accent);
|
|
81
|
+
box-shadow: 0 0 0 var(--_ring-size) var(--_ring-color), 0 2px 14px color-mix(in oklab, var(--color-accent) 10%, transparent);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Native control resets inside the shell */
|
|
85
|
+
[data-ui='field']
|
|
86
|
+
[data-part='control']
|
|
87
|
+
:is(
|
|
88
|
+
input[type='text'],
|
|
89
|
+
input[type='email'],
|
|
90
|
+
input[type='search'],
|
|
91
|
+
input[type='password'],
|
|
92
|
+
input[type='tel'],
|
|
93
|
+
input[type='url'],
|
|
94
|
+
input[type='number'],
|
|
95
|
+
textarea,
|
|
96
|
+
select
|
|
97
|
+
) {
|
|
98
|
+
background: transparent;
|
|
99
|
+
border: 0;
|
|
100
|
+
outline: none;
|
|
101
|
+
margin: 0;
|
|
102
|
+
padding: 0;
|
|
103
|
+
width: 100%;
|
|
104
|
+
min-width: 0; /* allow shrinking in flex/overflow layouts */
|
|
105
|
+
font: inherit;
|
|
106
|
+
line-height: 1.4;
|
|
107
|
+
color: var(--text);
|
|
108
|
+
caret-color: var(--color-accent);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Placeholder & selection */
|
|
112
|
+
[data-ui='field'] [data-part='control'] :is(input, textarea)::placeholder {
|
|
113
|
+
color: var(--text-faint);
|
|
114
|
+
opacity: 1;
|
|
115
|
+
}
|
|
116
|
+
[data-ui='field'] [data-part='control'] *::selection {
|
|
117
|
+
background: color-mix(in oklab, var(--color-accent) 22%, transparent);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* Textarea sizing */
|
|
121
|
+
[data-ui='field'] [data-part='control'] textarea {
|
|
122
|
+
resize: vertical;
|
|
123
|
+
min-height: 2.5rem;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Select tweaks */
|
|
127
|
+
[data-ui='field'] [data-part='control'] select {
|
|
128
|
+
appearance: none;
|
|
129
|
+
padding-right: 1.5rem; /* room for chevron */
|
|
130
|
+
background-image: linear-gradient(45deg, transparent 50%, currentColor 50%), linear-gradient(135deg, currentColor 50%, transparent 50%);
|
|
131
|
+
background-position: right 0.5rem center, right 0.25rem center;
|
|
132
|
+
background-size: 6px 6px, 6px 6px;
|
|
133
|
+
background-repeat: no-repeat;
|
|
134
|
+
color: var(--text);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Disabled/read-only native controls (mirrors root [data-disabled]) */
|
|
138
|
+
[data-ui='field'] [data-part='control'] :is(input, textarea, select):disabled,
|
|
139
|
+
[data-ui='field'][data-disabled] [data-part='control'] :is(input, textarea, select) {
|
|
140
|
+
cursor: not-allowed;
|
|
141
|
+
opacity: 0.7;
|
|
142
|
+
}
|
|
143
|
+
[data-ui='field'] [data-part='control'] :is(input, textarea, select)[readonly] {
|
|
144
|
+
opacity: 0.85;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* states */
|
|
148
|
+
[data-ui='field'][data-state='invalid'] [data-part='control'] {
|
|
149
|
+
border-color: var(--color-danger);
|
|
150
|
+
box-shadow: 0 0 0 var(--_ring-size) color-mix(in oklab, var(--color-danger) 60%, transparent);
|
|
151
|
+
}
|
|
152
|
+
/* alias: some callers emit 'error' instead of 'invalid' */
|
|
153
|
+
[data-ui='field'][data-state='error'] [data-part='control'] {
|
|
154
|
+
border-color: var(--color-danger);
|
|
155
|
+
box-shadow: 0 0 0 var(--_ring-size) color-mix(in oklab, var(--color-danger) 60%, transparent);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Disabled — prefer [data-disabled] on root; keep data-state='disabled' for back-compat */
|
|
159
|
+
[data-ui='field'][data-disabled] [data-part='label'] {
|
|
160
|
+
color: var(--text-subtle);
|
|
161
|
+
}
|
|
162
|
+
[data-ui='field'][data-disabled] [data-part='hint'],
|
|
163
|
+
[data-ui='field'][data-disabled] [data-part='description'] {
|
|
164
|
+
color: var(--text-faint);
|
|
165
|
+
}
|
|
166
|
+
[data-ui='field'][data-disabled] [data-part='control'] {
|
|
167
|
+
cursor: not-allowed;
|
|
168
|
+
opacity: 0.6;
|
|
169
|
+
background: color-mix(in oklab, var(--surface) 92%, var(--elev) 8%);
|
|
170
|
+
box-shadow: none;
|
|
171
|
+
outline: none;
|
|
172
|
+
}
|
|
173
|
+
/* Back-compat: support the old state hook */
|
|
174
|
+
[data-ui='field'][data-state='disabled'] [data-part='label'] {
|
|
175
|
+
color: var(--text-subtle);
|
|
176
|
+
}
|
|
177
|
+
[data-ui='field'][data-state='disabled'] [data-part='hint'],
|
|
178
|
+
[data-ui='field'][data-state='disabled'] [data-part='description'] {
|
|
179
|
+
color: var(--text-faint);
|
|
180
|
+
}
|
|
181
|
+
[data-ui='field'][data-state='disabled'] [data-part='control'] {
|
|
182
|
+
cursor: not-allowed;
|
|
183
|
+
opacity: 0.6;
|
|
184
|
+
background: color-mix(in oklab, var(--surface) 92%, var(--elev) 8%);
|
|
185
|
+
box-shadow: none;
|
|
186
|
+
outline: none;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* calm required marker (dot) */
|
|
190
|
+
[data-ui='field'] [data-part='label'][data-required]::after {
|
|
191
|
+
content: '•';
|
|
192
|
+
margin-left: 0.25rem;
|
|
193
|
+
opacity: 0.55;
|
|
194
|
+
}
|
|
195
|
+
}
|
package/styles/pad.css
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/* 1) Pad runtime mappings — inherit from global theme */
|
|
2
|
+
@layer base {
|
|
3
|
+
:root {
|
|
4
|
+
/* Surfaces & text */
|
|
5
|
+
--pad-surface: var(--color-surface);
|
|
6
|
+
--pad-elev: var(--color-elev);
|
|
7
|
+
--pad-border: var(--color-border);
|
|
8
|
+
--pad-text: var(--color-text);
|
|
9
|
+
--pad-text-muted: var(--color-muted);
|
|
10
|
+
--pad-text-subtle: var(--color-subtle);
|
|
11
|
+
--pad-text-faint: var(--color-faint);
|
|
12
|
+
|
|
13
|
+
/* Accent system */
|
|
14
|
+
--pad-accent: var(--color-accent);
|
|
15
|
+
--pad-onaccent: var(--color-on-accent);
|
|
16
|
+
|
|
17
|
+
/* Shape & depth */
|
|
18
|
+
--pad-radius: var(--sheet-radius, var(--radius-2xl));
|
|
19
|
+
--pad-shadow: var(--shadow-card, 0 6px 18px -6px rgb(0 0 0 / 0.2));
|
|
20
|
+
--pad-ring: var(--ring-accent, color-mix(in oklab, var(--pad-accent) 85%, white 15%));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* 2) Pad-scoped utilities */
|
|
25
|
+
@layer components {
|
|
26
|
+
.pad-surface {
|
|
27
|
+
background: var(--pad-surface);
|
|
28
|
+
color: var(--pad-text);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.pad-card {
|
|
32
|
+
background: var(--pad-elev);
|
|
33
|
+
color: var(--pad-text);
|
|
34
|
+
border: 1px solid var(--pad-border);
|
|
35
|
+
border-radius: var(--pad-radius);
|
|
36
|
+
box-shadow: var(--pad-shadow);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.pad-accent {
|
|
40
|
+
background: var(--pad-accent);
|
|
41
|
+
color: var(--pad-onaccent);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.pad-ring {
|
|
45
|
+
box-shadow: 0 0 0 3px var(--pad-ring);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* 3) Pad mood & depth utilities (Layered Synesthetic UI) */
|
|
50
|
+
@layer utilities {
|
|
51
|
+
/* Mood → glow intensity map (used by .mood-glow) */
|
|
52
|
+
[data-pad-mood='soft'] {
|
|
53
|
+
--pad-glow: 0.15;
|
|
54
|
+
}
|
|
55
|
+
[data-pad-mood='focused'] {
|
|
56
|
+
--pad-glow: 0.32;
|
|
57
|
+
}
|
|
58
|
+
[data-pad-mood='celebratory'] {
|
|
59
|
+
--pad-glow: 0.55;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Mood-responsive glow halo. Apply to any rounded container.
|
|
63
|
+
Tip: wrap your pad header/body in a `.mood-glow` element. */
|
|
64
|
+
.mood-glow {
|
|
65
|
+
position: relative;
|
|
66
|
+
}
|
|
67
|
+
.mood-glow::before {
|
|
68
|
+
content: '';
|
|
69
|
+
position: absolute;
|
|
70
|
+
inset: -2px;
|
|
71
|
+
border-radius: inherit;
|
|
72
|
+
pointer-events: none;
|
|
73
|
+
background: radial-gradient(120% 120% at 50% 50%, color-mix(in oklab, var(--pad-accent) 65%, transparent 35%) 0%, transparent 60%);
|
|
74
|
+
filter: blur(24px);
|
|
75
|
+
opacity: var(--pad-glow, 0.2);
|
|
76
|
+
transition: opacity var(--duration-normal, 220ms) var(--easing-soft, ease);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Mood ring — constant outline that scales with mood (pairs well with .mood-glow) */
|
|
80
|
+
.mood-ring {
|
|
81
|
+
position: relative;
|
|
82
|
+
}
|
|
83
|
+
.mood-ring::after {
|
|
84
|
+
content: '';
|
|
85
|
+
position: absolute;
|
|
86
|
+
inset: 0; /* hugs the element */
|
|
87
|
+
border-radius: inherit;
|
|
88
|
+
pointer-events: none;
|
|
89
|
+
/* width scales a touch with mood; color reuses --pad-ring */
|
|
90
|
+
box-shadow: 0 0 0 calc(2px + 2px * var(--pad-glow, 0.2)) var(--pad-ring);
|
|
91
|
+
opacity: clamp(0.25, var(--pad-glow, 0.35), 0.8);
|
|
92
|
+
transition: opacity var(--duration-normal, 220ms) var(--easing-soft, ease);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Whisper ring — depth-aware focus/hover outline */
|
|
96
|
+
.whisper-ring {
|
|
97
|
+
outline: none;
|
|
98
|
+
transition: box-shadow var(--duration-snug, 160ms) var(--easing-soft, ease);
|
|
99
|
+
}
|
|
100
|
+
[data-depth='0'] .whisper-ring:focus-visible,
|
|
101
|
+
[data-depth='0'] .whisper-ring:hover {
|
|
102
|
+
box-shadow: 0 0 0 0 var(--pad-ring);
|
|
103
|
+
}
|
|
104
|
+
[data-depth='1'] .whisper-ring:focus-visible,
|
|
105
|
+
[data-depth='1'] .whisper-ring:hover {
|
|
106
|
+
box-shadow: 0 0 0 2px var(--pad-ring);
|
|
107
|
+
}
|
|
108
|
+
[data-depth='2'] .whisper-ring:focus-visible,
|
|
109
|
+
[data-depth='2'] .whisper-ring:hover {
|
|
110
|
+
box-shadow: 0 0 0 3px var(--pad-ring);
|
|
111
|
+
}
|
|
112
|
+
[data-depth='3'] .whisper-ring:focus-visible,
|
|
113
|
+
[data-depth='3'] .whisper-ring:hover {
|
|
114
|
+
box-shadow: 0 0 0 5px var(--pad-ring);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* Wave visual — fades in with depth (for layered ornaments) */
|
|
118
|
+
.wave-visual {
|
|
119
|
+
opacity: 0.15;
|
|
120
|
+
transition: opacity var(--duration-normal, 220ms) var(--easing-soft, ease);
|
|
121
|
+
}
|
|
122
|
+
[data-depth='1'] .wave-visual {
|
|
123
|
+
opacity: 0.35;
|
|
124
|
+
}
|
|
125
|
+
[data-depth='2'] .wave-visual {
|
|
126
|
+
opacity: 0.6;
|
|
127
|
+
}
|
|
128
|
+
[data-depth='3'] .wave-visual {
|
|
129
|
+
opacity: 0.9;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* A11y: respect motion preferences */
|
|
133
|
+
@media (prefers-reduced-motion: reduce) {
|
|
134
|
+
.mood-glow::before,
|
|
135
|
+
.whisper-ring,
|
|
136
|
+
.wave-visual {
|
|
137
|
+
transition: none !important;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
package/styles/pill.css
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/* ─────────────────────────────────────────────────────────────
|
|
2
|
+
Garden UI — Pill skin (opt‑in)
|
|
3
|
+
Whisper: "labels should sit light, but speak clearly." 🌬️
|
|
4
|
+
|
|
5
|
+
Purpose
|
|
6
|
+
• Selector-only skin for the headless Pill primitive.
|
|
7
|
+
• Driven entirely by Garden tokens; no hardcoded hex.
|
|
8
|
+
|
|
9
|
+
Data API
|
|
10
|
+
• [data-ui='pill'] — root
|
|
11
|
+
• [data-variant='soft|solid|outline|subtle'] — visual weight
|
|
12
|
+
• [data-tone='subtle|accent|positive|warning|danger']
|
|
13
|
+
• [data-density='cozy|snug'] — vertical rhythm
|
|
14
|
+
• [data-depth='inherit|0|1|2|3'] — shadow depth passthrough (optional)
|
|
15
|
+
|
|
16
|
+
Notes
|
|
17
|
+
• Subtle variant uses neutral surface tokens (good for low-stakes tags).
|
|
18
|
+
• Variants map tone to color tokens; tones override the default accent.
|
|
19
|
+
• Keep animations out; density & colors should feel calm by default.
|
|
20
|
+
──────────────────────────────────────────────────────────── */
|
|
21
|
+
@layer components {
|
|
22
|
+
[data-ui='pill'] {
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 0.375rem;
|
|
26
|
+
border-radius: var(--radius-pill, 9999px);
|
|
27
|
+
font-weight: 500;
|
|
28
|
+
line-height: 1;
|
|
29
|
+
white-space: nowrap;
|
|
30
|
+
border: 1px solid transparent;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* Density — cozy (default) and snug (compact) */
|
|
34
|
+
[data-ui='pill'][data-density='cozy'] {
|
|
35
|
+
padding: 0.375rem 0.625rem;
|
|
36
|
+
font-size: 0.8125rem;
|
|
37
|
+
}
|
|
38
|
+
[data-ui='pill'][data-density='snug'] {
|
|
39
|
+
padding: 0.25rem 0.5rem;
|
|
40
|
+
font-size: 0.75rem;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[data-ui='pill'] [data-slot~='icon'] {
|
|
44
|
+
display: inline-flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Variants — default tone maps to accent palette */
|
|
50
|
+
[data-ui='pill'][data-variant='solid'] {
|
|
51
|
+
background: var(--color-accent);
|
|
52
|
+
color: var(--color-on-accent);
|
|
53
|
+
}
|
|
54
|
+
[data-ui='pill'][data-variant='soft'] {
|
|
55
|
+
background: color-mix(in oklab, var(--color-accent) 16%, transparent);
|
|
56
|
+
color: var(--color-accent);
|
|
57
|
+
border-color: color-mix(in oklab, var(--color-accent) 35%, transparent);
|
|
58
|
+
}
|
|
59
|
+
[data-ui='pill'][data-variant='outline'] {
|
|
60
|
+
background: transparent;
|
|
61
|
+
color: var(--color-accent);
|
|
62
|
+
border-color: var(--color-accent);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Tones — override accent mapping for positive|warning|danger */
|
|
66
|
+
[data-ui='pill'][data-tone='positive'][data-variant='solid'] {
|
|
67
|
+
background: var(--color-positive);
|
|
68
|
+
color: var(--color-on-accent);
|
|
69
|
+
}
|
|
70
|
+
[data-ui='pill'][data-tone='warning'][data-variant='solid'] {
|
|
71
|
+
background: var(--color-warning);
|
|
72
|
+
color: var(--color-on-accent);
|
|
73
|
+
}
|
|
74
|
+
[data-ui='pill'][data-tone='danger'][data-variant='solid'] {
|
|
75
|
+
background: var(--color-danger);
|
|
76
|
+
color: var(--color-on-accent);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
[data-ui='pill'][data-tone='positive'][data-variant='soft'] {
|
|
80
|
+
background: color-mix(in oklab, var(--color-positive) 16%, transparent);
|
|
81
|
+
color: var(--color-positive);
|
|
82
|
+
border-color: color-mix(in oklab, var(--color-positive) 35%, transparent);
|
|
83
|
+
}
|
|
84
|
+
[data-ui='pill'][data-tone='warning'][data-variant='soft'] {
|
|
85
|
+
background: color-mix(in oklab, var(--color-warning) 16%, transparent);
|
|
86
|
+
color: var(--color-warning);
|
|
87
|
+
border-color: color-mix(in oklab, var(--color-warning) 35%, transparent);
|
|
88
|
+
}
|
|
89
|
+
[data-ui='pill'][data-tone='danger'][data-variant='soft'] {
|
|
90
|
+
background: color-mix(in oklab, var(--color-danger) 16%, transparent);
|
|
91
|
+
color: var(--color-danger);
|
|
92
|
+
border-color: color-mix(in oklab, var(--color-danger) 35%, transparent);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
[data-ui='pill'][data-tone='positive'][data-variant='outline'] {
|
|
96
|
+
color: var(--color-positive);
|
|
97
|
+
border-color: var(--color-positive);
|
|
98
|
+
}
|
|
99
|
+
[data-ui='pill'][data-tone='warning'][data-variant='outline'] {
|
|
100
|
+
color: var(--color-warning);
|
|
101
|
+
border-color: var(--color-warning);
|
|
102
|
+
}
|
|
103
|
+
[data-ui='pill'][data-tone='danger'][data-variant='outline'] {
|
|
104
|
+
color: var(--color-danger);
|
|
105
|
+
border-color: var(--color-danger);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Subtle — neutral surface, gentle border; text uses neutral color token */
|
|
109
|
+
[data-ui='pill'][data-variant='subtle'] {
|
|
110
|
+
background: var(--color-fill-subtle);
|
|
111
|
+
color: var(--color-text);
|
|
112
|
+
border-color: color-mix(in oklab, var(--color-text) 12%, transparent);
|
|
113
|
+
}
|
|
114
|
+
/* Depth passthrough — opt‑in shadow for chip emphasis */
|
|
115
|
+
[data-ui='pill'][data-depth='inherit'] { box-shadow: var(--depth-shadow, var(--shadow-depth-1)); }
|
|
116
|
+
[data-ui='pill'][data-depth='0'] { box-shadow: var(--shadow-depth-0); }
|
|
117
|
+
[data-ui='pill'][data-depth='1'] { box-shadow: var(--shadow-depth-1); }
|
|
118
|
+
[data-ui='pill'][data-depth='2'] { box-shadow: var(--shadow-depth-2); }
|
|
119
|
+
[data-ui='pill'][data-depth='3'] { box-shadow: var(--shadow-depth-3); }
|
|
120
|
+
|
|
121
|
+
/* Tone → focus ring color variable (used by :focus-visible) */
|
|
122
|
+
[data-ui='pill'][data-tone='subtle'] { --ring-accent: color-mix(in oklab, var(--color-text) 80%, white 20%); }
|
|
123
|
+
[data-ui='pill'][data-tone='accent'] { --ring-accent: color-mix(in oklab, var(--color-accent) 85%, white 15%); }
|
|
124
|
+
[data-ui='pill'][data-tone='positive']{ --ring-accent: color-mix(in oklab, var(--color-positive) 85%, white 15%); }
|
|
125
|
+
[data-ui='pill'][data-tone='warning'] { --ring-accent: color-mix(in oklab, var(--color-warning) 85%, white 15%); }
|
|
126
|
+
[data-ui='pill'][data-tone='danger'] { --ring-accent: color-mix(in oklab, var(--color-danger) 85%, white 15%); }
|
|
127
|
+
|
|
128
|
+
/* Focus-visible — gentle tokenized outline for focusable pills */
|
|
129
|
+
[data-ui='pill']:focus-visible {
|
|
130
|
+
outline: 2px solid var(--ring-accent, color-mix(in oklab, var(--color-accent) 85%, white 15%));
|
|
131
|
+
outline-offset: 2px;
|
|
132
|
+
}
|
|
133
|
+
/* Optional: interactive hover/active soften (opt‑in or semantic elements) */
|
|
134
|
+
[data-ui='pill'][data-interactive='true'],
|
|
135
|
+
button[data-ui='pill'],
|
|
136
|
+
a[data-ui='pill'] {
|
|
137
|
+
transition: filter var(--duration-snug, 160ms) var(--ease-soft, ease);
|
|
138
|
+
}
|
|
139
|
+
[data-ui='pill'][data-interactive='true']:hover,
|
|
140
|
+
button[data-ui='pill']:hover,
|
|
141
|
+
a[data-ui='pill']:hover {
|
|
142
|
+
filter: brightness(1.01);
|
|
143
|
+
}
|
|
144
|
+
[data-ui='pill'][data-interactive='true']:active,
|
|
145
|
+
button[data-ui='pill']:active,
|
|
146
|
+
a[data-ui='pill']:active {
|
|
147
|
+
filter: brightness(0.99);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@media (prefers-reduced-motion: reduce) {
|
|
151
|
+
[data-ui='pill'][data-interactive='true'],
|
|
152
|
+
button[data-ui='pill'],
|
|
153
|
+
a[data-ui='pill'] {
|
|
154
|
+
transition: none;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* Disabled state — dim + no soften; supports native and ARIA patterns */
|
|
159
|
+
[data-ui='pill'][aria-disabled='true'],
|
|
160
|
+
button[data-ui='pill'][disabled],
|
|
161
|
+
a[data-ui='pill'][aria-disabled='true'] {
|
|
162
|
+
opacity: 0.55;
|
|
163
|
+
filter: none !important;
|
|
164
|
+
cursor: not-allowed;
|
|
165
|
+
pointer-events: none;
|
|
166
|
+
}
|
|
167
|
+
}
|