@aortl/admin-css 0.16.0 → 0.16.2
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/CHANGELOG.md +54 -0
- package/dist/admin.css +25 -4
- package/dist/admin.min.css +1 -1
- package/dist/admin.scoped.css +25 -4
- package/dist/admin.scoped.min.css +18 -15
- package/package.json +3 -2
- package/src/components/accordion.css +7 -10
- package/src/components/alert.css +6 -21
- package/src/components/app-shell.css +2 -4
- package/src/components/badge.css +1 -5
- package/src/components/breadcrumbs.css +3 -8
- package/src/components/button-group.css +7 -19
- package/src/components/button.css +7 -23
- package/src/components/card.css +13 -20
- package/src/components/chart.css +26 -83
- package/src/components/checkbox.css +5 -7
- package/src/components/code-block.css +2 -4
- package/src/components/container.css +3 -7
- package/src/components/dialog.css +13 -13
- package/src/components/field.css +4 -4
- package/src/components/footer.css +2 -3
- package/src/components/indicator.css +9 -28
- package/src/components/input-group.css +3 -6
- package/src/components/input.css +2 -5
- package/src/components/kbd.css +7 -13
- package/src/components/link.css +3 -5
- package/src/components/menu.css +11 -21
- package/src/components/navbar.css +3 -7
- package/src/components/pagination.css +1 -4
- package/src/components/progress.css +3 -7
- package/src/components/property-list.css +5 -14
- package/src/components/prose.css +7 -21
- package/src/components/radio.css +5 -5
- package/src/components/select.css +6 -9
- package/src/components/sidebar.css +2 -7
- package/src/components/spinner.css +1 -4
- package/src/components/stat-card.css +5 -16
- package/src/components/switch.css +5 -3
- package/src/components/table.css +20 -30
- package/src/components/tabs.css +14 -32
- package/src/components/textarea.css +3 -7
- package/src/components/tooltip.css +6 -16
- package/src/fonts.css +8 -28
- package/src/theme.css +32 -100
- package/src/utilities.css +11 -37
package/src/components/tabs.css
CHANGED
|
@@ -3,10 +3,8 @@
|
|
|
3
3
|
@apply flex flex-col;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
-
/*
|
|
7
|
-
|
|
8
|
-
scoped under `.tabs` so generic `class="tab"` markup elsewhere on the
|
|
9
|
-
page (e.g. Starlight's own <Tabs> component) doesn't pick them up. */
|
|
6
|
+
/* All selectors are scoped under `.tabs` so generic `class="tab"` markup
|
|
7
|
+
elsewhere (e.g. Starlight's own <Tabs>) doesn't pick them up. */
|
|
10
8
|
.tabs .tab-list {
|
|
11
9
|
@apply inline-flex items-center gap-1 border-b border-border;
|
|
12
10
|
/* Containing block for the sliding ::before marker (see @supports below) */
|
|
@@ -30,14 +28,11 @@
|
|
|
30
28
|
@apply text-text;
|
|
31
29
|
}
|
|
32
30
|
|
|
33
|
-
/* Keep a tab's leading icon at its intrinsic size when the label is long. */
|
|
34
31
|
.tabs .tab > :is(i, svg) {
|
|
35
32
|
flex-shrink: 0;
|
|
36
33
|
}
|
|
37
34
|
|
|
38
|
-
/* Vanilla radio
|
|
39
|
-
<label class="tab"> as the selected tab when the radio is :checked.
|
|
40
|
-
Pairs with `:has(input:checked)` below to show the right panel. */
|
|
35
|
+
/* Vanilla radio pattern: hidden inputs; :checked styles the following label. */
|
|
41
36
|
.tabs .tab-input {
|
|
42
37
|
position: absolute;
|
|
43
38
|
width: 1px;
|
|
@@ -57,9 +52,7 @@
|
|
|
57
52
|
@apply outline-2 outline-offset-2 outline-focus;
|
|
58
53
|
}
|
|
59
54
|
|
|
60
|
-
/* Default
|
|
61
|
-
.tab, overlapping the .tab-list bottom border. Applies to any tabs root
|
|
62
|
-
that isn't .tabs-boxed, so the bare `.tabs` default gets it for free. */
|
|
55
|
+
/* Default underline marker — the pseudo overlaps the .tab-list bottom border. */
|
|
63
56
|
.tabs:not(.tabs-boxed) .tab {
|
|
64
57
|
position: relative;
|
|
65
58
|
}
|
|
@@ -81,13 +74,12 @@
|
|
|
81
74
|
transform: scaleX(1);
|
|
82
75
|
}
|
|
83
76
|
|
|
84
|
-
/* Boxed (segmented control)
|
|
77
|
+
/* Boxed (segmented control). */
|
|
85
78
|
.tabs-boxed .tab-list {
|
|
86
79
|
@apply gap-0 p-0.5 border border-border rounded-md bg-surface-muted;
|
|
87
80
|
}
|
|
88
81
|
|
|
89
|
-
/* Sit above the sliding thumb (
|
|
90
|
-
legible while it passes behind them. */
|
|
82
|
+
/* Sit above the sliding thumb (::before below) so labels stay legible. */
|
|
91
83
|
.tabs-boxed .tab {
|
|
92
84
|
@apply rounded relative z-[1];
|
|
93
85
|
}
|
|
@@ -98,14 +90,11 @@
|
|
|
98
90
|
@apply bg-surface text-text shadow-sm;
|
|
99
91
|
}
|
|
100
92
|
|
|
101
|
-
/* Sliding active marker
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
page don't cross-anchor; gating the whole block on its support keeps the
|
|
107
|
-
effect off where it'd misbehave, leaving the per-tab marker above as the
|
|
108
|
-
fallback. */
|
|
93
|
+
/* Sliding active marker, zero extra DOM: the selected tab becomes a CSS
|
|
94
|
+
anchor and a single .tab-list pseudo tracks it via anchor() insets, which
|
|
95
|
+
the browser interpolates between tabs — vanilla `:checked` and React both
|
|
96
|
+
slide. `anchor-scope` confines the name per list so multiple tab sets
|
|
97
|
+
don't cross-anchor; the per-tab marker above remains the fallback. */
|
|
109
98
|
@supports (anchor-scope: --x) {
|
|
110
99
|
.tabs .tab-list {
|
|
111
100
|
anchor-scope: --tab-thumb;
|
|
@@ -123,8 +112,7 @@
|
|
|
123
112
|
position-anchor: --tab-thumb;
|
|
124
113
|
}
|
|
125
114
|
|
|
126
|
-
/* Bordered: a
|
|
127
|
-
per-tab ::after grow. */
|
|
115
|
+
/* Bordered: a bar sliding along the bottom edge replaces the per-tab ::after grow. */
|
|
128
116
|
.tabs:not(.tabs-boxed) .tab::after {
|
|
129
117
|
display: none;
|
|
130
118
|
}
|
|
@@ -175,7 +163,6 @@
|
|
|
175
163
|
}
|
|
176
164
|
}
|
|
177
165
|
|
|
178
|
-
/* Full width — list stretches across the container, tabs share space evenly. */
|
|
179
166
|
.tabs-full-width:not([data-orientation="vertical"]) .tab-list {
|
|
180
167
|
@apply flex w-full;
|
|
181
168
|
}
|
|
@@ -184,7 +171,6 @@
|
|
|
184
171
|
@apply flex-1 justify-center;
|
|
185
172
|
}
|
|
186
173
|
|
|
187
|
-
/* Sizes — cascade to nested tabs. */
|
|
188
174
|
.tabs-sm .tab {
|
|
189
175
|
@apply px-2 h-7 text-xs;
|
|
190
176
|
}
|
|
@@ -198,8 +184,7 @@
|
|
|
198
184
|
@apply pt-3 outline-none;
|
|
199
185
|
}
|
|
200
186
|
|
|
201
|
-
/* Vanilla
|
|
202
|
-
checked input is shown. Each .tabs root scopes its own selectors. */
|
|
187
|
+
/* Vanilla pattern: show only the panel whose data-value matches the checked input. */
|
|
203
188
|
.tabs .tab-panel {
|
|
204
189
|
display: none;
|
|
205
190
|
}
|
|
@@ -213,14 +198,11 @@
|
|
|
213
198
|
display: block;
|
|
214
199
|
}
|
|
215
200
|
|
|
216
|
-
/* Base UI
|
|
217
|
-
above is a no-op there. Reinstate display when the panel is shown by
|
|
218
|
-
Base UI. */
|
|
201
|
+
/* Base UI applies `hidden` itself — reinstate display for its panels. */
|
|
219
202
|
.tabs .tab-panel:not([hidden]):not([data-value]) {
|
|
220
203
|
display: block;
|
|
221
204
|
}
|
|
222
205
|
|
|
223
|
-
/* Vertical orientation. */
|
|
224
206
|
.tabs[data-orientation="vertical"] {
|
|
225
207
|
@apply flex-row gap-3;
|
|
226
208
|
}
|
|
@@ -18,8 +18,7 @@
|
|
|
18
18
|
@apply border-danger hover:border-danger focus-visible:outline-danger;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
/* Status variants
|
|
22
|
-
warning's yellow accent (which fails AA as text) is fine here. */
|
|
21
|
+
/* Status variants color border + outline only — warning's yellow fails AA as text. */
|
|
23
22
|
.textarea-info {
|
|
24
23
|
@apply border-info hover:border-info focus-visible:outline-info;
|
|
25
24
|
}
|
|
@@ -32,16 +31,13 @@
|
|
|
32
31
|
@apply border-warning hover:border-warning focus-visible:outline-warning;
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
/* Grow with content (Chromium 123+;
|
|
36
|
-
|
|
37
|
-
attribute; cap growth with a consumer `max-height`. Manual drag-resize is
|
|
38
|
-
off — height is content-driven. */
|
|
34
|
+
/* Grow with content (Chromium 123+; fixed box elsewhere). Floor is the larger
|
|
35
|
+
of `min-h-*` and `rows`; cap with a consumer `max-height`. */
|
|
39
36
|
.textarea-autosize {
|
|
40
37
|
field-sizing: content;
|
|
41
38
|
resize: none;
|
|
42
39
|
}
|
|
43
40
|
|
|
44
|
-
/* Sizes */
|
|
45
41
|
.textarea-sm {
|
|
46
42
|
@apply text-xs px-2.5 py-1.5 min-h-16;
|
|
47
43
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
@layer components {
|
|
2
|
-
/*
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* driven by Base UI's `data-side` / `data-starting-style` / `data-ending-style`
|
|
8
|
-
* attributes.
|
|
9
|
-
*
|
|
10
|
-
* Vanilla: `.tooltip-wrap` is a `position: relative` parent that reveals a
|
|
11
|
-
* nested `.tooltip` on `:hover` / `:focus-within`. No portal, no JS — works in
|
|
12
|
-
* every modern browser today. The platform-native future is `interesttarget` +
|
|
13
|
-
* `popover="hint"`, but cross-browser support is still rolling out.
|
|
14
|
-
*/
|
|
2
|
+
/* Two paths, one class. React: Base UI portals and positions the popup;
|
|
3
|
+
`.tooltip` carries paint + per-side transitions via Base UI's data attrs.
|
|
4
|
+
Vanilla: `.tooltip-wrap` reveals a nested `.tooltip` on :hover /
|
|
5
|
+
:focus-within — no JS. Replace with `interesttarget` + `popover="hint"`
|
|
6
|
+
once cross-browser support lands. */
|
|
15
7
|
.tooltip {
|
|
16
8
|
@apply inline-block max-w-xs px-2 py-1
|
|
17
9
|
rounded-md
|
|
@@ -22,13 +14,11 @@
|
|
|
22
14
|
text-wrap: balance;
|
|
23
15
|
}
|
|
24
16
|
|
|
25
|
-
/* Sizes */
|
|
26
17
|
.tooltip-sm {
|
|
27
18
|
@apply px-1.5 py-0.5;
|
|
28
19
|
}
|
|
29
20
|
|
|
30
|
-
/* React
|
|
31
|
-
150ms ease, matching Dialog. */
|
|
21
|
+
/* React enter/exit — Base UI sets these data attrs; 150ms matches Dialog. */
|
|
32
22
|
.tooltip {
|
|
33
23
|
transition:
|
|
34
24
|
opacity 150ms ease-out,
|
package/src/fonts.css
CHANGED
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* IBM Plex Sans + Mono
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* the wght axis); Plex Mono ships as discrete weight files.
|
|
7
|
-
*
|
|
8
|
-
* `font-display: swap` paints text immediately. Layout shift on swap is
|
|
9
|
-
* neutralised by the metric-matched fallback faces below ("IBM Plex Sans
|
|
10
|
-
* Fallback" / "IBM Plex Mono Fallback"): they alias a local system font but
|
|
11
|
-
* override its metrics to occupy Plex's exact box, so the swap changes glyph
|
|
12
|
-
* shapes without moving anything. The fallback families are wired into
|
|
13
|
-
* `--font-sans` / `--font-mono` in theme.css, ahead of the generic stack.
|
|
14
|
-
*
|
|
15
|
-
* Opt out by overriding `--font-sans` / `--font-mono`, or by importing
|
|
16
|
-
* admin-css's source files individually and skipping this one.
|
|
2
|
+
* IBM Plex Sans + Mono from Google's CDN (latin + latin-ext only).
|
|
3
|
+
* `font-display: swap` paints text immediately; the metric-matched fallback
|
|
4
|
+
* faces below occupy Plex's exact box, so the swap changes glyph shapes
|
|
5
|
+
* without layout shift. Opt out by overriding `--font-sans` / `--font-mono`.
|
|
17
6
|
*/
|
|
18
7
|
|
|
19
|
-
/* IBM Plex Sans — variable, weights 400–600 */
|
|
20
8
|
@font-face {
|
|
21
9
|
font-family: "IBM Plex Sans";
|
|
22
10
|
font-style: normal;
|
|
@@ -41,7 +29,6 @@
|
|
|
41
29
|
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
42
30
|
}
|
|
43
31
|
|
|
44
|
-
/* IBM Plex Mono — discrete weights 400, 500 */
|
|
45
32
|
@font-face {
|
|
46
33
|
font-family: "IBM Plex Mono";
|
|
47
34
|
font-style: normal;
|
|
@@ -89,16 +76,10 @@
|
|
|
89
76
|
U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
90
77
|
}
|
|
91
78
|
|
|
92
|
-
/*
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* doesn't depend on capsize, so if the primary font ever changes, recompute
|
|
97
|
-
* them with capsize rather than hand-editing. size-adjust holds in every
|
|
98
|
-
* engine; the ascent/descent overrides are ignored by Safari/WebKit, but
|
|
99
|
-
* line-gap is 0 so the residual vertical shift there is negligible.
|
|
100
|
-
*/
|
|
101
|
-
/* IBM Plex Sans -> Arial */
|
|
79
|
+
/* Metric-matched fallbacks — override numbers computed with @capsizecss/core
|
|
80
|
+
`createFontStack` (not a dependency); if the primary font changes, recompute
|
|
81
|
+
there rather than hand-editing. Safari/WebKit ignores the ascent/descent
|
|
82
|
+
overrides, but line-gap is 0 so the residual shift there is negligible. */
|
|
102
83
|
@font-face {
|
|
103
84
|
font-family: "IBM Plex Sans Fallback";
|
|
104
85
|
src: local("Arial"), local("ArialMT");
|
|
@@ -107,7 +88,6 @@
|
|
|
107
88
|
line-gap-override: 0%;
|
|
108
89
|
size-adjust: 101.1663%;
|
|
109
90
|
}
|
|
110
|
-
/* IBM Plex Mono -> Courier New */
|
|
111
91
|
@font-face {
|
|
112
92
|
font-family: "IBM Plex Mono Fallback";
|
|
113
93
|
src: local("Courier New"), local("CourierNewPSMT");
|
package/src/theme.css
CHANGED
|
@@ -1,38 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
* Design tokens —
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 1. Palette — the Flexoki ramps (paper, black, base, red, orange,
|
|
9
|
-
* yellow, green, cyan, blue, purple, magenta). Replaces Tailwind's
|
|
10
|
-
* default colors entirely. Tones are absolute and identical in
|
|
11
|
-
* light/dark mode — Flexoki's inverted ramp pairs (paper↔black,
|
|
12
|
-
* base-50↔base-950, blue-600↔blue-400, …) live in the semantic
|
|
13
|
-
* layer below.
|
|
14
|
-
*
|
|
15
|
-
* 2. Semantic — purpose-named aliases (primary, surface, danger, ...)
|
|
16
|
-
* pointing at palette tones via `light-dark()`. The active value
|
|
17
|
-
* tracks the cascaded `color-scheme` declared on :root: auto by
|
|
18
|
-
* default (system preference), forced via `[data-theme="dark"]` or
|
|
19
|
-
* `[data-theme="light"]`. Components only reference these aliases,
|
|
20
|
-
* so they pick up dark mode for free.
|
|
21
|
-
*
|
|
22
|
-
* Reskin by remapping the alias:
|
|
23
|
-
*
|
|
24
|
-
* :root { --color-primary: var(--color-green-600); }
|
|
25
|
-
*
|
|
26
|
-
* or replacing the palette tone underneath:
|
|
27
|
-
*
|
|
28
|
-
* :root { --color-blue-600: oklch(0.55 0.18 250); }
|
|
1
|
+
/*
|
|
2
|
+
* Design tokens — Flexoki (https://stephango.com/flexoki), two @theme layers:
|
|
3
|
+
* palette ramps (absolute tones, identical in light and dark) and semantic
|
|
4
|
+
* aliases declared via light-dark(), which flip with the cascaded color-scheme.
|
|
5
|
+
* Components reference only the semantic aliases; reskin by remapping an alias
|
|
6
|
+
* (--color-primary) or the palette tone underneath it.
|
|
29
7
|
*/
|
|
30
8
|
|
|
31
9
|
@theme static {
|
|
32
10
|
/* Wipe Tailwind's default palette — Flexoki is the single source of truth. */
|
|
33
11
|
--color-*: initial;
|
|
34
12
|
|
|
35
|
-
/* Base */
|
|
36
13
|
--color-paper: #ffffff;
|
|
37
14
|
--color-black: #0f0f0f;
|
|
38
15
|
--color-base-50: #fafafa;
|
|
@@ -49,7 +26,6 @@
|
|
|
49
26
|
--color-base-900: #272727;
|
|
50
27
|
--color-base-950: #1b1b1b;
|
|
51
28
|
|
|
52
|
-
/* Red */
|
|
53
29
|
--color-red-50: #ffe1d5;
|
|
54
30
|
--color-red-100: #ffcabb;
|
|
55
31
|
--color-red-150: #fdb2a2;
|
|
@@ -64,7 +40,6 @@
|
|
|
64
40
|
--color-red-900: #3e1715;
|
|
65
41
|
--color-red-950: #261312;
|
|
66
42
|
|
|
67
|
-
/* Orange */
|
|
68
43
|
--color-orange-50: #ffe7ce;
|
|
69
44
|
--color-orange-100: #fed3af;
|
|
70
45
|
--color-orange-150: #fcc192;
|
|
@@ -79,7 +54,6 @@
|
|
|
79
54
|
--color-orange-900: #40200d;
|
|
80
55
|
--color-orange-950: #27180e;
|
|
81
56
|
|
|
82
|
-
/* Yellow */
|
|
83
57
|
--color-yellow-50: #faeec6;
|
|
84
58
|
--color-yellow-100: #f6e2a0;
|
|
85
59
|
--color-yellow-150: #f1d67e;
|
|
@@ -94,7 +68,6 @@
|
|
|
94
68
|
--color-yellow-900: #3a2d04;
|
|
95
69
|
--color-yellow-950: #241e08;
|
|
96
70
|
|
|
97
|
-
/* Green */
|
|
98
71
|
--color-green-50: #edeecf;
|
|
99
72
|
--color-green-100: #dde2b2;
|
|
100
73
|
--color-green-150: #cdd597;
|
|
@@ -109,7 +82,6 @@
|
|
|
109
82
|
--color-green-900: #252d09;
|
|
110
83
|
--color-green-950: #1a1e0c;
|
|
111
84
|
|
|
112
|
-
/* Cyan */
|
|
113
85
|
--color-cyan-50: #ddf1e4;
|
|
114
86
|
--color-cyan-100: #bfe8d9;
|
|
115
87
|
--color-cyan-150: #a2dece;
|
|
@@ -124,7 +96,6 @@
|
|
|
124
96
|
--color-cyan-900: #122f2c;
|
|
125
97
|
--color-cyan-950: #101f1d;
|
|
126
98
|
|
|
127
|
-
/* Blue */
|
|
128
99
|
--color-blue-50: #e1eceb;
|
|
129
100
|
--color-blue-100: #c6dde8;
|
|
130
101
|
--color-blue-150: #abcfe2;
|
|
@@ -139,7 +110,6 @@
|
|
|
139
110
|
--color-blue-900: #12253b;
|
|
140
111
|
--color-blue-950: #101a24;
|
|
141
112
|
|
|
142
|
-
/* Purple */
|
|
143
113
|
--color-purple-50: #f0eaec;
|
|
144
114
|
--color-purple-100: #e2d9e9;
|
|
145
115
|
--color-purple-150: #d3cae6;
|
|
@@ -154,7 +124,6 @@
|
|
|
154
124
|
--color-purple-900: #261c39;
|
|
155
125
|
--color-purple-950: #1a1623;
|
|
156
126
|
|
|
157
|
-
/* Magenta */
|
|
158
127
|
--color-magenta-50: #fee4e5;
|
|
159
128
|
--color-magenta-100: #fccfda;
|
|
160
129
|
--color-magenta-150: #f9b9cf;
|
|
@@ -171,13 +140,9 @@
|
|
|
171
140
|
}
|
|
172
141
|
|
|
173
142
|
@theme static {
|
|
174
|
-
/*
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
* (`text-sm`, `font-semibold`, `leading-tight`, …) — the system is
|
|
178
|
-
* dense and small enough that an extra semantic layer would just be
|
|
179
|
-
* indirection. Override `--font-sans` to swap the entire UI font.
|
|
180
|
-
*/
|
|
143
|
+
/* Only the font stack is tokenized — sizes, weights, and line-heights
|
|
144
|
+
compose from Tailwind's default scale at the call site; a semantic
|
|
145
|
+
layer there would just be indirection. */
|
|
181
146
|
--font-sans:
|
|
182
147
|
"IBM Plex Sans", "IBM Plex Sans Fallback", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
|
|
183
148
|
Roboto, sans-serif;
|
|
@@ -188,71 +153,50 @@
|
|
|
188
153
|
|
|
189
154
|
@theme static {
|
|
190
155
|
/*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
* - accent-600 ↔ accent-400, accent-50 ↔ accent-950
|
|
195
|
-
*
|
|
196
|
-
* On accent buttons in dark mode the base shifts to the lighter
|
|
197
|
-
* accent-400 tone, so `content` (text on top) flips to black for
|
|
198
|
-
* legibility — the same trade-off `warning` already makes in both
|
|
199
|
-
* modes against bright yellow.
|
|
156
|
+
* Light/dark branches are Flexoki's symmetric ramp pairs (paper↔black,
|
|
157
|
+
* base-50↔base-950, accent-600↔accent-400). Dark mode fills with the
|
|
158
|
+
* lighter accent-400, so `-content` text flips to black for legibility.
|
|
200
159
|
*/
|
|
201
160
|
|
|
202
|
-
/* Surfaces */
|
|
203
161
|
--color-surface: light-dark(var(--color-paper), var(--color-black));
|
|
204
162
|
--color-surface-muted: light-dark(var(--color-base-50), var(--color-base-950));
|
|
205
163
|
--color-surface-strong: light-dark(var(--color-base-100), var(--color-base-900));
|
|
206
164
|
|
|
207
|
-
/* Text */
|
|
208
165
|
--color-text: light-dark(var(--color-black), var(--color-base-200));
|
|
209
166
|
--color-text-muted: light-dark(var(--color-base-600), var(--color-base-500));
|
|
210
167
|
|
|
211
|
-
/* Borders */
|
|
212
168
|
--color-border: light-dark(var(--color-base-150), var(--color-base-850));
|
|
213
169
|
--color-border-strong: light-dark(var(--color-base-300), var(--color-base-700));
|
|
214
170
|
|
|
215
|
-
/*
|
|
216
|
-
|
|
217
|
-
block visually carves out from regular chrome; matches `surface-muted`
|
|
218
|
-
depth in dark mode. */
|
|
171
|
+
/* <pre>-style output blocks (logs, JSON). One step darker than
|
|
172
|
+
`surface-strong` in light mode so the block carves out from chrome. */
|
|
219
173
|
--color-code-surface: light-dark(var(--color-base-150), var(--color-base-950));
|
|
220
174
|
--color-code-text: light-dark(var(--color-base-800), var(--color-base-200));
|
|
221
175
|
|
|
222
|
-
/*
|
|
223
|
-
|
|
224
|
-
retintable from a single token. */
|
|
176
|
+
/* Dimming layer behind `<dialog>` and the mobile sidebar drawer — one
|
|
177
|
+
token so both overlays match. */
|
|
225
178
|
--color-scrim: color-mix(in oklab, var(--color-black) 40%, transparent);
|
|
226
179
|
|
|
227
|
-
/* Primary
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
neutral gray wash — `bg-primary-muted` selected/active states read as a
|
|
232
|
-
quiet fill rather than a colored highlight. The interactive blue that used
|
|
233
|
-
to live here now drives `--color-link` / `--color-focus` and `info`. */
|
|
180
|
+
/* Primary is neutral ink, inverting with the mode. Unlike the colored
|
|
181
|
+
accents, `-hover` moves *toward* the surface (you can't darken past ink)
|
|
182
|
+
and `-muted` is a gray wash, so selected/active fills read quiet rather
|
|
183
|
+
than colored. */
|
|
234
184
|
--color-primary: light-dark(var(--color-black), var(--color-paper));
|
|
235
185
|
--color-primary-hover: light-dark(var(--color-base-800), var(--color-base-200));
|
|
236
186
|
--color-primary-muted: light-dark(var(--color-base-150), var(--color-base-800));
|
|
237
187
|
--color-primary-content: light-dark(var(--color-paper), var(--color-black));
|
|
238
188
|
|
|
239
|
-
/*
|
|
240
|
-
|
|
241
|
-
independently of the `info` status color, even though both start blue. */
|
|
189
|
+
/* Separate tokens so link text and focus rings can be retinted
|
|
190
|
+
independently of the `info` status color, even though all start blue. */
|
|
242
191
|
--color-link: light-dark(var(--color-blue-600), var(--color-blue-400));
|
|
243
192
|
--color-link-hover: light-dark(var(--color-blue-700), var(--color-blue-300));
|
|
244
193
|
--color-focus: light-dark(var(--color-blue-600), var(--color-blue-400));
|
|
245
194
|
|
|
246
|
-
/*
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
-muted, and -content siblings derive from the base via `color-mix`,
|
|
252
|
-
so a single override propagates. Mixing toward `--color-text` and
|
|
253
|
-
`--color-surface` (themselves `light-dark()` pairs) keeps the
|
|
254
|
-
derivations in step with light/dark mode without nesting light-dark()
|
|
255
|
-
inside color-mix(). Bright accents (e.g. yellow) may want a manual
|
|
195
|
+
/* Per-app brand signal. Defaults to neutral gray so an un-branded shell
|
|
196
|
+
reads as chrome; override at :root (or inline on .app-shell) to brand a
|
|
197
|
+
whole app. -hover/-muted derive via color-mix toward --color-text /
|
|
198
|
+
--color-surface (themselves light-dark() pairs), so one override
|
|
199
|
+
propagates and stays mode-aware. Bright accents may need a manual
|
|
256
200
|
-content override for contrast. */
|
|
257
201
|
--color-system-accent: light-dark(var(--color-base-600), var(--color-base-400));
|
|
258
202
|
--color-system-accent-hover: color-mix(
|
|
@@ -267,38 +211,30 @@
|
|
|
267
211
|
);
|
|
268
212
|
--color-system-accent-content: light-dark(var(--color-paper), var(--color-black));
|
|
269
213
|
|
|
270
|
-
/* Danger — red */
|
|
271
214
|
--color-danger: light-dark(var(--color-red-600), var(--color-red-400));
|
|
272
215
|
--color-danger-hover: light-dark(var(--color-red-700), var(--color-red-300));
|
|
273
216
|
--color-danger-muted: light-dark(var(--color-red-50), var(--color-red-950));
|
|
274
217
|
--color-danger-content: light-dark(var(--color-paper), var(--color-black));
|
|
275
218
|
|
|
276
|
-
/* Success — green */
|
|
277
219
|
--color-success: light-dark(var(--color-green-600), var(--color-green-400));
|
|
278
220
|
--color-success-hover: light-dark(var(--color-green-700), var(--color-green-300));
|
|
279
221
|
--color-success-muted: light-dark(var(--color-green-50), var(--color-green-950));
|
|
280
222
|
--color-success-content: light-dark(var(--color-paper), var(--color-black));
|
|
281
223
|
|
|
282
|
-
/* Warning
|
|
224
|
+
/* Warning stays bright in both modes; content text is dark either way */
|
|
283
225
|
--color-warning: var(--color-yellow-400);
|
|
284
226
|
--color-warning-hover: light-dark(var(--color-yellow-500), var(--color-yellow-300));
|
|
285
227
|
--color-warning-muted: light-dark(var(--color-yellow-50), var(--color-yellow-950));
|
|
286
228
|
--color-warning-content: var(--color-black);
|
|
287
229
|
|
|
288
|
-
/* Info — Flexoki blue (the calm "FYI" status color) */
|
|
289
230
|
--color-info: light-dark(var(--color-blue-600), var(--color-blue-400));
|
|
290
231
|
--color-info-hover: light-dark(var(--color-blue-700), var(--color-blue-300));
|
|
291
232
|
--color-info-muted: light-dark(var(--color-blue-50), var(--color-blue-950));
|
|
292
233
|
--color-info-content: light-dark(var(--color-paper), var(--color-black));
|
|
293
234
|
}
|
|
294
235
|
|
|
295
|
-
/*
|
|
296
|
-
|
|
297
|
-
* preference; the attribute overrides force a specific mode and also
|
|
298
|
-
* flip native form controls, scrollbars, etc. The attribute selector
|
|
299
|
-
* isn't scoped to :root so subtrees can opt into a different mode (e.g.
|
|
300
|
-
* a dark hero section on an otherwise light page).
|
|
301
|
-
*/
|
|
236
|
+
/* `light dark` follows the OS; [data-theme] forces a mode. Deliberately not
|
|
237
|
+
scoped to :root so any subtree can opt into a different mode. */
|
|
302
238
|
:root {
|
|
303
239
|
color-scheme: light dark;
|
|
304
240
|
}
|
|
@@ -309,12 +245,8 @@
|
|
|
309
245
|
color-scheme: light;
|
|
310
246
|
}
|
|
311
247
|
|
|
312
|
-
/*
|
|
313
|
-
|
|
314
|
-
* authored utilities (`dark:shadow-lg`, …) match what the tokens do.
|
|
315
|
-
* Default v4 uses prefers-color-scheme alone, which would ignore the
|
|
316
|
-
* [data-theme] override.
|
|
317
|
-
*/
|
|
248
|
+
/* Tailwind's default `dark:` is prefers-color-scheme only; realign it so
|
|
249
|
+
authored utilities follow [data-theme] like the tokens do. */
|
|
318
250
|
@custom-variant dark {
|
|
319
251
|
&:where([data-theme="dark"], [data-theme="dark"] *) {
|
|
320
252
|
@slot;
|