@human-synthesis/norns-ui 0.0.3 → 0.0.6
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 +81 -225
- package/package.json +13 -3
- package/src/auto-import.js +81 -19
- package/src/components/Accordion.n +39 -0
- package/src/components/Audio.n +24 -0
- package/src/components/Autocomplete.n +134 -0
- package/src/components/Avatar.n +27 -0
- package/src/components/AvatarGroup.n +25 -0
- package/src/components/Badge.n +20 -0
- package/src/components/Banner.n +25 -0
- package/src/components/Breadcrumbs.n +22 -0
- package/src/components/Btn.n +29 -8
- package/src/components/ButtonGroup.n +14 -0
- package/src/components/Calendar.n +153 -0
- package/src/components/Card.n +34 -0
- package/src/components/Carousel.n +66 -0
- package/src/components/Chip.n +27 -0
- package/src/components/Collapsible.n +29 -0
- package/src/components/ColorPicker.n +62 -0
- package/src/components/ContextMenu.n +67 -0
- package/src/components/CopyButton.n +50 -0
- package/src/components/DataTable.n +61 -0
- package/src/components/DatePicker.n +56 -0
- package/src/components/DateRangePicker.n +47 -0
- package/src/components/Dialog.n +35 -22
- package/src/components/Dropdown.n +54 -23
- package/src/components/GradientText.n +21 -0
- package/src/components/Header.n +23 -0
- package/src/components/HeroBanner.n +37 -0
- package/src/components/HierarchicalMenu.n +38 -0
- package/src/components/Icon.n +16 -0
- package/src/components/Image.n +31 -0
- package/src/components/MegaMenu.n +36 -0
- package/src/components/MultiSelect.n +158 -0
- package/src/components/NumberInput.n +49 -0
- package/src/components/OtpField.n +67 -0
- package/src/components/Pagination.n +73 -0
- package/src/components/Popover.n +30 -15
- package/src/components/Progress.n +26 -0
- package/src/components/ProgressCircular.n +52 -0
- package/src/components/RippleButton.n +56 -0
- package/src/components/ScrollArea.n +20 -0
- package/src/components/Separator.n +12 -0
- package/src/components/Sheet.n +36 -22
- package/src/components/ShinyButton.n +36 -0
- package/src/components/Skeleton.n +27 -0
- package/src/components/Stepper.n +35 -0
- package/src/components/Surface.n +10 -0
- package/src/components/Tabs.n +39 -13
- package/src/components/TagsInput.n +66 -0
- package/src/components/ThemeToggler.n +43 -0
- package/src/components/TimePicker.n +153 -0
- package/src/components/Timeline.n +27 -0
- package/src/components/ToggleButton.n +35 -0
- package/src/components/ToggleButtonGroup.n +54 -0
- package/src/components/Toolbar.n +15 -0
- package/src/components/Tooltip.n +52 -19
- package/src/components/Tree.n +57 -0
- package/src/components/Uploader.n +88 -0
- package/src/components/Video.n +26 -0
- package/src/index.js +64 -1
- package/src/lib/behaviors/clickOutside.svelte.js +54 -0
- package/src/lib/behaviors/escape.svelte.js +36 -0
- package/src/lib/behaviors/floating.svelte.js +137 -0
- package/src/lib/behaviors/focusTrap.svelte.js +80 -0
- package/src/lib/behaviors/index.js +14 -0
- package/src/lib/behaviors/portal.svelte.js +32 -0
- package/src/lib/behaviors/rovingTabindex.svelte.js +76 -0
- package/src/lib/behaviors/scrollLock.svelte.js +56 -0
- package/src/motion/AnimatedNumber.n +55 -0
- package/src/motion/GradientBackground.n +25 -0
- package/src/motion/LiquidButton.n +48 -0
- package/src/motion/Reveal.n +37 -0
- package/src/motion/Sparkles.n +53 -0
- package/src/motion/index.js +18 -0
- package/src/styles/atoms.css +1481 -223
- package/src/styles/tokens.css +204 -40
- package/src/types/Accordion.d.ts +17 -0
- package/src/types/AnimatedNumber.d.ts +15 -0
- package/src/types/Audio.d.ts +18 -0
- package/src/types/Autocomplete.d.ts +17 -0
- package/src/types/Avatar.d.ts +14 -0
- package/src/types/AvatarGroup.d.ts +15 -0
- package/src/types/Badge.d.ts +14 -0
- package/src/types/Banner.d.ts +15 -0
- package/src/types/Breadcrumbs.d.ts +15 -0
- package/src/types/Btn.d.ts +10 -0
- package/src/types/ButtonGroup.d.ts +10 -0
- package/src/types/Calendar.d.ts +20 -0
- package/src/types/Card.d.ts +19 -0
- package/src/types/Carousel.d.ts +23 -0
- package/src/types/Chip.d.ts +12 -0
- package/src/types/Collapsible.d.ts +13 -0
- package/src/types/ColorPicker.d.ts +15 -0
- package/src/types/ContextMenu.d.ts +24 -0
- package/src/types/CopyButton.d.ts +16 -0
- package/src/types/DataTable.d.ts +27 -0
- package/src/types/DatePicker.d.ts +23 -0
- package/src/types/DateRangePicker.d.ts +17 -0
- package/src/types/Dialog.d.ts +4 -0
- package/src/types/Dropdown.d.ts +2 -1
- package/src/types/GradientBackground.d.ts +14 -0
- package/src/types/GradientText.d.ts +19 -0
- package/src/types/Header.d.ts +12 -0
- package/src/types/HeroBanner.d.ts +17 -0
- package/src/types/HierarchicalMenu.d.ts +20 -0
- package/src/types/Icon.d.ts +21 -0
- package/src/types/Image.d.ts +15 -0
- package/src/types/LiquidButton.d.ts +15 -0
- package/src/types/MegaMenu.d.ts +29 -0
- package/src/types/MultiSelect.d.ts +16 -0
- package/src/types/NumberInput.d.ts +17 -0
- package/src/types/OtpField.d.ts +13 -0
- package/src/types/Pagination.d.ts +13 -0
- package/src/types/Progress.d.ts +14 -0
- package/src/types/ProgressCircular.d.ts +14 -0
- package/src/types/Reveal.d.ts +20 -0
- package/src/types/RippleButton.d.ts +15 -0
- package/src/types/ScrollArea.d.ts +11 -0
- package/src/types/Separator.d.ts +9 -0
- package/src/types/Sheet.d.ts +3 -0
- package/src/types/ShinyButton.d.ts +15 -0
- package/src/types/Skeleton.d.ts +13 -0
- package/src/types/Sparkles.d.ts +13 -0
- package/src/types/Stepper.d.ts +19 -0
- package/src/types/Surface.d.ts +10 -0
- package/src/types/Tabs.d.ts +2 -0
- package/src/types/TagsInput.d.ts +17 -0
- package/src/types/ThemeToggler.d.ts +17 -0
- package/src/types/TimePicker.d.ts +20 -0
- package/src/types/Timeline.d.ts +17 -0
- package/src/types/ToggleButton.d.ts +16 -0
- package/src/types/ToggleButtonGroup.d.ts +21 -0
- package/src/types/Toolbar.d.ts +12 -0
- package/src/types/Tooltip.d.ts +3 -0
- package/src/types/Tree.d.ts +20 -0
- package/src/types/Uploader.d.ts +15 -0
- package/src/types/Video.d.ts +20 -0
package/src/styles/atoms.css
CHANGED
|
@@ -1,33 +1,198 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Norns UI — component atom classes.
|
|
3
3
|
*
|
|
4
|
-
* Pure Tailwind utility
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Pure Tailwind utility composition via `@layer components`. No JS, no Svelte.
|
|
5
|
+
* Atoms reference role tokens (and the new elevation/motion/icon-btn tokens
|
|
6
|
+
* in tokens.css), never raw color shades. That's how light/dark theme swap
|
|
7
|
+
* works through a single point of change.
|
|
7
8
|
*
|
|
8
|
-
* Naming
|
|
9
|
+
* Naming: `<atom>-<variant>` and `<atom>-<size>`. Predictable, AI-friendly.
|
|
10
|
+
*
|
|
11
|
+
* Design rules — every atom obeys these unless it has a documented reason:
|
|
12
|
+
* 1. Radius: `--ui-radius` for floating panels & full-size controls,
|
|
13
|
+
* `--ui-radius-sm` for items inside menus, `--ui-radius-lg` only for
|
|
14
|
+
* Dialog and HeroBanner.
|
|
15
|
+
* 2. Hover on any interactive surface uses `bg-bg-muted`. No exceptions.
|
|
16
|
+
* 3. Focus uses the `--ui-focus-ring` shadow on `:focus-visible`.
|
|
17
|
+
* 4. Transitions use `--ui-motion-fast` + `--ui-motion-ease`.
|
|
18
|
+
* 5. Shadows use `--ui-elev-{1,2,3}`. No raw shadow utilities.
|
|
9
19
|
*/
|
|
10
20
|
|
|
11
21
|
@reference 'tailwindcss';
|
|
12
22
|
|
|
23
|
+
@layer base {
|
|
24
|
+
html {
|
|
25
|
+
font-family: var(--font-sans);
|
|
26
|
+
color: var(--color-fg);
|
|
27
|
+
background-color: var(--color-bg);
|
|
28
|
+
font-feature-settings: 'ss01';
|
|
29
|
+
}
|
|
30
|
+
body {
|
|
31
|
+
color: var(--color-fg);
|
|
32
|
+
background-color: var(--color-bg);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@media (prefers-reduced-motion: reduce) {
|
|
36
|
+
*,
|
|
37
|
+
*::before,
|
|
38
|
+
*::after {
|
|
39
|
+
animation-duration: 0.01ms !important;
|
|
40
|
+
animation-iteration-count: 1 !important;
|
|
41
|
+
transition-duration: 0.01ms !important;
|
|
42
|
+
scroll-behavior: auto !important;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* Heading hierarchy */
|
|
47
|
+
h1 { @apply text-4xl font-bold tracking-tight leading-tight; }
|
|
48
|
+
h2 { @apply text-3xl font-semibold tracking-tight leading-tight; }
|
|
49
|
+
h3 { @apply text-2xl font-semibold tracking-tight leading-snug; }
|
|
50
|
+
h4 { @apply text-xl font-semibold leading-snug; }
|
|
51
|
+
h5 { @apply text-lg font-semibold leading-snug; }
|
|
52
|
+
h6 { @apply text-base font-semibold; }
|
|
53
|
+
|
|
54
|
+
code {
|
|
55
|
+
font-family: var(--font-mono);
|
|
56
|
+
@apply text-[0.9em] px-1 py-0.5;
|
|
57
|
+
background-color: var(--color-bg-muted);
|
|
58
|
+
color: var(--color-fg);
|
|
59
|
+
border-radius: var(--ui-radius-sm);
|
|
60
|
+
}
|
|
61
|
+
pre {
|
|
62
|
+
font-family: var(--font-mono);
|
|
63
|
+
@apply text-sm p-3 overflow-x-auto;
|
|
64
|
+
background-color: var(--color-bg-muted);
|
|
65
|
+
color: var(--color-fg);
|
|
66
|
+
border-radius: var(--ui-radius);
|
|
67
|
+
}
|
|
68
|
+
pre code {
|
|
69
|
+
@apply p-0 bg-transparent;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
kbd {
|
|
73
|
+
font-family: var(--font-mono);
|
|
74
|
+
@apply text-xs px-1.5 py-0.5 border;
|
|
75
|
+
background-color: var(--color-bg-muted);
|
|
76
|
+
border-color: var(--color-border);
|
|
77
|
+
color: var(--color-fg);
|
|
78
|
+
border-radius: var(--ui-radius-sm);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
hr { border-color: var(--color-border); }
|
|
82
|
+
}
|
|
83
|
+
|
|
13
84
|
@layer components {
|
|
14
|
-
/*
|
|
85
|
+
/* ============================================================ */
|
|
86
|
+
/* Shared mixins */
|
|
87
|
+
/* ============================================================ */
|
|
88
|
+
|
|
89
|
+
/* `.ui-ring` — single canonical focus indicator. Components compose:
|
|
90
|
+
* .btn { ... }
|
|
91
|
+
* .btn:focus-visible { box-shadow: var(--ui-focus-ring); }
|
|
92
|
+
* or apply this helper class directly. */
|
|
93
|
+
.ui-ring:focus-visible {
|
|
94
|
+
outline: none;
|
|
95
|
+
box-shadow: var(--ui-focus-ring);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/* `.surface-elevated` — public class for Popover, Dropdown, Tooltip-rich,
|
|
99
|
+
* Dialog, Sheet, Toast, nav-menu-content, etc. Each of those atoms also
|
|
100
|
+
* extends this rule via selector lists below, so consumers can apply
|
|
101
|
+
* either name. */
|
|
102
|
+
.surface-elevated,
|
|
103
|
+
.popover-content,
|
|
104
|
+
.dropdown-content,
|
|
105
|
+
.tooltip-rich,
|
|
106
|
+
.dialog-content,
|
|
107
|
+
.sheet-content,
|
|
108
|
+
.toast,
|
|
109
|
+
.nav-menu-content {
|
|
110
|
+
background-color: var(--color-bg-elevated);
|
|
111
|
+
color: var(--color-fg);
|
|
112
|
+
border: 1px solid var(--color-border);
|
|
113
|
+
border-radius: var(--ui-radius);
|
|
114
|
+
box-shadow: var(--ui-elev-2);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* `.control-base` — public alias. Form-control atoms below extend this
|
|
118
|
+
* rule via selector lists, so `.input`, `.textarea`, `.select`, etc. all
|
|
119
|
+
* share one source of truth for size/padding/border/focus/disabled. */
|
|
120
|
+
.control-base,
|
|
121
|
+
.input,
|
|
122
|
+
.textarea,
|
|
123
|
+
.select,
|
|
124
|
+
.color-picker-text,
|
|
125
|
+
.date-picker-trigger {
|
|
126
|
+
@apply block w-full text-sm leading-none;
|
|
127
|
+
background-color: var(--color-bg);
|
|
128
|
+
color: var(--color-fg);
|
|
129
|
+
border: 1px solid var(--color-border-strong);
|
|
130
|
+
border-radius: var(--ui-radius);
|
|
131
|
+
height: var(--ui-h-md);
|
|
132
|
+
padding-inline: 0.75rem;
|
|
133
|
+
transition: border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
134
|
+
background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
135
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
136
|
+
}
|
|
137
|
+
.control-base::placeholder,
|
|
138
|
+
.input::placeholder,
|
|
139
|
+
.textarea::placeholder,
|
|
140
|
+
.select::placeholder { color: var(--color-fg-subtle); }
|
|
141
|
+
.control-base:focus-visible,
|
|
142
|
+
.input:focus-visible,
|
|
143
|
+
.textarea:focus-visible,
|
|
144
|
+
.select:focus-visible,
|
|
145
|
+
.date-picker-trigger:focus-visible {
|
|
146
|
+
outline: none;
|
|
147
|
+
border-color: var(--color-ring);
|
|
148
|
+
box-shadow: var(--ui-focus-ring);
|
|
149
|
+
}
|
|
150
|
+
.control-base:disabled,
|
|
151
|
+
.input:disabled,
|
|
152
|
+
.textarea:disabled,
|
|
153
|
+
.select:disabled {
|
|
154
|
+
@apply cursor-not-allowed opacity-70;
|
|
155
|
+
background-color: var(--color-bg-muted);
|
|
156
|
+
}
|
|
157
|
+
.control-err,
|
|
158
|
+
.input-err,
|
|
159
|
+
.textarea-err,
|
|
160
|
+
.select-err {
|
|
161
|
+
border-color: var(--color-danger-500);
|
|
162
|
+
}
|
|
163
|
+
.control-err:focus-visible,
|
|
164
|
+
.input-err:focus-visible,
|
|
165
|
+
.textarea-err:focus-visible,
|
|
166
|
+
.select-err:focus-visible {
|
|
167
|
+
border-color: var(--color-danger-500);
|
|
168
|
+
box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-danger-500);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* ============================================================ */
|
|
172
|
+
/* Button */
|
|
173
|
+
/* ============================================================ */
|
|
15
174
|
.btn {
|
|
16
|
-
@apply inline-flex items-center justify-center gap-2
|
|
17
|
-
@apply
|
|
18
|
-
@apply select-none cursor-pointer;
|
|
175
|
+
@apply inline-flex items-center justify-center gap-2 text-sm font-medium leading-none whitespace-nowrap;
|
|
176
|
+
@apply select-none cursor-pointer relative overflow-hidden;
|
|
19
177
|
@apply disabled:cursor-not-allowed disabled:opacity-60;
|
|
20
|
-
|
|
178
|
+
border-radius: var(--ui-radius);
|
|
21
179
|
height: var(--ui-h-md);
|
|
22
180
|
padding-inline: 0.875rem;
|
|
23
|
-
|
|
181
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
182
|
+
color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
183
|
+
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
184
|
+
transform var(--ui-motion-fast) var(--ui-motion-ease),
|
|
185
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease),
|
|
186
|
+
opacity var(--ui-motion-fast) var(--ui-motion-ease);
|
|
187
|
+
}
|
|
188
|
+
.btn:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
189
|
+
.btn:not(:disabled):active { transform: scale(0.97); }
|
|
24
190
|
|
|
25
191
|
.btn-sm {
|
|
26
192
|
@apply text-xs;
|
|
27
193
|
height: var(--ui-h-sm);
|
|
28
194
|
padding-inline: 0.625rem;
|
|
29
195
|
}
|
|
30
|
-
|
|
31
196
|
.btn-lg {
|
|
32
197
|
@apply text-base;
|
|
33
198
|
height: var(--ui-h-lg);
|
|
@@ -35,330 +200,1423 @@
|
|
|
35
200
|
}
|
|
36
201
|
|
|
37
202
|
.btn-primary {
|
|
38
|
-
|
|
203
|
+
background-color: var(--color-primary-600);
|
|
204
|
+
color: var(--color-fg-on-primary);
|
|
39
205
|
}
|
|
206
|
+
.btn-primary:hover { background-color: var(--color-primary-700); }
|
|
207
|
+
.btn-primary:active { background-color: var(--color-primary-800); }
|
|
40
208
|
|
|
41
209
|
.btn-secondary {
|
|
42
|
-
|
|
210
|
+
background-color: var(--color-bg-muted);
|
|
211
|
+
color: var(--color-fg);
|
|
212
|
+
border: 1px solid var(--color-border);
|
|
213
|
+
}
|
|
214
|
+
.btn-secondary:hover { background-color: var(--color-bg-subtle); }
|
|
215
|
+
.btn-secondary:active { background-color: var(--color-border); }
|
|
216
|
+
.btn-secondary[data-pressed='true'] {
|
|
217
|
+
background-color: var(--color-border);
|
|
218
|
+
border-color: var(--color-border-strong);
|
|
43
219
|
}
|
|
44
220
|
|
|
45
221
|
.btn-ghost {
|
|
46
|
-
|
|
222
|
+
background-color: transparent;
|
|
223
|
+
color: var(--color-fg-muted);
|
|
224
|
+
}
|
|
225
|
+
.btn-ghost:hover {
|
|
226
|
+
background-color: var(--color-bg-muted);
|
|
227
|
+
color: var(--color-fg);
|
|
228
|
+
}
|
|
229
|
+
.btn-ghost[data-pressed='true'] {
|
|
230
|
+
background-color: var(--color-bg-muted);
|
|
231
|
+
color: var(--color-fg);
|
|
47
232
|
}
|
|
48
233
|
|
|
49
234
|
.btn-danger {
|
|
50
|
-
|
|
235
|
+
background-color: var(--color-danger-600);
|
|
236
|
+
color: white;
|
|
237
|
+
}
|
|
238
|
+
.btn-danger:hover { background-color: var(--color-danger-700); }
|
|
239
|
+
.btn-danger:active { background-color: var(--color-danger-800); }
|
|
240
|
+
.btn-danger:focus-visible {
|
|
241
|
+
box-shadow: 0 0 0 2px var(--color-bg), 0 0 0 4px var(--color-danger-500);
|
|
51
242
|
}
|
|
52
243
|
|
|
53
244
|
.btn-link {
|
|
54
|
-
@apply bg-transparent
|
|
245
|
+
@apply bg-transparent underline-offset-4 hover:underline px-0;
|
|
246
|
+
color: var(--color-primary-600);
|
|
55
247
|
height: auto;
|
|
56
248
|
}
|
|
249
|
+
[data-theme='dark'] .btn-link {
|
|
250
|
+
color: var(--color-primary-400);
|
|
251
|
+
}
|
|
57
252
|
|
|
58
|
-
/*
|
|
253
|
+
/* Square icon-button — close buttons, calendar nav, chevron triggers, etc.
|
|
254
|
+
* The selector list extends `.btn-icon` to consumer atoms so they share
|
|
255
|
+
* one source of truth without `@apply`-ing across custom classes. */
|
|
256
|
+
.btn-icon,
|
|
257
|
+
.dialog-close,
|
|
258
|
+
.toast-close,
|
|
259
|
+
.combobox-trigger,
|
|
260
|
+
.calendar-nav,
|
|
261
|
+
.pagination-item {
|
|
262
|
+
@apply inline-flex items-center justify-center;
|
|
263
|
+
width: var(--ui-icon-btn-md);
|
|
264
|
+
height: var(--ui-icon-btn-md);
|
|
265
|
+
padding: 0;
|
|
266
|
+
border-radius: var(--ui-radius-sm);
|
|
267
|
+
color: var(--color-fg-muted);
|
|
268
|
+
background: transparent;
|
|
269
|
+
border: none;
|
|
270
|
+
cursor: pointer;
|
|
271
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
272
|
+
color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
273
|
+
}
|
|
274
|
+
.btn-icon:hover,
|
|
275
|
+
.dialog-close:hover,
|
|
276
|
+
.combobox-trigger:hover,
|
|
277
|
+
.calendar-nav:hover,
|
|
278
|
+
.pagination-item:hover {
|
|
279
|
+
background-color: var(--color-bg-muted);
|
|
280
|
+
color: var(--color-fg);
|
|
281
|
+
}
|
|
282
|
+
.btn-icon:focus-visible,
|
|
283
|
+
.dialog-close:focus-visible,
|
|
284
|
+
.toast-close:focus-visible,
|
|
285
|
+
.combobox-trigger:focus-visible,
|
|
286
|
+
.calendar-nav:focus-visible,
|
|
287
|
+
.pagination-item:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
288
|
+
.btn-icon-sm,
|
|
289
|
+
.dialog-close,
|
|
290
|
+
.toast-close,
|
|
291
|
+
.combobox-trigger,
|
|
292
|
+
.calendar-nav { width: var(--ui-icon-btn-sm); height: var(--ui-icon-btn-sm); }
|
|
293
|
+
.btn-icon-lg { width: var(--ui-icon-btn-lg); height: var(--ui-icon-btn-lg); }
|
|
294
|
+
|
|
295
|
+
/* Spinner used inside Btn loading state */
|
|
59
296
|
.ui-spinner {
|
|
60
297
|
@apply inline-block size-4 animate-spin rounded-full border-2 border-current border-t-transparent;
|
|
61
298
|
}
|
|
62
299
|
|
|
63
|
-
/*
|
|
64
|
-
.
|
|
65
|
-
|
|
66
|
-
@apply placeholder:text-neutral-400;
|
|
67
|
-
@apply transition-[border-color,box-shadow] duration-150 ease-out;
|
|
68
|
-
@apply focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-500/30;
|
|
69
|
-
@apply disabled:cursor-not-allowed disabled:bg-neutral-50 disabled:opacity-70;
|
|
70
|
-
height: var(--ui-h-md);
|
|
71
|
-
padding-inline: 0.75rem;
|
|
72
|
-
}
|
|
73
|
-
|
|
300
|
+
/* ============================================================ */
|
|
301
|
+
/* Form controls — base shared with .control-base above */
|
|
302
|
+
/* ============================================================ */
|
|
74
303
|
.input-sm {
|
|
75
304
|
@apply text-xs;
|
|
76
305
|
height: var(--ui-h-sm);
|
|
77
306
|
padding-inline: 0.625rem;
|
|
78
307
|
}
|
|
79
|
-
|
|
80
308
|
.input-lg {
|
|
81
309
|
@apply text-base;
|
|
82
310
|
height: var(--ui-h-lg);
|
|
83
311
|
padding-inline: 0.875rem;
|
|
84
312
|
}
|
|
85
313
|
|
|
86
|
-
.input-err {
|
|
87
|
-
@apply border-red-500 focus:border-red-500 focus:ring-red-500/30;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/* Textarea overrides .input's height */
|
|
91
314
|
.textarea {
|
|
92
|
-
@apply
|
|
93
|
-
|
|
94
|
-
@apply transition-[border-color,box-shadow] duration-150 ease-out;
|
|
95
|
-
@apply focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-500/30;
|
|
96
|
-
@apply disabled:cursor-not-allowed disabled:bg-neutral-50 disabled:opacity-70;
|
|
315
|
+
@apply leading-snug;
|
|
316
|
+
padding-block: 0.5rem;
|
|
97
317
|
min-height: calc(var(--ui-h-md) * 2);
|
|
318
|
+
height: auto;
|
|
98
319
|
}
|
|
99
320
|
|
|
100
|
-
.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
.select {
|
|
105
|
-
@apply block w-full rounded-md border border-neutral-300 bg-white text-sm text-neutral-900 shadow-sm;
|
|
106
|
-
@apply transition-[border-color,box-shadow] duration-150 ease-out;
|
|
107
|
-
@apply focus:outline-none focus:border-primary-500 focus:ring-2 focus:ring-primary-500/30;
|
|
108
|
-
@apply disabled:cursor-not-allowed disabled:bg-neutral-50 disabled:opacity-70;
|
|
109
|
-
height: var(--ui-h-md);
|
|
110
|
-
padding-inline: 0.75rem;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.select-err {
|
|
114
|
-
@apply border-red-500 focus:border-red-500 focus:ring-red-500/30;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/* --- Checkbox / Radio --- */
|
|
118
|
-
.checkbox {
|
|
119
|
-
@apply size-4 cursor-pointer rounded border-neutral-300 text-primary-600 shadow-sm;
|
|
120
|
-
@apply focus:outline-none focus:ring-2 focus:ring-primary-500/30 focus:ring-offset-1;
|
|
121
|
-
@apply disabled:cursor-not-allowed disabled:opacity-60;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
.checkbox-err {
|
|
125
|
-
@apply border-red-500 focus:ring-red-500/30;
|
|
126
|
-
}
|
|
127
|
-
|
|
321
|
+
/* Checkbox / Radio — small square/round controls. Native `accent-color`
|
|
322
|
+
* does the colored fill once checked. */
|
|
323
|
+
.checkbox,
|
|
128
324
|
.radio {
|
|
129
|
-
@apply size-4 cursor-pointer
|
|
130
|
-
@apply focus:outline-none focus:ring-2 focus:ring-primary-500/30 focus:ring-offset-1;
|
|
325
|
+
@apply size-4 cursor-pointer;
|
|
131
326
|
@apply disabled:cursor-not-allowed disabled:opacity-60;
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
327
|
+
border: 1px solid var(--color-border-strong);
|
|
328
|
+
accent-color: var(--color-primary-600);
|
|
329
|
+
transition: box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
330
|
+
}
|
|
331
|
+
.checkbox { border-radius: var(--ui-radius-sm); }
|
|
332
|
+
.radio { border-radius: var(--ui-radius-full); }
|
|
333
|
+
.checkbox:focus-visible,
|
|
334
|
+
.radio:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
335
|
+
.checkbox-err,
|
|
336
|
+
.radio-err { border-color: var(--color-danger-500); }
|
|
137
337
|
|
|
138
|
-
/*
|
|
139
|
-
* Implemented as a checkbox the user wraps in a label; we provide the
|
|
140
|
-
* pill track via .switch and the moving knob via ::before.
|
|
141
|
-
*/
|
|
338
|
+
/* Switch */
|
|
142
339
|
.switch {
|
|
143
|
-
@apply relative inline-flex h-5 w-9 shrink-0 cursor-pointer appearance-none rounded-full
|
|
144
|
-
@apply transition-colors duration-150 ease-out;
|
|
145
|
-
@apply checked:bg-primary-600;
|
|
146
|
-
@apply focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500/30 focus-visible:ring-offset-1;
|
|
340
|
+
@apply relative inline-flex h-5 w-9 shrink-0 cursor-pointer appearance-none rounded-full;
|
|
147
341
|
@apply disabled:cursor-not-allowed disabled:opacity-60;
|
|
342
|
+
background-color: var(--color-border-strong);
|
|
343
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
344
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
148
345
|
}
|
|
346
|
+
.switch:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
347
|
+
.switch:checked { background-color: var(--color-primary-600); }
|
|
149
348
|
.switch::before {
|
|
150
349
|
content: '';
|
|
151
|
-
@apply absolute left-0.5 top-0.5 size-4 rounded-full
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
.switch:checked::before {
|
|
155
|
-
transform: translateX(1rem);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/* --- Field (label + control + help/error) --- */
|
|
159
|
-
.field {
|
|
160
|
-
@apply flex flex-col;
|
|
350
|
+
@apply absolute left-0.5 top-0.5 size-4 rounded-full;
|
|
351
|
+
background-color: white;
|
|
352
|
+
transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
161
353
|
}
|
|
354
|
+
.switch:checked::before { transform: translateX(1rem); }
|
|
162
355
|
|
|
356
|
+
/* ============================================================ */
|
|
357
|
+
/* Field */
|
|
358
|
+
/* ============================================================ */
|
|
359
|
+
.field { @apply flex flex-col; }
|
|
163
360
|
.field-label {
|
|
164
|
-
@apply mb-1 block text-sm font-medium
|
|
361
|
+
@apply mb-1 block text-sm font-medium;
|
|
362
|
+
color: var(--color-fg);
|
|
165
363
|
}
|
|
166
|
-
|
|
167
364
|
.field-required {
|
|
168
|
-
@apply ml-0.5
|
|
365
|
+
@apply ml-0.5;
|
|
366
|
+
color: var(--color-danger-600);
|
|
169
367
|
}
|
|
170
|
-
|
|
171
368
|
.field-help {
|
|
172
|
-
@apply mt-1 text-xs
|
|
369
|
+
@apply mt-1 text-xs;
|
|
370
|
+
color: var(--color-fg-muted);
|
|
173
371
|
}
|
|
174
|
-
|
|
175
372
|
.field-error {
|
|
176
|
-
@apply mt-1 text-xs
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
.field-row {
|
|
180
|
-
@apply flex items-center gap-2;
|
|
373
|
+
@apply mt-1 text-xs;
|
|
374
|
+
color: var(--color-danger-600);
|
|
181
375
|
}
|
|
376
|
+
.field-row { @apply flex items-center gap-2; }
|
|
182
377
|
|
|
183
|
-
/* Field-group: border-grouped collection of fields */
|
|
184
378
|
.field-group {
|
|
185
|
-
@apply space-y-3
|
|
379
|
+
@apply space-y-3 p-4;
|
|
380
|
+
border: 1px solid var(--color-border);
|
|
381
|
+
border-radius: var(--ui-radius);
|
|
186
382
|
}
|
|
187
|
-
|
|
188
383
|
.field-group-legend {
|
|
189
|
-
@apply -mx-1 -mt-1 px-1 text-sm font-medium
|
|
384
|
+
@apply -mx-1 -mt-1 px-1 text-sm font-medium;
|
|
385
|
+
color: var(--color-fg);
|
|
190
386
|
}
|
|
191
387
|
|
|
192
|
-
|
|
193
|
-
.form {
|
|
194
|
-
@apply space-y-4;
|
|
195
|
-
}
|
|
388
|
+
.form { @apply space-y-4; }
|
|
196
389
|
|
|
197
|
-
/*
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
* dependency, no v4 plugin.
|
|
201
|
-
*/
|
|
390
|
+
/* ============================================================ */
|
|
391
|
+
/* Dialog */
|
|
392
|
+
/* ============================================================ */
|
|
202
393
|
.dialog-overlay {
|
|
203
|
-
@apply fixed inset-0 z-50
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
394
|
+
@apply fixed inset-0 z-50 backdrop-blur-sm;
|
|
395
|
+
background-color: oklch(0% 0 0 / 0.5);
|
|
396
|
+
opacity: 0;
|
|
397
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease);
|
|
207
398
|
}
|
|
399
|
+
.dialog-overlay[data-state='open'] { opacity: 1; }
|
|
208
400
|
|
|
209
401
|
.dialog-content {
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
402
|
+
/* Centered via translate longhand so it doesn't compose with the
|
|
403
|
+
* scale animation below. Tailwind v4 emits `translate:` for its
|
|
404
|
+
* `-translate-x-*` utilities; mixing them with `transform:` here
|
|
405
|
+
* would double the offset. */
|
|
406
|
+
@apply fixed left-1/2 top-1/2 z-50 w-full max-w-lg p-6;
|
|
407
|
+
translate: -50% -50%;
|
|
408
|
+
/* base surface comes from `.surface-elevated` selector list */
|
|
409
|
+
border-radius: var(--ui-radius-lg);
|
|
410
|
+
box-shadow: var(--ui-elev-3);
|
|
411
|
+
opacity: 0;
|
|
412
|
+
scale: 0.96;
|
|
413
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease),
|
|
414
|
+
scale var(--ui-motion-fast) var(--ui-motion-ease);
|
|
213
415
|
}
|
|
214
416
|
.dialog-content[data-state='open'] {
|
|
215
|
-
|
|
417
|
+
opacity: 1;
|
|
418
|
+
scale: 1;
|
|
216
419
|
}
|
|
217
|
-
|
|
218
420
|
.dialog-title {
|
|
219
|
-
@apply text-lg font-semibold leading-tight tracking-tight
|
|
421
|
+
@apply text-lg font-semibold leading-tight tracking-tight;
|
|
422
|
+
color: var(--color-fg);
|
|
220
423
|
}
|
|
221
|
-
|
|
222
424
|
.dialog-description {
|
|
223
|
-
@apply mt-1 text-sm
|
|
425
|
+
@apply mt-1 text-sm;
|
|
426
|
+
color: var(--color-fg-muted);
|
|
427
|
+
}
|
|
428
|
+
.dialog-body { @apply mt-4; }
|
|
429
|
+
.dialog-actions { @apply mt-6 flex items-center justify-end gap-2; }
|
|
430
|
+
.dialog-close { @apply absolute right-3 top-3; }
|
|
431
|
+
|
|
432
|
+
/* ============================================================ */
|
|
433
|
+
/* Sheet (and Drawer, which is just Sheet with side="left") */
|
|
434
|
+
/* ============================================================ */
|
|
435
|
+
.sheet-content {
|
|
436
|
+
@apply fixed z-50 p-6;
|
|
437
|
+
background-color: var(--color-bg-elevated);
|
|
438
|
+
color: var(--color-fg);
|
|
439
|
+
border: 1px solid var(--color-border);
|
|
440
|
+
box-shadow: var(--ui-elev-3);
|
|
441
|
+
/* Same precaution as `.dialog-content`: drive the slide via the
|
|
442
|
+
* `translate:` longhand and avoid mixing with `transform:` so they
|
|
443
|
+
* don't compose. */
|
|
444
|
+
transition: translate var(--ui-motion-med) var(--ui-motion-ease);
|
|
445
|
+
}
|
|
446
|
+
.sheet-right { @apply right-0 top-0 h-full w-full max-w-md; translate: 100% 0; }
|
|
447
|
+
.sheet-left { @apply left-0 top-0 h-full w-full max-w-md; translate: -100% 0; }
|
|
448
|
+
.sheet-top { @apply left-0 top-0 w-full; translate: 0 -100%; }
|
|
449
|
+
.sheet-bottom { @apply bottom-0 left-0 w-full; translate: 0 100%; }
|
|
450
|
+
.sheet-right[data-state='open'],
|
|
451
|
+
.sheet-left[data-state='open'],
|
|
452
|
+
.sheet-top[data-state='open'],
|
|
453
|
+
.sheet-bottom[data-state='open'] { translate: 0 0; }
|
|
454
|
+
.sheet-body { @apply mt-4; }
|
|
455
|
+
|
|
456
|
+
/* ============================================================ */
|
|
457
|
+
/* Popover / Dropdown / Tooltip — all surface-elevated */
|
|
458
|
+
/* ============================================================ */
|
|
459
|
+
.popover-content {
|
|
460
|
+
@apply z-50 p-3 text-sm;
|
|
461
|
+
/* base surface comes from `.surface-elevated` selector list */
|
|
462
|
+
opacity: 0;
|
|
463
|
+
transform: scale(0.96);
|
|
464
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease),
|
|
465
|
+
transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
466
|
+
}
|
|
467
|
+
.popover-content[data-state='open'] {
|
|
468
|
+
opacity: 1;
|
|
469
|
+
transform: scale(1);
|
|
224
470
|
}
|
|
225
471
|
|
|
226
|
-
.
|
|
227
|
-
@apply
|
|
472
|
+
.dropdown-content {
|
|
473
|
+
@apply z-50 text-sm;
|
|
474
|
+
/* base surface comes from `.surface-elevated` selector list */
|
|
475
|
+
min-width: 8rem;
|
|
476
|
+
padding: 0.25rem;
|
|
477
|
+
opacity: 0;
|
|
478
|
+
transform: scale(0.96);
|
|
479
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease),
|
|
480
|
+
transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
481
|
+
}
|
|
482
|
+
.dropdown-content[data-state='open'] {
|
|
483
|
+
opacity: 1;
|
|
484
|
+
transform: scale(1);
|
|
485
|
+
}
|
|
486
|
+
.dropdown-item {
|
|
487
|
+
@apply flex cursor-pointer select-none items-center gap-2 px-2 py-1.5 text-sm outline-none;
|
|
488
|
+
color: var(--color-fg);
|
|
489
|
+
border-radius: var(--ui-radius-sm);
|
|
490
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
491
|
+
}
|
|
492
|
+
.dropdown-item:hover:not([data-disabled]),
|
|
493
|
+
.dropdown-item:focus-visible,
|
|
494
|
+
.dropdown-item[data-active='true'] {
|
|
495
|
+
background-color: var(--color-bg-muted);
|
|
496
|
+
outline: none;
|
|
497
|
+
}
|
|
498
|
+
.dropdown-item[data-disabled] {
|
|
499
|
+
@apply cursor-not-allowed opacity-50;
|
|
500
|
+
}
|
|
501
|
+
.dropdown-separator {
|
|
502
|
+
@apply -mx-1 my-1 h-px;
|
|
503
|
+
background-color: var(--color-border);
|
|
228
504
|
}
|
|
229
505
|
|
|
230
|
-
.
|
|
231
|
-
@apply
|
|
506
|
+
.tooltip-content {
|
|
507
|
+
@apply z-50 px-2 py-1 text-xs;
|
|
508
|
+
background-color: var(--color-bg-inverse);
|
|
509
|
+
color: var(--color-bg);
|
|
510
|
+
border-radius: var(--ui-radius-sm);
|
|
511
|
+
box-shadow: var(--ui-elev-2);
|
|
512
|
+
opacity: 0;
|
|
513
|
+
transform: scale(0.96);
|
|
514
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease),
|
|
515
|
+
transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
516
|
+
}
|
|
517
|
+
.tooltip-content[data-state='open'] {
|
|
518
|
+
opacity: 1;
|
|
519
|
+
transform: scale(1);
|
|
520
|
+
}
|
|
521
|
+
/* `.tooltip-rich` is in the `.surface-elevated` selector list above. */
|
|
522
|
+
.tooltip-rich {
|
|
523
|
+
@apply p-3 text-sm max-w-xs;
|
|
232
524
|
}
|
|
233
525
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
526
|
+
/* ============================================================ */
|
|
527
|
+
/* Tabs */
|
|
528
|
+
/* ============================================================ */
|
|
529
|
+
.tabs-root { @apply space-y-3; }
|
|
530
|
+
.tabs-list {
|
|
531
|
+
@apply inline-flex h-9 items-center justify-center p-1;
|
|
532
|
+
background-color: var(--color-bg-muted);
|
|
533
|
+
color: var(--color-fg-muted);
|
|
534
|
+
border-radius: var(--ui-radius);
|
|
238
535
|
}
|
|
536
|
+
.tabs-trigger {
|
|
537
|
+
@apply inline-flex items-center justify-center whitespace-nowrap px-3 py-1 text-sm font-medium;
|
|
538
|
+
@apply disabled:cursor-not-allowed disabled:opacity-50;
|
|
539
|
+
color: var(--color-fg-muted);
|
|
540
|
+
background: transparent;
|
|
541
|
+
border: none;
|
|
542
|
+
cursor: pointer;
|
|
543
|
+
border-radius: var(--ui-radius-sm);
|
|
544
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
545
|
+
color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
546
|
+
}
|
|
547
|
+
.tabs-trigger:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
548
|
+
.tabs-trigger[aria-selected='true'],
|
|
549
|
+
.tabs-trigger[data-state='active'] {
|
|
550
|
+
background-color: var(--color-bg-elevated);
|
|
551
|
+
color: var(--color-fg);
|
|
552
|
+
}
|
|
553
|
+
.tabs-content:focus-visible { outline: none; }
|
|
239
554
|
|
|
240
|
-
/*
|
|
241
|
-
|
|
242
|
-
|
|
555
|
+
/* ============================================================ */
|
|
556
|
+
/* Toast */
|
|
557
|
+
/* ============================================================ */
|
|
558
|
+
.toast-region {
|
|
559
|
+
@apply pointer-events-none fixed bottom-4 right-4 z-[100] flex w-full max-w-sm flex-col gap-2;
|
|
243
560
|
}
|
|
244
|
-
.
|
|
245
|
-
@apply
|
|
561
|
+
.toast {
|
|
562
|
+
@apply pointer-events-auto flex items-start gap-3 p-3;
|
|
563
|
+
/* base surface comes from `.surface-elevated` selector list */
|
|
564
|
+
animation: norns-toast-in var(--ui-motion-med) var(--ui-motion-ease);
|
|
246
565
|
}
|
|
247
|
-
|
|
248
|
-
|
|
566
|
+
@keyframes norns-toast-in {
|
|
567
|
+
from { opacity: 0; transform: translateX(1rem); }
|
|
568
|
+
to { opacity: 1; transform: translateX(0); }
|
|
249
569
|
}
|
|
250
|
-
.
|
|
251
|
-
|
|
570
|
+
.toast-info {
|
|
571
|
+
background-color: var(--color-info-bg);
|
|
572
|
+
color: var(--color-info-fg);
|
|
573
|
+
border-color: var(--color-info-border);
|
|
252
574
|
}
|
|
253
|
-
.
|
|
254
|
-
|
|
575
|
+
.toast-success {
|
|
576
|
+
background-color: var(--color-success-bg);
|
|
577
|
+
color: var(--color-success-fg);
|
|
578
|
+
border-color: var(--color-success-border);
|
|
255
579
|
}
|
|
256
|
-
.
|
|
257
|
-
|
|
580
|
+
.toast-warning {
|
|
581
|
+
background-color: var(--color-warning-bg);
|
|
582
|
+
color: var(--color-warning-fg);
|
|
583
|
+
border-color: var(--color-warning-border);
|
|
258
584
|
}
|
|
259
|
-
.
|
|
260
|
-
|
|
585
|
+
.toast-error {
|
|
586
|
+
background-color: var(--color-danger-bg);
|
|
587
|
+
color: var(--color-danger-fg);
|
|
588
|
+
border-color: var(--color-danger-border);
|
|
261
589
|
}
|
|
262
|
-
.
|
|
263
|
-
|
|
590
|
+
.toast-message { @apply flex-1 text-sm leading-snug; }
|
|
591
|
+
.toast-close {
|
|
592
|
+
@apply -mr-1 -mt-0.5;
|
|
593
|
+
color: currentColor;
|
|
594
|
+
opacity: 0.6;
|
|
264
595
|
}
|
|
265
|
-
.
|
|
266
|
-
|
|
596
|
+
.toast-close:hover { opacity: 1; background-color: transparent; color: currentColor; }
|
|
597
|
+
|
|
598
|
+
/* ============================================================ */
|
|
599
|
+
/* Surface / Card */
|
|
600
|
+
/* ============================================================ */
|
|
601
|
+
.surface {
|
|
602
|
+
background-color: var(--color-bg-elevated);
|
|
603
|
+
color: var(--color-fg);
|
|
604
|
+
border: 1px solid var(--color-border);
|
|
605
|
+
border-radius: var(--ui-radius);
|
|
606
|
+
}
|
|
607
|
+
.surface-glass {
|
|
608
|
+
background-color: color-mix(in oklab, var(--color-bg-elevated) 65%, transparent);
|
|
609
|
+
backdrop-filter: blur(12px);
|
|
610
|
+
-webkit-backdrop-filter: blur(12px);
|
|
611
|
+
}
|
|
612
|
+
.card {
|
|
613
|
+
background-color: var(--color-bg-elevated);
|
|
614
|
+
color: var(--color-fg);
|
|
615
|
+
border: 1px solid var(--color-border);
|
|
616
|
+
border-radius: var(--ui-radius-lg);
|
|
617
|
+
}
|
|
618
|
+
.card-padded { @apply p-5; }
|
|
619
|
+
.card-header {
|
|
620
|
+
@apply px-5 pt-5 pb-3;
|
|
621
|
+
border-bottom: 1px solid var(--color-border);
|
|
622
|
+
border-top-left-radius: var(--ui-radius-lg);
|
|
623
|
+
border-top-right-radius: var(--ui-radius-lg);
|
|
624
|
+
}
|
|
625
|
+
.card-body { @apply p-5; }
|
|
626
|
+
.card-footer {
|
|
627
|
+
@apply px-5 py-3;
|
|
628
|
+
border-top: 1px solid var(--color-border);
|
|
629
|
+
background-color: var(--color-bg-subtle);
|
|
630
|
+
border-bottom-left-radius: var(--ui-radius-lg);
|
|
631
|
+
border-bottom-right-radius: var(--ui-radius-lg);
|
|
632
|
+
}
|
|
633
|
+
.card-interactive {
|
|
634
|
+
@apply cursor-pointer no-underline;
|
|
635
|
+
color: inherit;
|
|
636
|
+
transition: border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
637
|
+
transform var(--ui-motion-fast) var(--ui-motion-ease),
|
|
638
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
639
|
+
}
|
|
640
|
+
.card-interactive:hover {
|
|
641
|
+
border-color: var(--color-border-strong);
|
|
642
|
+
transform: translateY(-2px);
|
|
643
|
+
box-shadow: var(--ui-elev-2);
|
|
644
|
+
}
|
|
645
|
+
.card-interactive:focus-visible {
|
|
646
|
+
outline: none;
|
|
647
|
+
box-shadow: var(--ui-focus-ring);
|
|
267
648
|
}
|
|
268
649
|
|
|
269
|
-
|
|
270
|
-
|
|
650
|
+
/* ============================================================ */
|
|
651
|
+
/* Banner */
|
|
652
|
+
/* ============================================================ */
|
|
653
|
+
.banner {
|
|
654
|
+
@apply flex items-start gap-3 p-3 text-sm;
|
|
655
|
+
border: 1px solid;
|
|
656
|
+
border-radius: var(--ui-radius);
|
|
657
|
+
animation: norns-banner-in var(--ui-motion-med) var(--ui-motion-ease) both;
|
|
658
|
+
}
|
|
659
|
+
@keyframes norns-banner-in {
|
|
660
|
+
from { opacity: 0; transform: translateY(-4px); }
|
|
661
|
+
to { opacity: 1; transform: translateY(0); }
|
|
662
|
+
}
|
|
663
|
+
.banner-info {
|
|
664
|
+
background-color: var(--color-info-bg);
|
|
665
|
+
color: var(--color-info-fg);
|
|
666
|
+
border-color: var(--color-info-border);
|
|
667
|
+
}
|
|
668
|
+
.banner-success {
|
|
669
|
+
background-color: var(--color-success-bg);
|
|
670
|
+
color: var(--color-success-fg);
|
|
671
|
+
border-color: var(--color-success-border);
|
|
672
|
+
}
|
|
673
|
+
.banner-warning {
|
|
674
|
+
background-color: var(--color-warning-bg);
|
|
675
|
+
color: var(--color-warning-fg);
|
|
676
|
+
border-color: var(--color-warning-border);
|
|
677
|
+
}
|
|
678
|
+
.banner-danger {
|
|
679
|
+
background-color: var(--color-danger-bg);
|
|
680
|
+
color: var(--color-danger-fg);
|
|
681
|
+
border-color: var(--color-danger-border);
|
|
682
|
+
}
|
|
683
|
+
.banner-icon { @apply shrink-0 mt-0.5; }
|
|
684
|
+
.banner-body { @apply flex-1; }
|
|
685
|
+
.banner-actions { @apply shrink-0 flex gap-2 ml-auto; }
|
|
686
|
+
|
|
687
|
+
/* ============================================================ */
|
|
688
|
+
/* Badge / Chip */
|
|
689
|
+
/* ============================================================ */
|
|
690
|
+
.badge {
|
|
691
|
+
@apply inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium leading-none;
|
|
692
|
+
border-radius: var(--ui-radius-full);
|
|
693
|
+
background-color: var(--color-bg-muted);
|
|
694
|
+
color: var(--color-fg);
|
|
695
|
+
}
|
|
696
|
+
.badge-primary {
|
|
697
|
+
background-color: var(--color-primary-100);
|
|
698
|
+
color: var(--color-primary-900);
|
|
699
|
+
}
|
|
700
|
+
[data-theme='dark'] .badge-primary {
|
|
701
|
+
background-color: var(--color-primary-950);
|
|
702
|
+
color: var(--color-primary-200);
|
|
703
|
+
}
|
|
704
|
+
.badge-success { background-color: var(--color-success-bg); color: var(--color-success-fg); }
|
|
705
|
+
.badge-warning { background-color: var(--color-warning-bg); color: var(--color-warning-fg); }
|
|
706
|
+
.badge-danger { background-color: var(--color-danger-bg); color: var(--color-danger-fg); }
|
|
707
|
+
.badge-info { background-color: var(--color-info-bg); color: var(--color-info-fg); }
|
|
708
|
+
.badge-sm { @apply text-[10px] px-1.5; }
|
|
709
|
+
|
|
710
|
+
.chip {
|
|
711
|
+
@apply inline-flex items-center gap-1.5 px-2.5 py-1 text-xs font-medium;
|
|
712
|
+
background-color: var(--color-bg-muted);
|
|
713
|
+
color: var(--color-fg);
|
|
714
|
+
border: 1px solid var(--color-border);
|
|
715
|
+
border-radius: var(--ui-radius-full);
|
|
716
|
+
}
|
|
717
|
+
.chip-remove {
|
|
718
|
+
@apply -mr-1 inline-flex size-4 items-center justify-center rounded-full;
|
|
719
|
+
opacity: 0.6;
|
|
720
|
+
transition: opacity var(--ui-motion-fast) var(--ui-motion-ease),
|
|
721
|
+
background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
722
|
+
}
|
|
723
|
+
.chip-remove:hover {
|
|
724
|
+
opacity: 1;
|
|
725
|
+
background-color: var(--color-bg-muted);
|
|
271
726
|
}
|
|
272
727
|
|
|
273
|
-
/*
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
728
|
+
/* ============================================================ */
|
|
729
|
+
/* Avatar */
|
|
730
|
+
/* ============================================================ */
|
|
731
|
+
.avatar {
|
|
732
|
+
@apply relative inline-flex shrink-0 items-center justify-center overflow-hidden font-medium;
|
|
733
|
+
background-color: var(--color-bg-muted);
|
|
734
|
+
color: var(--color-fg);
|
|
735
|
+
border-radius: var(--ui-radius-full);
|
|
736
|
+
}
|
|
737
|
+
.avatar-sm { @apply size-6 text-xs; }
|
|
738
|
+
.avatar-md { @apply size-8 text-sm; }
|
|
739
|
+
.avatar-lg { @apply size-12 text-base; }
|
|
740
|
+
.avatar-xl { @apply size-16 text-lg; }
|
|
741
|
+
.avatar img { @apply h-full w-full object-cover; }
|
|
742
|
+
|
|
743
|
+
.avatar-group { @apply inline-flex items-center; }
|
|
744
|
+
.avatar-group-item,
|
|
745
|
+
.avatar-group-overflow {
|
|
746
|
+
@apply relative inline-flex;
|
|
747
|
+
margin-left: -0.5rem;
|
|
748
|
+
box-shadow: 0 0 0 2px var(--color-bg);
|
|
749
|
+
border-radius: var(--ui-radius-full);
|
|
750
|
+
transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
751
|
+
}
|
|
752
|
+
.avatar-group-item:first-child,
|
|
753
|
+
.avatar-group:has(.avatar-group-item:first-child) > .avatar-group-item:first-child {
|
|
754
|
+
margin-left: 0;
|
|
755
|
+
}
|
|
756
|
+
.avatar-group-item:hover { transform: translateY(-2px); z-index: 1; }
|
|
757
|
+
.avatar-group-overflow {
|
|
758
|
+
@apply text-xs font-medium;
|
|
759
|
+
background-color: var(--color-bg-muted);
|
|
760
|
+
color: var(--color-fg-muted);
|
|
277
761
|
}
|
|
278
|
-
|
|
279
|
-
|
|
762
|
+
|
|
763
|
+
/* ============================================================ */
|
|
764
|
+
/* Decorative buttons (CSS-only motion) */
|
|
765
|
+
/* ============================================================ */
|
|
766
|
+
.gradient-text {
|
|
767
|
+
background-clip: text;
|
|
768
|
+
-webkit-background-clip: text;
|
|
769
|
+
color: transparent;
|
|
770
|
+
background-size: 200% 200%;
|
|
771
|
+
background-position: 0% 50%;
|
|
772
|
+
}
|
|
773
|
+
.gradient-text-anim { animation: norns-gradient-shift 6s ease-in-out infinite; }
|
|
774
|
+
@keyframes norns-gradient-shift {
|
|
775
|
+
0%, 100% { background-position: 0% 50%; }
|
|
776
|
+
50% { background-position: 100% 50%; }
|
|
280
777
|
}
|
|
281
778
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
779
|
+
.copy-btn-check { animation: norns-copy-pop 250ms ease-out; }
|
|
780
|
+
@keyframes norns-copy-pop {
|
|
781
|
+
0% { transform: scale(0.5); opacity: 0; }
|
|
782
|
+
70% { transform: scale(1.15); }
|
|
783
|
+
100% { transform: scale(1); opacity: 1; }
|
|
286
784
|
}
|
|
287
|
-
|
|
288
|
-
|
|
785
|
+
|
|
786
|
+
.shiny-btn { position: relative; isolation: isolate; }
|
|
787
|
+
.shiny-btn-shine {
|
|
788
|
+
position: absolute;
|
|
789
|
+
inset: 0;
|
|
790
|
+
pointer-events: none;
|
|
791
|
+
background: linear-gradient(
|
|
792
|
+
110deg,
|
|
793
|
+
transparent 30%,
|
|
794
|
+
color-mix(in oklab, white 35%, transparent) 50%,
|
|
795
|
+
transparent 70%
|
|
796
|
+
);
|
|
797
|
+
background-size: 250% 100%;
|
|
798
|
+
background-position: 200% 0;
|
|
799
|
+
animation: norns-shiny 2.6s ease-in-out infinite;
|
|
800
|
+
mix-blend-mode: overlay;
|
|
801
|
+
border-radius: inherit;
|
|
802
|
+
}
|
|
803
|
+
@keyframes norns-shiny {
|
|
804
|
+
0% { background-position: 200% 0; }
|
|
805
|
+
100% { background-position: -150% 0; }
|
|
289
806
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
807
|
+
|
|
808
|
+
.ripple-btn { position: relative; overflow: hidden; }
|
|
809
|
+
.ripple-btn-ripple {
|
|
810
|
+
position: absolute;
|
|
811
|
+
pointer-events: none;
|
|
812
|
+
border-radius: var(--ui-radius-full);
|
|
813
|
+
background-color: color-mix(in oklab, currentColor 35%, transparent);
|
|
814
|
+
transform: scale(0);
|
|
815
|
+
opacity: 0.6;
|
|
816
|
+
animation: norns-ripple 600ms ease-out forwards;
|
|
817
|
+
}
|
|
818
|
+
@keyframes norns-ripple {
|
|
819
|
+
to { transform: scale(1); opacity: 0; }
|
|
294
820
|
}
|
|
295
|
-
|
|
296
|
-
|
|
821
|
+
|
|
822
|
+
.liquid-btn { position: relative; isolation: isolate; overflow: hidden; }
|
|
823
|
+
.liquid-btn-blob {
|
|
824
|
+
position: absolute;
|
|
825
|
+
inset: -25%;
|
|
826
|
+
background: radial-gradient(
|
|
827
|
+
circle,
|
|
828
|
+
color-mix(in oklab, white 40%, transparent),
|
|
829
|
+
transparent 60%
|
|
830
|
+
);
|
|
831
|
+
transform: scale(0.6);
|
|
832
|
+
mix-blend-mode: overlay;
|
|
833
|
+
pointer-events: none;
|
|
834
|
+
filter: blur(12px);
|
|
835
|
+
z-index: 0;
|
|
836
|
+
}
|
|
837
|
+
.liquid-btn-content {
|
|
838
|
+
@apply inline-flex items-center gap-2 relative;
|
|
839
|
+
z-index: 1;
|
|
297
840
|
}
|
|
298
841
|
|
|
299
|
-
|
|
300
|
-
.
|
|
301
|
-
|
|
302
|
-
|
|
842
|
+
.sparkles-wrap { @apply relative inline-block; }
|
|
843
|
+
.sparkles-overlay { @apply pointer-events-none absolute inset-0 overflow-hidden; }
|
|
844
|
+
.sparkle {
|
|
845
|
+
position: absolute;
|
|
846
|
+
display: block;
|
|
847
|
+
border-radius: var(--ui-radius-full);
|
|
848
|
+
background: var(--sparkle-color, var(--color-primary-400));
|
|
849
|
+
opacity: 0;
|
|
850
|
+
transform: scale(0);
|
|
851
|
+
animation: norns-sparkle 2.4s ease-in-out infinite;
|
|
852
|
+
animation-fill-mode: forwards;
|
|
853
|
+
filter: drop-shadow(0 0 4px var(--sparkle-color, var(--color-primary-400)));
|
|
854
|
+
}
|
|
855
|
+
.sparkles-paused .sparkle { animation-play-state: paused; }
|
|
856
|
+
@keyframes norns-sparkle {
|
|
857
|
+
0%, 100% { opacity: 0; transform: scale(0) rotate(0deg); }
|
|
858
|
+
20%, 80% { opacity: 1; }
|
|
859
|
+
50% { transform: scale(1) rotate(180deg); }
|
|
303
860
|
}
|
|
304
|
-
|
|
305
|
-
.
|
|
306
|
-
@apply
|
|
861
|
+
|
|
862
|
+
.gradient-bg {
|
|
863
|
+
@apply relative overflow-hidden;
|
|
864
|
+
background-image: linear-gradient(
|
|
865
|
+
var(--gradient-bg-angle, 130deg),
|
|
866
|
+
var(--gradient-bg-stops, var(--color-primary-500), var(--color-info-500))
|
|
867
|
+
);
|
|
868
|
+
background-size: 300% 300%;
|
|
869
|
+
animation: norns-gradient-loop var(--gradient-bg-duration, 18s) ease-in-out infinite;
|
|
870
|
+
}
|
|
871
|
+
@keyframes norns-gradient-loop {
|
|
872
|
+
0%, 100% { background-position: 0% 50%; }
|
|
873
|
+
25% { background-position: 100% 50%; }
|
|
874
|
+
50% { background-position: 100% 100%; }
|
|
875
|
+
75% { background-position: 0% 100%; }
|
|
307
876
|
}
|
|
308
877
|
|
|
309
|
-
/*
|
|
310
|
-
|
|
311
|
-
|
|
878
|
+
/* ============================================================ */
|
|
879
|
+
/* Skeleton / Progress */
|
|
880
|
+
/* ============================================================ */
|
|
881
|
+
.skeleton {
|
|
882
|
+
@apply block;
|
|
883
|
+
background-color: var(--color-bg-muted);
|
|
884
|
+
border-radius: var(--ui-radius-sm);
|
|
885
|
+
animation: norns-skeleton-pulse 1.6s ease-in-out infinite;
|
|
886
|
+
}
|
|
887
|
+
.skeleton-circle { border-radius: var(--ui-radius-full); }
|
|
888
|
+
@keyframes norns-skeleton-pulse {
|
|
889
|
+
0%, 100% { opacity: 1; }
|
|
890
|
+
50% { opacity: 0.5; }
|
|
312
891
|
}
|
|
313
|
-
|
|
314
|
-
|
|
892
|
+
|
|
893
|
+
.progress {
|
|
894
|
+
@apply relative h-2 w-full overflow-hidden;
|
|
895
|
+
background-color: var(--color-bg-muted);
|
|
896
|
+
border-radius: var(--ui-radius-full);
|
|
897
|
+
}
|
|
898
|
+
.progress-bar {
|
|
899
|
+
@apply h-full;
|
|
900
|
+
background-color: var(--color-primary-600);
|
|
901
|
+
border-radius: var(--ui-radius-full);
|
|
902
|
+
transition: width var(--ui-motion-slow) var(--ui-motion-ease);
|
|
903
|
+
}
|
|
904
|
+
.progress-bar-success { background-color: var(--color-success-600); }
|
|
905
|
+
.progress-bar-warning { background-color: var(--color-warning-600); }
|
|
906
|
+
.progress-bar-danger { background-color: var(--color-danger-600); }
|
|
907
|
+
.progress-indeterminate .progress-bar {
|
|
908
|
+
width: 35%;
|
|
909
|
+
animation: norns-progress-indeterminate 1.4s ease-in-out infinite;
|
|
910
|
+
}
|
|
911
|
+
@keyframes norns-progress-indeterminate {
|
|
912
|
+
0% { transform: translateX(-100%); }
|
|
913
|
+
100% { transform: translateX(385%); }
|
|
315
914
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
915
|
+
|
|
916
|
+
/* ============================================================ */
|
|
917
|
+
/* Header / Hero / Stepper / Breadcrumbs / Pagination */
|
|
918
|
+
/* ============================================================ */
|
|
919
|
+
.norns-header {
|
|
920
|
+
@apply flex items-center justify-between gap-4 px-6 py-3;
|
|
921
|
+
background-color: var(--color-bg);
|
|
922
|
+
border-bottom: 1px solid var(--color-border);
|
|
923
|
+
}
|
|
924
|
+
.norns-header-sticky {
|
|
925
|
+
@apply sticky top-0 z-30;
|
|
926
|
+
background-color: color-mix(in oklab, var(--color-bg) 85%, transparent);
|
|
927
|
+
backdrop-filter: blur(8px);
|
|
928
|
+
}
|
|
929
|
+
.norns-header-brand {
|
|
930
|
+
@apply flex items-center gap-2 font-semibold;
|
|
931
|
+
color: var(--color-fg);
|
|
932
|
+
}
|
|
933
|
+
.norns-header-nav { @apply flex items-center gap-1; }
|
|
934
|
+
.norns-header-actions { @apply flex items-center gap-2; }
|
|
935
|
+
|
|
936
|
+
.hero {
|
|
937
|
+
@apply relative overflow-hidden p-8 md:p-12;
|
|
938
|
+
background-color: var(--color-bg-elevated);
|
|
939
|
+
border: 1px solid var(--color-border);
|
|
940
|
+
border-radius: var(--ui-radius-lg);
|
|
941
|
+
}
|
|
942
|
+
.hero-center { @apply text-center; }
|
|
943
|
+
.hero-title {
|
|
944
|
+
@apply text-3xl font-bold tracking-tight md:text-4xl;
|
|
945
|
+
color: var(--color-fg);
|
|
946
|
+
}
|
|
947
|
+
.hero-description {
|
|
948
|
+
@apply mt-3 text-base md:text-lg max-w-prose;
|
|
949
|
+
color: var(--color-fg-muted);
|
|
950
|
+
}
|
|
951
|
+
.hero-center .hero-description { @apply mx-auto; }
|
|
952
|
+
.hero-actions { @apply mt-6 flex flex-wrap items-center gap-3; }
|
|
953
|
+
.hero-center .hero-actions { @apply justify-center; }
|
|
954
|
+
.hero-image {
|
|
955
|
+
@apply pointer-events-none absolute inset-y-0 right-0 w-1/2 object-cover opacity-20;
|
|
321
956
|
}
|
|
322
|
-
|
|
323
|
-
|
|
957
|
+
|
|
958
|
+
.stepper { @apply flex items-center gap-3; }
|
|
959
|
+
.stepper-vertical { @apply flex-col items-stretch; }
|
|
960
|
+
.stepper-step {
|
|
961
|
+
@apply flex items-center gap-2 text-sm;
|
|
962
|
+
color: var(--color-fg-muted);
|
|
963
|
+
}
|
|
964
|
+
.stepper-step-current { color: var(--color-fg); font-weight: 600; }
|
|
965
|
+
.stepper-step-complete { color: var(--color-fg); }
|
|
966
|
+
.stepper-marker {
|
|
967
|
+
@apply inline-flex shrink-0 items-center justify-center text-xs font-semibold;
|
|
968
|
+
width: var(--ui-icon-btn-md);
|
|
969
|
+
height: var(--ui-icon-btn-md);
|
|
970
|
+
border-radius: var(--ui-radius-full);
|
|
971
|
+
background-color: var(--color-bg-muted);
|
|
972
|
+
color: var(--color-fg-muted);
|
|
973
|
+
border: 1px solid var(--color-border);
|
|
974
|
+
}
|
|
975
|
+
.stepper-step-current .stepper-marker {
|
|
976
|
+
background-color: var(--color-primary-600);
|
|
977
|
+
color: white;
|
|
978
|
+
border-color: var(--color-primary-600);
|
|
979
|
+
}
|
|
980
|
+
.stepper-step-complete .stepper-marker {
|
|
981
|
+
background-color: var(--color-success-600);
|
|
982
|
+
color: white;
|
|
983
|
+
border-color: var(--color-success-600);
|
|
984
|
+
}
|
|
985
|
+
.stepper-divider { @apply h-px flex-1; background-color: var(--color-border); }
|
|
986
|
+
.stepper-vertical .stepper-divider { @apply h-6 w-px ml-3; }
|
|
987
|
+
|
|
988
|
+
.breadcrumbs {
|
|
989
|
+
@apply flex items-center gap-1 text-sm;
|
|
990
|
+
color: var(--color-fg-muted);
|
|
991
|
+
}
|
|
992
|
+
.breadcrumb-item { @apply inline-flex items-center gap-1; }
|
|
993
|
+
.breadcrumb-link { color: var(--color-fg-muted); }
|
|
994
|
+
.breadcrumb-link:hover { color: var(--color-fg); }
|
|
995
|
+
.breadcrumb-current { color: var(--color-fg); font-weight: 500; }
|
|
996
|
+
.breadcrumb-separator {
|
|
997
|
+
@apply mx-1 select-none;
|
|
998
|
+
color: var(--color-fg-subtle);
|
|
324
999
|
}
|
|
325
1000
|
|
|
326
|
-
|
|
327
|
-
.
|
|
328
|
-
|
|
1001
|
+
.pagination { @apply inline-flex items-center gap-1; }
|
|
1002
|
+
.pagination-item {
|
|
1003
|
+
/* base + hover come from `.btn-icon` selector list above. The pagination
|
|
1004
|
+
* variant is full-md icon-button size (8x8 in original), so override
|
|
1005
|
+
* the small default. */
|
|
1006
|
+
width: var(--ui-icon-btn-md);
|
|
1007
|
+
height: var(--ui-icon-btn-md);
|
|
1008
|
+
}
|
|
1009
|
+
.pagination-item-active,
|
|
1010
|
+
.pagination-item-active:hover {
|
|
1011
|
+
background-color: var(--color-primary-600);
|
|
1012
|
+
color: white;
|
|
1013
|
+
}
|
|
1014
|
+
.pagination-item:disabled {
|
|
1015
|
+
@apply cursor-not-allowed opacity-40;
|
|
1016
|
+
}
|
|
1017
|
+
.pagination-ellipsis {
|
|
1018
|
+
@apply inline-flex items-center justify-center text-sm select-none;
|
|
1019
|
+
width: var(--ui-icon-btn-md);
|
|
1020
|
+
height: var(--ui-icon-btn-md);
|
|
1021
|
+
color: var(--color-fg-subtle);
|
|
329
1022
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
1023
|
+
|
|
1024
|
+
/* ============================================================ */
|
|
1025
|
+
/* Accordion / Collapsible — both built on <details> */
|
|
1026
|
+
/* ============================================================ */
|
|
1027
|
+
.accordion {
|
|
1028
|
+
border: 1px solid var(--color-border);
|
|
1029
|
+
border-radius: var(--ui-radius);
|
|
1030
|
+
}
|
|
1031
|
+
.accordion-item { border-bottom: 1px solid var(--color-border); }
|
|
1032
|
+
.accordion-item:last-child { border-bottom: none; }
|
|
1033
|
+
.accordion-trigger {
|
|
1034
|
+
@apply flex w-full items-center justify-between gap-2 px-4 py-3 text-left text-sm font-medium cursor-pointer;
|
|
1035
|
+
color: var(--color-fg);
|
|
1036
|
+
background: transparent;
|
|
1037
|
+
list-style: none;
|
|
1038
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1039
|
+
}
|
|
1040
|
+
.accordion-trigger::-webkit-details-marker { display: none; }
|
|
1041
|
+
.accordion-trigger:hover { background-color: var(--color-bg-muted); }
|
|
1042
|
+
.accordion-trigger:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1043
|
+
.accordion-item[open] > .accordion-trigger > .accordion-chevron {
|
|
1044
|
+
transform: rotate(180deg);
|
|
1045
|
+
}
|
|
1046
|
+
.accordion-chevron {
|
|
1047
|
+
@apply size-4 shrink-0;
|
|
1048
|
+
color: var(--color-fg-muted);
|
|
1049
|
+
transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1050
|
+
}
|
|
1051
|
+
.accordion-content {
|
|
1052
|
+
@apply px-4 pb-3 text-sm;
|
|
1053
|
+
color: var(--color-fg-muted);
|
|
333
1054
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
1055
|
+
|
|
1056
|
+
.collapsible {
|
|
1057
|
+
border: 1px solid var(--color-border);
|
|
1058
|
+
border-radius: var(--ui-radius);
|
|
1059
|
+
background-color: var(--color-bg-elevated);
|
|
1060
|
+
}
|
|
1061
|
+
.collapsible-trigger {
|
|
1062
|
+
@apply flex w-full items-center gap-2 px-3 py-2 text-left text-sm font-medium cursor-pointer;
|
|
1063
|
+
color: var(--color-fg);
|
|
1064
|
+
background: transparent;
|
|
1065
|
+
list-style: none;
|
|
1066
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1067
|
+
}
|
|
1068
|
+
.collapsible-trigger::-webkit-details-marker { display: none; }
|
|
1069
|
+
.collapsible-trigger:hover { background-color: var(--color-bg-muted); }
|
|
1070
|
+
.collapsible-trigger:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1071
|
+
.collapsible[open] > .collapsible-trigger > .collapsible-chevron {
|
|
1072
|
+
transform: rotate(90deg);
|
|
1073
|
+
}
|
|
1074
|
+
.collapsible-chevron {
|
|
1075
|
+
@apply size-4 shrink-0;
|
|
1076
|
+
color: var(--color-fg-muted);
|
|
1077
|
+
transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1078
|
+
}
|
|
1079
|
+
.collapsible-title { @apply flex-1; }
|
|
1080
|
+
.collapsible-content {
|
|
1081
|
+
@apply px-3 pb-3 pt-1 text-sm;
|
|
1082
|
+
color: var(--color-fg-muted);
|
|
343
1083
|
}
|
|
344
|
-
|
|
345
|
-
|
|
1084
|
+
|
|
1085
|
+
/* ============================================================ */
|
|
1086
|
+
/* Separator / Toolbar */
|
|
1087
|
+
/* ============================================================ */
|
|
1088
|
+
.separator { background-color: var(--color-border); }
|
|
1089
|
+
.separator-horizontal { @apply h-px w-full; }
|
|
1090
|
+
.separator-vertical { @apply w-px h-full self-stretch; }
|
|
1091
|
+
|
|
1092
|
+
.toolbar {
|
|
1093
|
+
@apply flex items-center gap-1 p-1;
|
|
1094
|
+
background-color: var(--color-bg-muted);
|
|
1095
|
+
border: 1px solid var(--color-border);
|
|
1096
|
+
border-radius: var(--ui-radius);
|
|
346
1097
|
}
|
|
347
|
-
.
|
|
348
|
-
|
|
1098
|
+
.toolbar-vertical { @apply flex-col items-stretch; }
|
|
1099
|
+
|
|
1100
|
+
/* ============================================================ */
|
|
1101
|
+
/* ButtonGroup — covers `.btn`, `.btn-secondary[data-pressed]` */
|
|
1102
|
+
/* ============================================================ */
|
|
1103
|
+
.btn-group { @apply inline-flex; }
|
|
1104
|
+
.btn-group > * { border-radius: 0; }
|
|
1105
|
+
.btn-group > :first-child {
|
|
1106
|
+
border-top-left-radius: var(--ui-radius);
|
|
1107
|
+
border-bottom-left-radius: var(--ui-radius);
|
|
1108
|
+
}
|
|
1109
|
+
.btn-group > :last-child {
|
|
1110
|
+
border-top-right-radius: var(--ui-radius);
|
|
1111
|
+
border-bottom-right-radius: var(--ui-radius);
|
|
1112
|
+
}
|
|
1113
|
+
.btn-group > * + * { margin-left: -1px; }
|
|
1114
|
+
|
|
1115
|
+
.btn-group-vertical { @apply flex-col; }
|
|
1116
|
+
.btn-group-vertical > * { width: 100%; border-radius: 0; }
|
|
1117
|
+
.btn-group-vertical > :first-child {
|
|
1118
|
+
border-top-left-radius: var(--ui-radius);
|
|
1119
|
+
border-top-right-radius: var(--ui-radius);
|
|
349
1120
|
}
|
|
350
|
-
.
|
|
351
|
-
|
|
1121
|
+
.btn-group-vertical > :last-child {
|
|
1122
|
+
border-bottom-left-radius: var(--ui-radius);
|
|
1123
|
+
border-bottom-right-radius: var(--ui-radius);
|
|
352
1124
|
}
|
|
353
|
-
.
|
|
354
|
-
|
|
1125
|
+
.btn-group-vertical > * + * { margin-left: 0; margin-top: -1px; }
|
|
1126
|
+
|
|
1127
|
+
/* ============================================================ */
|
|
1128
|
+
/* NumberInput */
|
|
1129
|
+
/* ============================================================ */
|
|
1130
|
+
.number-input {
|
|
1131
|
+
@apply inline-flex items-stretch;
|
|
1132
|
+
border-radius: var(--ui-radius);
|
|
1133
|
+
}
|
|
1134
|
+
.number-input-field {
|
|
1135
|
+
@apply text-center;
|
|
1136
|
+
border-radius: 0;
|
|
1137
|
+
min-width: 4rem;
|
|
1138
|
+
-moz-appearance: textfield;
|
|
1139
|
+
}
|
|
1140
|
+
.number-input-field::-webkit-outer-spin-button,
|
|
1141
|
+
.number-input-field::-webkit-inner-spin-button {
|
|
1142
|
+
-webkit-appearance: none;
|
|
1143
|
+
margin: 0;
|
|
1144
|
+
}
|
|
1145
|
+
.number-step {
|
|
1146
|
+
@apply inline-flex items-center justify-center px-2 cursor-pointer;
|
|
1147
|
+
background-color: var(--color-bg-muted);
|
|
1148
|
+
color: var(--color-fg);
|
|
1149
|
+
border: 1px solid var(--color-border-strong);
|
|
1150
|
+
height: var(--ui-h-md);
|
|
1151
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
355
1152
|
}
|
|
356
|
-
.
|
|
357
|
-
|
|
1153
|
+
.number-step:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1154
|
+
.number-step:first-child {
|
|
1155
|
+
border-top-left-radius: var(--ui-radius);
|
|
1156
|
+
border-bottom-left-radius: var(--ui-radius);
|
|
1157
|
+
border-right: none;
|
|
358
1158
|
}
|
|
359
|
-
.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
1159
|
+
.number-step:last-child {
|
|
1160
|
+
border-top-right-radius: var(--ui-radius);
|
|
1161
|
+
border-bottom-right-radius: var(--ui-radius);
|
|
1162
|
+
border-left: none;
|
|
1163
|
+
}
|
|
1164
|
+
.number-step:hover:not(:disabled) { background-color: var(--color-bg-subtle); }
|
|
1165
|
+
.number-step:disabled { @apply cursor-not-allowed opacity-40; }
|
|
1166
|
+
|
|
1167
|
+
/* ============================================================ */
|
|
1168
|
+
/* OtpField */
|
|
1169
|
+
/* ============================================================ */
|
|
1170
|
+
.otp-field { @apply inline-flex gap-2; }
|
|
1171
|
+
.otp-cell {
|
|
1172
|
+
@apply text-center font-mono text-lg;
|
|
1173
|
+
width: 2.75rem;
|
|
1174
|
+
height: 3rem;
|
|
1175
|
+
background-color: var(--color-bg);
|
|
1176
|
+
color: var(--color-fg);
|
|
1177
|
+
border: 1px solid var(--color-border-strong);
|
|
1178
|
+
border-radius: var(--ui-radius);
|
|
1179
|
+
transition: border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1180
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1181
|
+
}
|
|
1182
|
+
.otp-cell:focus-visible {
|
|
1183
|
+
outline: none;
|
|
1184
|
+
border-color: var(--color-ring);
|
|
1185
|
+
box-shadow: var(--ui-focus-ring);
|
|
363
1186
|
}
|
|
1187
|
+
|
|
1188
|
+
/* ============================================================ */
|
|
1189
|
+
/* TagsInput */
|
|
1190
|
+
/* ============================================================ */
|
|
1191
|
+
.tags-input {
|
|
1192
|
+
@apply flex w-full flex-wrap items-center gap-1.5 px-2 py-1.5;
|
|
1193
|
+
min-height: var(--ui-h-md);
|
|
1194
|
+
background-color: var(--color-bg);
|
|
1195
|
+
color: var(--color-fg);
|
|
1196
|
+
border: 1px solid var(--color-border-strong);
|
|
1197
|
+
border-radius: var(--ui-radius);
|
|
1198
|
+
transition: border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1199
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1200
|
+
}
|
|
1201
|
+
.tags-input:focus-within {
|
|
1202
|
+
outline: none;
|
|
1203
|
+
border-color: var(--color-ring);
|
|
1204
|
+
box-shadow: var(--ui-focus-ring);
|
|
1205
|
+
}
|
|
1206
|
+
.tags-input-err { border-color: var(--color-danger-500); }
|
|
1207
|
+
.tags-input-field {
|
|
1208
|
+
@apply min-w-[6rem] flex-1 text-sm outline-none;
|
|
1209
|
+
background: transparent;
|
|
1210
|
+
color: var(--color-fg);
|
|
1211
|
+
}
|
|
1212
|
+
.tags-input-field::placeholder { color: var(--color-fg-subtle); }
|
|
1213
|
+
|
|
1214
|
+
/* ============================================================ */
|
|
1215
|
+
/* Timeline */
|
|
1216
|
+
/* ============================================================ */
|
|
1217
|
+
.timeline { @apply list-none p-0 m-0 relative; }
|
|
1218
|
+
.timeline-item {
|
|
1219
|
+
@apply relative grid pl-10 pb-6;
|
|
1220
|
+
grid-template-columns: 1fr;
|
|
1221
|
+
}
|
|
1222
|
+
.timeline-item:last-child { @apply pb-0; }
|
|
1223
|
+
.timeline-dot {
|
|
1224
|
+
@apply absolute left-0 inline-flex items-center justify-center rounded-full text-white;
|
|
1225
|
+
width: var(--ui-icon-btn-md);
|
|
1226
|
+
height: var(--ui-icon-btn-md);
|
|
1227
|
+
background-color: var(--color-primary-600);
|
|
1228
|
+
top: 0;
|
|
1229
|
+
}
|
|
1230
|
+
.timeline-dot-success { background-color: var(--color-success-600); }
|
|
1231
|
+
.timeline-dot-warning { background-color: var(--color-warning-600); }
|
|
1232
|
+
.timeline-dot-danger { background-color: var(--color-danger-600); }
|
|
1233
|
+
.timeline-dot-info { background-color: var(--color-info-600); }
|
|
1234
|
+
.timeline-line {
|
|
1235
|
+
@apply absolute w-px;
|
|
1236
|
+
left: 0.875rem;
|
|
1237
|
+
top: 1.75rem;
|
|
1238
|
+
bottom: -0.5rem;
|
|
1239
|
+
background-color: var(--color-border);
|
|
1240
|
+
}
|
|
1241
|
+
.timeline-time { @apply text-xs; color: var(--color-fg-subtle); }
|
|
1242
|
+
.timeline-title { @apply text-sm font-semibold; color: var(--color-fg); }
|
|
1243
|
+
.timeline-description { @apply text-sm mt-0.5; color: var(--color-fg-muted); }
|
|
1244
|
+
|
|
1245
|
+
/* ============================================================ */
|
|
1246
|
+
/* Combobox / Autocomplete / MultiSelect */
|
|
1247
|
+
/* (Listbox styling — uses dropdown-content + dropdown-item) */
|
|
1248
|
+
/* ============================================================ */
|
|
1249
|
+
.combobox-input-wrap { @apply relative inline-flex w-full items-stretch; }
|
|
1250
|
+
.combobox-trigger { @apply absolute right-1 top-1/2 -translate-y-1/2; }
|
|
1251
|
+
/* Combobox-listbox is rendered with class="dropdown-content combobox-listbox"
|
|
1252
|
+
* so it inherits the elevated surface; this rule adds size constraints. */
|
|
1253
|
+
.combobox-listbox {
|
|
1254
|
+
max-height: 16rem;
|
|
1255
|
+
overflow-y: auto;
|
|
1256
|
+
min-width: 12rem;
|
|
1257
|
+
}
|
|
1258
|
+
.combobox-empty {
|
|
1259
|
+
@apply px-2 py-1.5 text-sm;
|
|
1260
|
+
color: var(--color-fg-muted);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/* MultiSelect — uses `.tags-input` as the wrapper so selected chips
|
|
1264
|
+
* render inline with the typed input. The `.multi-select` modifier
|
|
1265
|
+
* makes the wrapper a click target that focuses the inner input. */
|
|
1266
|
+
.multi-select { cursor: text; }
|
|
1267
|
+
.multi-select-toggle {
|
|
1268
|
+
@apply inline-flex items-center justify-center;
|
|
1269
|
+
width: var(--ui-icon-btn-sm);
|
|
1270
|
+
height: var(--ui-icon-btn-sm);
|
|
1271
|
+
padding: 0;
|
|
1272
|
+
border-radius: var(--ui-radius-sm);
|
|
1273
|
+
color: var(--color-fg-muted);
|
|
1274
|
+
background: transparent;
|
|
1275
|
+
border: none;
|
|
1276
|
+
cursor: pointer;
|
|
1277
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1278
|
+
color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1279
|
+
}
|
|
1280
|
+
.multi-select-toggle:hover {
|
|
1281
|
+
background-color: var(--color-bg-muted);
|
|
1282
|
+
color: var(--color-fg);
|
|
1283
|
+
}
|
|
1284
|
+
.multi-select-toggle:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1285
|
+
|
|
1286
|
+
/* ============================================================ */
|
|
1287
|
+
/* Navigation menu (Hierarchical / Mega) — CSS-only hover/focus */
|
|
1288
|
+
/* ============================================================ */
|
|
1289
|
+
.nav-menu { @apply relative z-10; }
|
|
1290
|
+
.nav-menu-list { @apply flex items-center gap-0 list-none p-0 m-0 flex-wrap; }
|
|
1291
|
+
.nav-menu-item { @apply relative; }
|
|
1292
|
+
.nav-menu-trigger {
|
|
1293
|
+
@apply inline-flex items-center gap-1 px-3 text-sm font-medium cursor-pointer select-none;
|
|
1294
|
+
height: var(--ui-h-md);
|
|
1295
|
+
color: var(--color-fg-muted);
|
|
1296
|
+
background-color: transparent;
|
|
1297
|
+
border-radius: var(--ui-radius-sm);
|
|
1298
|
+
text-decoration: none;
|
|
1299
|
+
border: none;
|
|
1300
|
+
font-family: inherit;
|
|
1301
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1302
|
+
color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1303
|
+
}
|
|
1304
|
+
.nav-menu-trigger:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1305
|
+
.nav-menu-trigger:hover {
|
|
1306
|
+
color: var(--color-fg);
|
|
1307
|
+
background-color: var(--color-bg-muted);
|
|
1308
|
+
}
|
|
1309
|
+
.nav-menu-chevron {
|
|
1310
|
+
@apply shrink-0;
|
|
1311
|
+
transition: transform var(--ui-motion-med) var(--ui-motion-ease);
|
|
1312
|
+
}
|
|
1313
|
+
.nav-menu-content {
|
|
1314
|
+
@apply absolute top-full left-0 mt-1 z-50 invisible;
|
|
1315
|
+
/* base surface comes from `.surface-elevated` selector list */
|
|
1316
|
+
min-width: 14rem;
|
|
1317
|
+
padding: 0.25rem;
|
|
1318
|
+
opacity: 0;
|
|
1319
|
+
transform: translateY(-4px);
|
|
1320
|
+
transition: opacity var(--ui-motion-med) var(--ui-motion-ease),
|
|
1321
|
+
transform var(--ui-motion-med) var(--ui-motion-ease),
|
|
1322
|
+
visibility var(--ui-motion-med) var(--ui-motion-ease);
|
|
1323
|
+
}
|
|
1324
|
+
.nav-menu-item:hover > .nav-menu-content,
|
|
1325
|
+
.nav-menu-item:focus-within > .nav-menu-content {
|
|
1326
|
+
@apply visible;
|
|
1327
|
+
opacity: 1;
|
|
1328
|
+
transform: translateY(0);
|
|
1329
|
+
}
|
|
1330
|
+
.nav-menu-item:hover > .nav-menu-trigger,
|
|
1331
|
+
.nav-menu-item:focus-within > .nav-menu-trigger {
|
|
1332
|
+
color: var(--color-fg);
|
|
1333
|
+
background-color: var(--color-bg-muted);
|
|
1334
|
+
}
|
|
1335
|
+
.nav-menu-item:hover > .nav-menu-trigger > .nav-menu-chevron,
|
|
1336
|
+
.nav-menu-item:focus-within > .nav-menu-trigger > .nav-menu-chevron {
|
|
1337
|
+
transform: rotate(180deg);
|
|
1338
|
+
}
|
|
1339
|
+
.nav-menu-link {
|
|
1340
|
+
@apply flex items-start gap-2 px-3 py-2 text-sm;
|
|
1341
|
+
color: var(--color-fg);
|
|
1342
|
+
text-decoration: none;
|
|
1343
|
+
border-radius: var(--ui-radius-sm);
|
|
1344
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1345
|
+
}
|
|
1346
|
+
.nav-menu-link:hover { background-color: var(--color-bg-muted); }
|
|
1347
|
+
|
|
1348
|
+
.mega-menu-grid {
|
|
1349
|
+
@apply grid gap-6 p-5;
|
|
1350
|
+
min-width: 32rem;
|
|
1351
|
+
}
|
|
1352
|
+
.mega-menu-grid.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
1353
|
+
.mega-menu-grid.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
|
|
1354
|
+
.mega-menu-grid.grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
|
|
1355
|
+
.mega-menu-column { @apply flex flex-col gap-1; }
|
|
1356
|
+
.mega-menu-title {
|
|
1357
|
+
@apply text-[11px] uppercase tracking-wider px-3 mb-1 font-semibold;
|
|
1358
|
+
color: var(--color-fg-subtle);
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
/* ============================================================ */
|
|
1362
|
+
/* ColorPicker */
|
|
1363
|
+
/* ============================================================ */
|
|
1364
|
+
.color-picker { @apply inline-flex items-center gap-2; }
|
|
1365
|
+
.color-picker-swatch {
|
|
1366
|
+
@apply inline-block size-9 cursor-pointer overflow-hidden;
|
|
1367
|
+
border: 1px solid var(--color-border-strong);
|
|
1368
|
+
border-radius: var(--ui-radius);
|
|
1369
|
+
}
|
|
1370
|
+
.color-picker-text { @apply font-mono; width: 8.5rem; }
|
|
1371
|
+
|
|
1372
|
+
/* ============================================================ */
|
|
1373
|
+
/* Uploader */
|
|
1374
|
+
/* ============================================================ */
|
|
1375
|
+
.uploader-root {
|
|
1376
|
+
@apply flex w-full flex-col items-center justify-center gap-2 p-6 text-center cursor-pointer;
|
|
1377
|
+
background-color: var(--color-bg-subtle);
|
|
1378
|
+
color: var(--color-fg);
|
|
1379
|
+
border: 2px dashed var(--color-border-strong);
|
|
1380
|
+
border-radius: var(--ui-radius);
|
|
1381
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1382
|
+
border-color var(--ui-motion-fast) var(--ui-motion-ease),
|
|
1383
|
+
box-shadow var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1384
|
+
}
|
|
1385
|
+
.uploader-root:hover { background-color: var(--color-bg-muted); }
|
|
1386
|
+
.uploader-root:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1387
|
+
.uploader-dragging {
|
|
1388
|
+
background-color: color-mix(in oklab, var(--color-primary-500) 6%, var(--color-bg-muted));
|
|
1389
|
+
border-color: var(--color-primary-500);
|
|
1390
|
+
}
|
|
1391
|
+
.uploader-text { @apply flex flex-col items-center gap-0.5; }
|
|
1392
|
+
.uploader-primary { @apply text-sm font-medium; }
|
|
1393
|
+
.uploader-helper { @apply text-xs; color: var(--color-fg-muted); }
|
|
1394
|
+
.uploader-list { @apply mt-2 flex flex-col gap-1 list-none p-0; }
|
|
1395
|
+
.uploader-item {
|
|
1396
|
+
@apply flex items-center gap-2 px-2 py-1.5;
|
|
1397
|
+
background-color: var(--color-bg-muted);
|
|
1398
|
+
border-radius: var(--ui-radius-sm);
|
|
1399
|
+
}
|
|
1400
|
+
|
|
1401
|
+
/* ============================================================ */
|
|
1402
|
+
/* Date / Time pickers + custom Calendar */
|
|
1403
|
+
/* ============================================================ */
|
|
1404
|
+
.date-picker-trigger {
|
|
1405
|
+
@apply inline-flex items-center gap-2 cursor-pointer text-left w-full;
|
|
1406
|
+
min-width: 12rem;
|
|
1407
|
+
}
|
|
1408
|
+
.date-picker-trigger[disabled] { @apply opacity-60 cursor-not-allowed; }
|
|
1409
|
+
|
|
1410
|
+
.calendar { @apply select-none; }
|
|
1411
|
+
.calendar-header {
|
|
1412
|
+
@apply flex items-center justify-between gap-1 mb-2;
|
|
1413
|
+
}
|
|
1414
|
+
.calendar-heading-btn {
|
|
1415
|
+
@apply flex-1 text-sm font-semibold py-1 px-2 cursor-pointer;
|
|
1416
|
+
color: var(--color-fg);
|
|
1417
|
+
background: transparent;
|
|
1418
|
+
border: none;
|
|
1419
|
+
border-radius: var(--ui-radius-sm);
|
|
1420
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1421
|
+
}
|
|
1422
|
+
.calendar-heading-btn:hover { background-color: var(--color-bg-muted); }
|
|
1423
|
+
.calendar-heading-btn:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1424
|
+
/* `.calendar-nav` is in the `.btn-icon` selector list above. */
|
|
1425
|
+
.calendar-row {
|
|
1426
|
+
@apply grid gap-0.5;
|
|
1427
|
+
grid-template-columns: repeat(7, minmax(0, 1fr));
|
|
1428
|
+
}
|
|
1429
|
+
.calendar-weekdays { @apply mb-1; }
|
|
1430
|
+
.calendar-weekday {
|
|
1431
|
+
@apply text-center text-[11px] font-medium uppercase py-1;
|
|
1432
|
+
color: var(--color-fg-subtle);
|
|
1433
|
+
}
|
|
1434
|
+
.calendar-day {
|
|
1435
|
+
@apply h-9 w-full inline-flex items-center justify-center text-sm cursor-pointer;
|
|
1436
|
+
color: var(--color-fg);
|
|
1437
|
+
background: transparent;
|
|
1438
|
+
border: none;
|
|
1439
|
+
border-radius: var(--ui-radius-sm);
|
|
1440
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1441
|
+
}
|
|
1442
|
+
.calendar-day:hover:not(:disabled) { background-color: var(--color-bg-muted); }
|
|
1443
|
+
.calendar-day:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1444
|
+
.calendar-day-outside { color: var(--color-fg-subtle); }
|
|
1445
|
+
.calendar-day-today {
|
|
1446
|
+
font-weight: 600;
|
|
1447
|
+
box-shadow: inset 0 0 0 1px var(--color-border-strong);
|
|
1448
|
+
}
|
|
1449
|
+
.calendar-day-selected,
|
|
1450
|
+
.calendar-day-selected:hover:not(:disabled) {
|
|
1451
|
+
background-color: var(--color-primary-600);
|
|
1452
|
+
color: white;
|
|
1453
|
+
font-weight: 600;
|
|
1454
|
+
}
|
|
1455
|
+
.calendar-day-selected:hover:not(:disabled) { background-color: var(--color-primary-700); }
|
|
1456
|
+
.calendar-day-in-range {
|
|
1457
|
+
background-color: color-mix(in oklab, var(--color-primary-500) 12%, transparent);
|
|
1458
|
+
border-radius: 0;
|
|
1459
|
+
}
|
|
1460
|
+
.calendar-day:disabled { @apply opacity-30 cursor-not-allowed; }
|
|
1461
|
+
|
|
1462
|
+
.time-picker-popover { min-width: 14rem; }
|
|
1463
|
+
.time-picker-grid { @apply flex items-stretch gap-1; }
|
|
1464
|
+
.time-picker-col {
|
|
1465
|
+
@apply flex-1 flex flex-col gap-0.5 overflow-y-auto py-1;
|
|
1466
|
+
max-height: 14rem;
|
|
1467
|
+
scroll-snap-type: y mandatory;
|
|
1468
|
+
scrollbar-width: thin;
|
|
1469
|
+
}
|
|
1470
|
+
.time-picker-col::-webkit-scrollbar { width: 4px; }
|
|
1471
|
+
.time-picker-col::-webkit-scrollbar-thumb {
|
|
1472
|
+
background-color: var(--color-border-strong);
|
|
1473
|
+
border-radius: 2px;
|
|
1474
|
+
}
|
|
1475
|
+
.time-picker-sep {
|
|
1476
|
+
@apply self-center text-xl font-mono;
|
|
1477
|
+
color: var(--color-fg-muted);
|
|
1478
|
+
}
|
|
1479
|
+
.time-picker-cell {
|
|
1480
|
+
@apply h-8 inline-flex items-center justify-center text-sm font-mono tabular-nums cursor-pointer;
|
|
1481
|
+
color: var(--color-fg);
|
|
1482
|
+
background: transparent;
|
|
1483
|
+
border: none;
|
|
1484
|
+
border-radius: var(--ui-radius-sm);
|
|
1485
|
+
scroll-snap-align: center;
|
|
1486
|
+
flex-shrink: 0;
|
|
1487
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1488
|
+
}
|
|
1489
|
+
.time-picker-cell:hover { background-color: var(--color-bg-muted); }
|
|
1490
|
+
.time-picker-cell-selected,
|
|
1491
|
+
.time-picker-cell-selected:hover {
|
|
1492
|
+
background-color: var(--color-primary-600);
|
|
1493
|
+
color: white;
|
|
1494
|
+
font-weight: 600;
|
|
1495
|
+
}
|
|
1496
|
+
.time-picker-cell-selected:hover { background-color: var(--color-primary-700); }
|
|
1497
|
+
|
|
1498
|
+
/* ============================================================ */
|
|
1499
|
+
/* DataTable */
|
|
1500
|
+
/* ============================================================ */
|
|
1501
|
+
.data-table-root {
|
|
1502
|
+
@apply w-full overflow-x-auto;
|
|
1503
|
+
border: 1px solid var(--color-border);
|
|
1504
|
+
border-radius: var(--ui-radius);
|
|
1505
|
+
}
|
|
1506
|
+
.data-table { @apply w-full text-sm; border-collapse: collapse; }
|
|
1507
|
+
.data-table th,
|
|
1508
|
+
.data-table td { @apply px-3 py-2 text-left align-middle; }
|
|
1509
|
+
.data-table thead th {
|
|
1510
|
+
@apply font-semibold;
|
|
1511
|
+
color: var(--color-fg);
|
|
1512
|
+
background-color: var(--color-bg-muted);
|
|
1513
|
+
border-bottom: 1px solid var(--color-border);
|
|
1514
|
+
}
|
|
1515
|
+
.data-table-sticky thead th { @apply sticky top-0 z-10; }
|
|
1516
|
+
.data-table tbody tr { border-bottom: 1px solid var(--color-border); }
|
|
1517
|
+
.data-table tbody tr:last-child { border-bottom: none; }
|
|
1518
|
+
.data-table tbody tr:hover { background-color: var(--color-bg-muted); }
|
|
1519
|
+
.data-table-striped tbody tr:nth-child(even) {
|
|
1520
|
+
background-color: var(--color-bg-subtle);
|
|
1521
|
+
}
|
|
1522
|
+
.data-table-dense th,
|
|
1523
|
+
.data-table-dense td { @apply py-1; }
|
|
1524
|
+
.data-table-row-clickable { @apply cursor-pointer; }
|
|
1525
|
+
.data-table-empty td {
|
|
1526
|
+
@apply text-center py-6;
|
|
1527
|
+
color: var(--color-fg-muted);
|
|
1528
|
+
}
|
|
1529
|
+
.data-table-sort {
|
|
1530
|
+
@apply inline-flex items-center gap-1;
|
|
1531
|
+
background: transparent;
|
|
1532
|
+
color: inherit;
|
|
1533
|
+
font: inherit;
|
|
1534
|
+
cursor: pointer;
|
|
1535
|
+
}
|
|
1536
|
+
.data-table-sort:hover { color: var(--color-primary-600); }
|
|
1537
|
+
|
|
1538
|
+
/* ============================================================ */
|
|
1539
|
+
/* Tree */
|
|
1540
|
+
/* ============================================================ */
|
|
1541
|
+
.tree { @apply text-sm; color: var(--color-fg); }
|
|
1542
|
+
.tree ul { @apply list-none p-0 m-0; }
|
|
1543
|
+
.tree-row {
|
|
1544
|
+
@apply flex w-full items-center gap-2 py-1 pr-2 text-left cursor-pointer;
|
|
1545
|
+
color: var(--color-fg);
|
|
1546
|
+
background-color: transparent;
|
|
1547
|
+
border-radius: var(--ui-radius-sm);
|
|
1548
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1549
|
+
}
|
|
1550
|
+
.tree-row:hover { background-color: var(--color-bg-muted); }
|
|
1551
|
+
.tree-row:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1552
|
+
.tree-row-selected,
|
|
1553
|
+
.tree-row-selected:hover {
|
|
1554
|
+
background-color: color-mix(in oklab, var(--color-primary-500) 12%, transparent);
|
|
1555
|
+
color: var(--color-fg);
|
|
1556
|
+
}
|
|
1557
|
+
.tree-chevron {
|
|
1558
|
+
@apply inline-flex size-4 shrink-0 items-center justify-center;
|
|
1559
|
+
color: var(--color-fg-muted);
|
|
1560
|
+
transition: transform var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1561
|
+
}
|
|
1562
|
+
.tree-chevron-open { transform: rotate(90deg); }
|
|
1563
|
+
.tree-chevron-spacer { @apply inline-block size-4 shrink-0; }
|
|
1564
|
+
.tree-label { @apply truncate; }
|
|
1565
|
+
|
|
1566
|
+
/* ============================================================ */
|
|
1567
|
+
/* ScrollArea */
|
|
1568
|
+
/* Atom-defined so the overflow rules ship in atoms.css; cannot */
|
|
1569
|
+
/* rely on Tailwind utility generation inside library `cn()` */
|
|
1570
|
+
/* calls because Tailwind v4 doesn't scan workspace-dep sources */
|
|
1571
|
+
/* by default. */
|
|
1572
|
+
/* ============================================================ */
|
|
1573
|
+
.norns-scroll-area {
|
|
1574
|
+
overflow-y: auto;
|
|
1575
|
+
overflow-x: hidden;
|
|
1576
|
+
}
|
|
1577
|
+
.norns-scroll-area-horizontal {
|
|
1578
|
+
overflow-x: auto;
|
|
1579
|
+
overflow-y: hidden;
|
|
1580
|
+
}
|
|
1581
|
+
.norns-scroll-area-both {
|
|
1582
|
+
overflow: auto;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/* ============================================================ */
|
|
1586
|
+
/* Carousel */
|
|
1587
|
+
/* ============================================================ */
|
|
1588
|
+
.carousel {
|
|
1589
|
+
@apply relative overflow-hidden w-full;
|
|
1590
|
+
border-radius: var(--ui-radius);
|
|
1591
|
+
background-color: var(--color-bg-muted);
|
|
1592
|
+
}
|
|
1593
|
+
.carousel-track {
|
|
1594
|
+
@apply flex h-full;
|
|
1595
|
+
transition: transform 500ms var(--ui-motion-ease);
|
|
1596
|
+
}
|
|
1597
|
+
.carousel-slide { @apply h-full w-full shrink-0; }
|
|
1598
|
+
.carousel-arrow {
|
|
1599
|
+
@apply absolute top-1/2 -translate-y-1/2 inline-flex items-center justify-center cursor-pointer;
|
|
1600
|
+
width: var(--ui-icon-btn-lg);
|
|
1601
|
+
height: var(--ui-icon-btn-lg);
|
|
1602
|
+
background-color: color-mix(in oklab, var(--color-bg) 70%, transparent);
|
|
1603
|
+
color: var(--color-fg);
|
|
1604
|
+
border: 1px solid var(--color-border);
|
|
1605
|
+
border-radius: var(--ui-radius-full);
|
|
1606
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1607
|
+
}
|
|
1608
|
+
.carousel-arrow:hover { background-color: var(--color-bg); }
|
|
1609
|
+
.carousel-arrow:focus-visible { outline: none; box-shadow: var(--ui-focus-ring); }
|
|
1610
|
+
.carousel-arrow-prev { @apply left-3; }
|
|
1611
|
+
.carousel-arrow-next { @apply right-3; }
|
|
1612
|
+
.carousel-dots {
|
|
1613
|
+
@apply absolute bottom-3 left-1/2 -translate-x-1/2 inline-flex items-center gap-1.5;
|
|
1614
|
+
}
|
|
1615
|
+
.carousel-dot {
|
|
1616
|
+
@apply size-2 rounded-full cursor-pointer;
|
|
1617
|
+
background-color: color-mix(in oklab, var(--color-bg-inverse) 50%, transparent);
|
|
1618
|
+
border: none;
|
|
1619
|
+
transition: background-color var(--ui-motion-fast) var(--ui-motion-ease);
|
|
1620
|
+
}
|
|
1621
|
+
.carousel-dot-active { background-color: var(--color-bg-inverse); }
|
|
364
1622
|
}
|