@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/toast.css
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/* ─────────────────────────────────────────────────────────────
|
|
3
|
+
Garden UI — Toast skin (headless primitive)
|
|
4
|
+
Whisper: "news should land softly, then move on." 🌬️
|
|
5
|
+
|
|
6
|
+
Purpose
|
|
7
|
+
• Selector-only skin for the headless Toast primitive.
|
|
8
|
+
• Tokens drive all visuals (no hardcoded hex).
|
|
9
|
+
• Calm by default; readable in both light/dark.
|
|
10
|
+
|
|
11
|
+
Data API (from the primitive)
|
|
12
|
+
• [data-ui="toast"] — container
|
|
13
|
+
◦ [data-position="bottom-center|top-right|top-center|bottom-right"]
|
|
14
|
+
• [data-role="stack"] — internal stack wrapper (grid)
|
|
15
|
+
• [data-ui="toast-item"] — individual toast
|
|
16
|
+
◦ [data-variant="neutral|positive|warning|danger"]
|
|
17
|
+
◦ optional [data-state="entering|leaving"] for transitions (future-friendly)
|
|
18
|
+
◦ children:
|
|
19
|
+
· [data-role="icon"] — optional leading emoji/glyph
|
|
20
|
+
· [data-role="content"] — wrapper for title/desc
|
|
21
|
+
· [data-role="title"] — strong line
|
|
22
|
+
· [data-role="desc"] — secondary line
|
|
23
|
+
· [data-role="message"] — single-line back-compat
|
|
24
|
+
|
|
25
|
+
A11y
|
|
26
|
+
• Items use role="status" + aria-atomic="true" so screen readers announce
|
|
27
|
+
the toast as a single unit. Timers pause on :hover / :focus-visible.
|
|
28
|
+
|
|
29
|
+
Tokens used
|
|
30
|
+
• Surface : --elev / --surface
|
|
31
|
+
• Text : --text / --text-subtle
|
|
32
|
+
• Accent : --color-accent / --color-positive / --color-warning / --color-danger
|
|
33
|
+
• Border : --border
|
|
34
|
+
• Motion : --animate-breathe, --duration-snug, --ease-soft
|
|
35
|
+
• Ring (focus): --ring-color (optional, falls back to accent mix)
|
|
36
|
+
|
|
37
|
+
Notes
|
|
38
|
+
• Keep the HTML minimal; this skin is resilient to the single-line legacy
|
|
39
|
+
form and the newer title+desc content model.
|
|
40
|
+
──────────────────────────────────────────────────────────── */
|
|
41
|
+
|
|
42
|
+
/* Container positions */
|
|
43
|
+
[data-ui='toast'][data-position='bottom-center'] {
|
|
44
|
+
position: fixed;
|
|
45
|
+
left: 0;
|
|
46
|
+
right: 0;
|
|
47
|
+
bottom: max(16px, env(safe-area-inset-bottom));
|
|
48
|
+
display: flex;
|
|
49
|
+
justify-content: center;
|
|
50
|
+
pointer-events: none;
|
|
51
|
+
z-index: 50;
|
|
52
|
+
}
|
|
53
|
+
[data-ui='toast'][data-position='top-right'] {
|
|
54
|
+
position: fixed;
|
|
55
|
+
right: 16px;
|
|
56
|
+
top: max(16px, env(safe-area-inset-top));
|
|
57
|
+
pointer-events: none;
|
|
58
|
+
z-index: 50;
|
|
59
|
+
}
|
|
60
|
+
[data-ui='toast'][data-position='top-center'] {
|
|
61
|
+
position: fixed;
|
|
62
|
+
left: 0;
|
|
63
|
+
right: 0;
|
|
64
|
+
top: max(16px, env(safe-area-inset-top));
|
|
65
|
+
display: flex;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
pointer-events: none;
|
|
68
|
+
z-index: 50;
|
|
69
|
+
}
|
|
70
|
+
[data-ui='toast'][data-position='bottom-right'] {
|
|
71
|
+
position: fixed;
|
|
72
|
+
right: 16px;
|
|
73
|
+
bottom: max(16px, env(safe-area-inset-bottom));
|
|
74
|
+
pointer-events: none;
|
|
75
|
+
z-index: 50;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/* Stack layout */
|
|
79
|
+
[data-ui='toast'] [data-role='stack'] {
|
|
80
|
+
display: grid;
|
|
81
|
+
gap: 8px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Stack alignment helpers per position */
|
|
85
|
+
[data-ui='toast'][data-position='top-right'] [data-role='stack'],
|
|
86
|
+
[data-ui='toast'][data-position='bottom-right'] [data-role='stack'] {
|
|
87
|
+
justify-items: end;
|
|
88
|
+
}
|
|
89
|
+
[data-ui='toast'][data-position='bottom-center'] [data-role='stack'],
|
|
90
|
+
[data-ui='toast'][data-position='top-center'] [data-role='stack'] {
|
|
91
|
+
justify-items: center;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* Burst protection — cap stack height & allow smooth scroll on overflow */
|
|
95
|
+
[data-ui='toast'] [data-role='stack'] {
|
|
96
|
+
/* Cap visible height; avoid scroll for normal usage */
|
|
97
|
+
max-height: min(40vh, 50svh);
|
|
98
|
+
overflow-y: auto;
|
|
99
|
+
overscroll-behavior: contain;
|
|
100
|
+
-webkit-overflow-scrolling: touch;
|
|
101
|
+
scroll-behavior: smooth;
|
|
102
|
+
padding-block: 2px; /* tiny cushion for focus ring / last item */
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/* Tighter caps per position (right stacks typically shorter) */
|
|
106
|
+
[data-ui='toast'][data-position='top-right'] [data-role='stack'],
|
|
107
|
+
[data-ui='toast'][data-position='bottom-right'] [data-role='stack'] {
|
|
108
|
+
max-height: min(36vh, 44svh);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/* Subtle scrollbar styling */
|
|
112
|
+
[data-ui='toast'] [data-role='stack']::-webkit-scrollbar {
|
|
113
|
+
width: 8px;
|
|
114
|
+
}
|
|
115
|
+
[data-ui='toast'] [data-role='stack']::-webkit-scrollbar-thumb {
|
|
116
|
+
background: color-mix(in oklab, var(--color-text) 18%, transparent);
|
|
117
|
+
border-radius: 8px;
|
|
118
|
+
}
|
|
119
|
+
[data-ui='toast'] [data-role='stack']::-webkit-scrollbar-thumb:hover {
|
|
120
|
+
background: color-mix(in oklab, var(--color-text) 28%, transparent);
|
|
121
|
+
}
|
|
122
|
+
[data-ui='toast'] [data-role='stack']::-webkit-scrollbar-track {
|
|
123
|
+
background: transparent;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Firefox */
|
|
127
|
+
[data-ui='toast'] [data-role='stack'] {
|
|
128
|
+
scrollbar-width: thin;
|
|
129
|
+
scrollbar-color: color-mix(in oklab, var(--color-text) 22%, transparent) transparent;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Item skin */
|
|
133
|
+
[data-ui='toast-item'] {
|
|
134
|
+
pointer-events: auto;
|
|
135
|
+
display: flex;
|
|
136
|
+
align-items: center;
|
|
137
|
+
gap: 10px;
|
|
138
|
+
background: var(--elev);
|
|
139
|
+
color: var(--text);
|
|
140
|
+
border: 1px solid var(--border);
|
|
141
|
+
border-left: 3px solid var(--bar, var(--color-accent));
|
|
142
|
+
border-radius: var(--radius-pill);
|
|
143
|
+
padding: 8px 12px;
|
|
144
|
+
box-shadow: var(--shadow-card-ambient);
|
|
145
|
+
max-width: min(92vw, 520px);
|
|
146
|
+
margin: 0 auto;
|
|
147
|
+
animation: var(--animate-breathe);
|
|
148
|
+
transition: opacity var(--duration-snug) var(--ease-soft), transform var(--duration-snug) var(--ease-soft);
|
|
149
|
+
will-change: opacity, transform;
|
|
150
|
+
cursor: pointer;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Leading icon (optional) — keeps emoji/glyphs neatly aligned */
|
|
154
|
+
[data-ui='toast-item'] [data-role='icon'] {
|
|
155
|
+
display: inline-flex;
|
|
156
|
+
align-items: center;
|
|
157
|
+
justify-content: center;
|
|
158
|
+
flex: 0 0 auto; /* do not shrink */
|
|
159
|
+
width: 18px;
|
|
160
|
+
height: 18px;
|
|
161
|
+
font-size: 14px; /* emoji size */
|
|
162
|
+
line-height: 1;
|
|
163
|
+
opacity: 0.95;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Content layout — single line by default; becomes vertical when title/desc present */
|
|
167
|
+
[data-ui='toast-item'] [data-role='content'] {
|
|
168
|
+
display: flex;
|
|
169
|
+
flex-direction: column;
|
|
170
|
+
align-items: flex-start;
|
|
171
|
+
gap: 2px;
|
|
172
|
+
min-width: 0; /* allow text wrap */
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Typography */
|
|
176
|
+
[data-ui='toast-item'] [data-role='title'] {
|
|
177
|
+
font-size: 14px;
|
|
178
|
+
font-weight: 600;
|
|
179
|
+
line-height: 1.2;
|
|
180
|
+
color: var(--text);
|
|
181
|
+
}
|
|
182
|
+
[data-ui='toast-item'] [data-role='desc'],
|
|
183
|
+
[data-ui='toast-item'] [data-role='message'] {
|
|
184
|
+
font-size: 13px;
|
|
185
|
+
line-height: 1.25;
|
|
186
|
+
color: var(--text-subtle);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/* Clamp long descriptions to ~3 lines */
|
|
190
|
+
[data-ui='toast-item'] [data-role='desc'] {
|
|
191
|
+
display: -webkit-box;
|
|
192
|
+
-webkit-line-clamp: 3;
|
|
193
|
+
-webkit-box-orient: vertical;
|
|
194
|
+
overflow: hidden;
|
|
195
|
+
word-break: break-word;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* Single-line message with ellipsis */
|
|
199
|
+
[data-ui='toast-item'] [data-role='message'] {
|
|
200
|
+
white-space: nowrap;
|
|
201
|
+
overflow: hidden;
|
|
202
|
+
text-overflow: ellipsis;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Back-compat: when only [data-role='message'] exists (no content wrapper) */
|
|
206
|
+
[data-ui='toast-item'] > [data-role='message'] {
|
|
207
|
+
font-size: 14px;
|
|
208
|
+
color: var(--text);
|
|
209
|
+
white-space: nowrap;
|
|
210
|
+
overflow: hidden;
|
|
211
|
+
text-overflow: ellipsis;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/* Variants set the accent bar color */
|
|
215
|
+
[data-ui='toast-item'][data-variant='neutral'] {
|
|
216
|
+
--bar: var(--color-accent);
|
|
217
|
+
}
|
|
218
|
+
[data-ui='toast-item'][data-variant='positive'] {
|
|
219
|
+
--bar: var(--color-positive);
|
|
220
|
+
}
|
|
221
|
+
[data-ui='toast-item'][data-variant='warning'] {
|
|
222
|
+
--bar: var(--color-warning);
|
|
223
|
+
}
|
|
224
|
+
[data-ui='toast-item'][data-variant='danger'] {
|
|
225
|
+
--bar: var(--color-danger);
|
|
226
|
+
}
|
|
227
|
+
/* Alias — info maps to accent (DX sugar) */
|
|
228
|
+
[data-ui='toast-item'][data-variant='info'] {
|
|
229
|
+
--bar: var(--color-accent);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Transient state — gentle entrance */
|
|
233
|
+
[data-ui='toast-item'][data-state='entering'] {
|
|
234
|
+
opacity: 0;
|
|
235
|
+
transform: translateY(-4px) scale(0.98);
|
|
236
|
+
/* The base rule already defines transition; we just set the starting pose.
|
|
237
|
+
When JS removes [data-state='entering'], it eases to opacity:1 / transform:none. */
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/* Transient state — graceful exit */
|
|
241
|
+
[data-ui='toast-item'][data-state='leaving'] {
|
|
242
|
+
opacity: 0;
|
|
243
|
+
transform: translateY(4px) scale(0.98);
|
|
244
|
+
transition: opacity var(--duration-snug) var(--ease-soft), transform var(--duration-snug) var(--ease-soft);
|
|
245
|
+
pointer-events: none; /* avoid clicks while fading */
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/* Position-aware vectors — slide down from top, up from bottom */
|
|
249
|
+
[data-ui='toast'][data-position='top-right'] [data-ui='toast-item'][data-state='entering'],
|
|
250
|
+
[data-ui='toast'][data-position='top-center'] [data-ui='toast-item'][data-state='entering'] {
|
|
251
|
+
transform: translateY(-6px) scale(0.98);
|
|
252
|
+
}
|
|
253
|
+
[data-ui='toast'][data-position='top-right'] [data-ui='toast-item'][data-state='leaving'],
|
|
254
|
+
[data-ui='toast'][data-position='top-center'] [data-ui='toast-item'][data-state='leaving'] {
|
|
255
|
+
transform: translateY(-6px) scale(0.98);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
[data-ui='toast'][data-position='bottom-right'] [data-ui='toast-item'][data-state='entering'],
|
|
259
|
+
[data-ui='toast'][data-position='bottom-center'] [data-ui='toast-item'][data-state='entering'] {
|
|
260
|
+
transform: translateY(6px) scale(0.98);
|
|
261
|
+
}
|
|
262
|
+
[data-ui='toast'][data-position='bottom-right'] [data-ui='toast-item'][data-state='leaving'],
|
|
263
|
+
[data-ui='toast'][data-position='bottom-center'] [data-ui='toast-item'][data-state='leaving'] {
|
|
264
|
+
transform: translateY(6px) scale(0.98);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/* Focus visibility — match ring semantics used across primitives */
|
|
268
|
+
[data-ui='toast-item']:focus-visible {
|
|
269
|
+
outline: 2px solid var(--ring-color, color-mix(in oklab, var(--color-accent) 60%, transparent));
|
|
270
|
+
outline-offset: 2px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/* Motion accessibility */
|
|
274
|
+
@media (prefers-reduced-motion: reduce) {
|
|
275
|
+
[data-ui='toast-item'] {
|
|
276
|
+
animation: none;
|
|
277
|
+
}
|
|
278
|
+
[data-ui='toast-item'][data-state='leaving'] {
|
|
279
|
+
transform: none;
|
|
280
|
+
transition: opacity var(--duration-snug) var(--ease-soft);
|
|
281
|
+
}
|
|
282
|
+
[data-ui='toast-item'][data-state='entering'] {
|
|
283
|
+
transform: none;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|