actual-css 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -3
- package/README.md +35 -30
- package/dist/actual.css +73 -4946
- package/dist/actual.full.css +7090 -0
- package/dist/actual.full.js +1 -0
- package/dist/actual.full.min.css +1 -0
- package/dist/actual.js +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/cascade-layer.md +34 -13
- package/docs/design-notes/column-layout.md +677 -0
- package/docs/design-notes/forced-colors.md +3 -0
- package/docs/design-notes/grid.md +612 -0
- package/docs/design-notes/naming.md +15 -0
- package/docs/design-notes/widget-primitives.md +1 -0
- package/docs/navigation.json +5 -1
- package/docs/pages/components/alert.md +16 -14
- package/docs/pages/components/aura.md +1 -1
- package/docs/pages/components/avatar.md +6 -6
- package/docs/pages/components/badge.md +7 -7
- package/docs/pages/components/button.md +16 -16
- package/docs/pages/components/card.md +13 -9
- package/docs/pages/components/chat.md +8 -8
- package/docs/pages/components/dialog.md +7 -7
- package/docs/pages/components/drawer.md +3 -3
- package/docs/pages/components/fab.md +7 -7
- package/docs/pages/components/navbar.md +9 -8
- package/docs/pages/components/pagination.md +4 -3
- package/docs/pages/components/skeleton.md +4 -4
- package/docs/pages/components/spinner.md +5 -5
- package/docs/pages/components/table.md +30 -5
- package/docs/pages/enhancements/flyout.md +13 -13
- package/docs/pages/enhancements/overview.md +1 -1
- package/docs/pages/enhancements/scrollspy.md +6 -6
- package/docs/pages/enhancements/status-bar.md +5 -1
- package/docs/pages/enhancements/tabs.md +6 -6
- package/docs/pages/enhancements/tooltip.md +1 -1
- package/docs/pages/examples/overview.md +39 -22
- package/docs/pages/forms/choice-cards.md +11 -6
- package/docs/pages/forms/controls.md +1 -1
- package/docs/pages/forms/detached-actions.md +1 -1
- package/docs/pages/forms/floating-field.md +10 -5
- package/docs/pages/forms/form-actions.md +1 -1
- package/docs/pages/forms/input-policy.md +1 -1
- package/docs/pages/forms/joined-controls.md +4 -4
- package/docs/pages/forms/labels.md +6 -6
- package/docs/pages/forms/otp.md +1 -1
- package/docs/pages/forms/overview.md +19 -19
- package/docs/pages/forms/password.md +1 -1
- package/docs/pages/forms/range.md +1 -1
- package/docs/pages/forms/states-and-sizes.md +41 -45
- package/docs/pages/forms/sticky-actions.md +3 -3
- package/docs/pages/forms/switch.md +110 -2
- package/docs/pages/forms/validation.md +9 -9
- package/docs/pages/foundations/philosophy.md +1 -1
- package/docs/pages/foundations/theming.md +17 -2
- package/docs/pages/foundations/tokens.md +22 -10
- package/docs/pages/foundations/typography.md +50 -20
- package/docs/pages/guides/bootstrap.md +11 -11
- package/docs/pages/guides/integrating-actual-css.md +186 -0
- package/docs/pages/guides/introduction.md +23 -26
- package/docs/pages/guides/modular-import.md +173 -0
- package/docs/pages/guides/progressive-enhancement.md +81 -78
- package/docs/pages/guides/tailwind.md +6 -8
- package/docs/pages/layout/app-shell.md +1 -1
- package/docs/pages/layout/center.md +1 -1
- package/docs/pages/layout/choosing.md +39 -0
- package/docs/pages/layout/column-layout.md +206 -0
- package/docs/pages/layout/frame.md +6 -1
- package/docs/pages/layout/grid.md +100 -102
- package/docs/pages/layout/list.md +1 -1
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +15 -2
- package/docs/pages/layout/scroll-snap.md +2 -2
- package/docs/pages/layout/scroll-target.md +45 -0
- package/docs/pages/layout/sidebar-layout.md +20 -19
- package/docs/pages/layout/stack.md +53 -1
- package/docs/pages/layout/switcher.md +10 -26
- package/docs/pages/layout/topbar.md +2 -2
- package/docs/pages/patterns/actions.md +1 -1
- package/docs/pages/patterns/code-block.md +1 -1
- package/docs/pages/patterns/exclusive-accordion.md +1 -1
- package/docs/pages/patterns/hierarchical-nav.md +1 -1
- package/docs/pages/patterns/icon-input.md +1 -1
- package/docs/pages/patterns/intent-nesting.md +1 -1
- package/docs/pages/patterns/navigation-list.md +1 -1
- package/docs/pages/patterns/overview.md +1 -1
- package/docs/pages/patterns/structured-lists.md +1 -1
- package/docs/pages/utilities/accessibility.md +3 -3
- package/docs/pages/utilities/flex.md +15 -15
- package/docs/pages/utilities/links.md +4 -4
- package/docs/pages/utilities/list.md +8 -8
- package/docs/pages/utilities/overflow.md +8 -8
- package/docs/pages/utilities/overview.md +1 -1
- package/docs/pages/utilities/shape.md +3 -3
- package/docs/pages/utilities/sizing-wrapping.md +23 -16
- package/docs/pages/utilities/spacing.md +20 -20
- package/docs/pages/utilities/text.md +10 -10
- package/llms.txt +46 -4
- package/package.json +42 -13
- package/scripts/reserved-classes.json +261 -0
- package/src/cli/actual-css.js +133 -0
- package/src/css/actual.css +1 -31
- package/src/css/actual.full.css +11 -2
- package/src/css/components/alert.css +17 -4
- package/src/css/components/badge.css +18 -6
- package/src/css/components/breadcrumb.css +1 -1
- package/src/css/components/button.css +19 -1
- package/src/css/components/card.css +27 -2
- package/src/css/components/drawer.css +27 -2
- package/src/css/components/flyout.css +5 -0
- package/src/css/components/index.css +32 -27
- package/src/css/components/join.css +8 -1
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +11 -1
- package/src/css/components/meter.css +4 -1
- package/src/css/components/modal.css +5 -0
- package/src/css/components/pagination.css +11 -0
- package/src/css/components/spinner.css +5 -0
- package/src/css/components/status-bar.css +5 -0
- package/src/css/components/surface.css +5 -0
- package/src/css/components/table.css +6 -0
- package/src/css/components/tooltip.css +5 -0
- package/src/css/core/index.css +9 -0
- package/src/css/core/print.css +18 -0
- package/src/css/{theme.css → core/theme.css} +20 -10
- package/src/css/{tokens.css → core/tokens.css} +15 -2
- package/src/css/{variants.css → core/variants.css} +3 -2
- package/src/css/effects/index.css +2 -0
- package/src/css/forms/base.css +8 -0
- package/src/css/forms/choice-card.css +5 -4
- package/src/css/forms/choice.css +49 -37
- package/src/css/forms/control.css +4 -1
- package/src/css/forms/custom-select.css +2 -0
- package/src/css/{optional → forms}/floating-field.css +25 -7
- package/src/css/forms/index.css +10 -13
- package/src/css/forms/native.css +15 -2
- package/src/css/{optional → forms}/otp.css +20 -16
- package/src/css/forms/switch.css +31 -29
- package/src/css/layout/app-shell.css +6 -0
- package/src/css/layout/center.css +13 -0
- package/src/css/layout/cluster.css +21 -0
- package/src/css/layout/column-layout.css +144 -0
- package/src/css/layout/container-query.css +13 -0
- package/src/css/layout/frame.css +19 -0
- package/src/css/layout/grid.css +141 -0
- package/src/css/layout/index.css +42 -0
- package/src/css/layout/measure.css +9 -0
- package/src/css/layout/media.css +10 -0
- package/src/css/layout/scroll-target.css +15 -0
- package/src/css/layout/scroller.css +41 -0
- package/src/css/layout/sidebar-layout.css +31 -0
- package/src/css/layout/stack.css +21 -0
- package/src/css/layout/switcher.css +23 -0
- package/src/css/{optional/layout-extra.css → layout/topbar.css} +0 -20
- package/src/css/typography/index.css +5 -0
- package/src/css/typography/lead.css +7 -0
- package/src/css/{components → typography}/overline.css +2 -2
- package/src/css/{prose.css → typography/prose.css} +53 -38
- package/src/css/{utilities.css → utilities/base.css} +2 -0
- package/src/css/utilities/index.css +3 -0
- package/src/js/escape.js +36 -0
- package/src/js/flyout.js +22 -12
- package/src/js/full.js +26 -0
- package/src/js/index.js +5 -21
- package/src/js/surface.js +1 -31
- package/src/js/tooltip.js +46 -18
- package/src/js/validation.js +1 -1
- package/src/tooling/css-bundle.js +308 -0
- package/dist/actual-themes.min.css +0 -1
- package/dist/optional.css +0 -1048
- package/dist/optional.min.css +0 -1
- package/docs/pages/guides/optional-components.md +0 -33
- package/src/css/grid.css +0 -109
- package/src/css/layout.css +0 -123
- package/src/css/optional/index.css +0 -10
- package/src/css/optional/scroller.css +0 -63
- package/src/css/print.css +0 -47
- package/src/css/themes/corporate.css +0 -60
- package/src/css/themes/cyberpunk.css +0 -60
- package/src/css/themes/dim.css +0 -33
- package/src/css/themes/edge.css +0 -117
- package/src/css/themes/forest.css +0 -65
- package/src/css/themes/gradient.css +0 -97
- package/src/css/themes/index.css +0 -47
- package/src/css/themes/indigo.css +0 -33
- package/src/css/themes/lavender.css +0 -66
- package/src/css/themes/mono.css +0 -60
- package/src/css/themes/neon.css +0 -66
- package/src/css/themes/ocean.css +0 -60
- package/src/css/themes/petrol.css +0 -64
- package/src/css/themes/spruce.css +0 -64
- package/src/css/themes/square.css +0 -65
- package/src/css/themes/sunset.css +0 -66
- /package/src/css/{optional → components}/chat.css +0 -0
- /package/src/css/{optional → components}/fab.css +0 -0
- /package/src/css/{base.css → core/base.css} +0 -0
- /package/src/css/{focus.css → core/focus.css} +0 -0
- /package/src/css/{intents.css → core/intents.css} +0 -0
- /package/src/css/{reset.css → core/reset.css} +0 -0
- /package/src/css/{optional → effects}/aura.css +0 -0
- /package/src/css/{optional → layout}/scroll-snap.css +0 -0
- /package/src/css/{optional/typography-fluid.css → typography/fluid.css} +0 -0
- /package/src/css/{optional/utilities-extra.css → utilities/extra.css} +0 -0
package/src/js/flyout.js
CHANGED
|
@@ -144,10 +144,29 @@ function connectTrigger(trigger) {
|
|
|
144
144
|
trigger.addEventListener("keydown", onTriggerKeydown, { signal: controller.signal });
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
function
|
|
148
|
-
|
|
147
|
+
function releasePanelReference(trigger, state) {
|
|
148
|
+
state.releaseMenu?.();
|
|
149
|
+
state.releaseMenu = null;
|
|
150
|
+
|
|
151
|
+
const panel = state.panel;
|
|
152
|
+
state.panel = null;
|
|
153
|
+
if (!panel) return;
|
|
154
|
+
|
|
155
|
+
const panelEntry = panelRefs.get(panel);
|
|
156
|
+
if (!panelEntry) return;
|
|
157
|
+
|
|
158
|
+
panelEntry.triggers.delete(trigger);
|
|
159
|
+
if (panelEntry.triggers.size === 0) {
|
|
160
|
+
panelEntry.release();
|
|
161
|
+
panelRefs.delete(panel);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
149
164
|
|
|
165
|
+
function resolvePanel(trigger, state) {
|
|
150
166
|
const panel = panelFor(trigger);
|
|
167
|
+
if (state.panel === panel && panel?.isConnected) return panel;
|
|
168
|
+
|
|
169
|
+
releasePanelReference(trigger, state);
|
|
151
170
|
if (!panel) return null;
|
|
152
171
|
|
|
153
172
|
let panelEntry = panelRefs.get(panel);
|
|
@@ -174,21 +193,12 @@ function resolvePanel(trigger, state) {
|
|
|
174
193
|
function disconnectTrigger(trigger) {
|
|
175
194
|
const state = triggerMap.get(trigger);
|
|
176
195
|
if (!state) return;
|
|
177
|
-
state.releaseMenu?.();
|
|
178
196
|
state.controller.abort();
|
|
179
197
|
if (state.panel?.isConnected && isSurfaceOpen(state.panel)) {
|
|
180
198
|
closeSurface(state.panel, { restoreFocus: false });
|
|
181
199
|
}
|
|
200
|
+
releasePanelReference(trigger, state);
|
|
182
201
|
triggerMap.delete(trigger);
|
|
183
|
-
|
|
184
|
-
const panelEntry = state.panel ? panelRefs.get(state.panel) : undefined;
|
|
185
|
-
if (panelEntry) {
|
|
186
|
-
panelEntry.triggers.delete(trigger);
|
|
187
|
-
if (panelEntry.triggers.size === 0) {
|
|
188
|
-
panelEntry.release();
|
|
189
|
-
panelRefs.delete(state.panel);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
202
|
}
|
|
193
203
|
|
|
194
204
|
registerEnhancement("flyout", (trigger) => {
|
package/src/js/full.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Actual CSS - JavaScript runtime, full bundle entry.
|
|
3
|
+
*
|
|
4
|
+
* Each module self-registers via observer: importing this bundle enables
|
|
5
|
+
* common behaviors. No DOMContentLoaded ceremony, no init calls.
|
|
6
|
+
* Injected content wires automatically; removal cleans up automatically.
|
|
7
|
+
*
|
|
8
|
+
* A plain `<script src="actual.full.js"></script>` (no bundler, no import) still
|
|
9
|
+
* gets the full runtime, including declarative triggers like status's
|
|
10
|
+
* `command="--status"` and the `actual:status` event — no global needed to
|
|
11
|
+
* drive them from other inline scripts either.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import "./flyout.js";
|
|
15
|
+
import "./context-menu.js";
|
|
16
|
+
import "./dialog.js";
|
|
17
|
+
import "./dismiss.js";
|
|
18
|
+
import "./tab.js";
|
|
19
|
+
import "./tooltip.js";
|
|
20
|
+
import "./scrollspy.js";
|
|
21
|
+
import "./filter.js";
|
|
22
|
+
import "./mask.js";
|
|
23
|
+
import "./password.js";
|
|
24
|
+
import "./validation.js";
|
|
25
|
+
import "./status.js";
|
|
26
|
+
import "./index.js";
|
package/src/js/index.js
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Actual CSS - JavaScript runtime.
|
|
2
|
+
* Actual CSS - JavaScript runtime, core entry.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* A plain `<script src="actual.js"></script>` (no bundler, no import) still
|
|
9
|
-
* gets the full runtime, including declarative triggers like status's
|
|
10
|
-
* `command="--status"` and the `actual:status` event — no global needed to
|
|
11
|
-
* drive them from other inline scripts either.
|
|
4
|
+
* This entry only starts the enhancement manifest loader. Built-in behaviors
|
|
5
|
+
* (dialogs, menus, tabs, validation, ...) ship in the full bundle entry
|
|
6
|
+
* (src/js/full.js). Use this module for pages that only need progressive
|
|
7
|
+
* enhancement via enhancement manifests.
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
|
-
import "./flyout.js";
|
|
15
|
-
import "./context-menu.js";
|
|
16
|
-
import "./dialog.js";
|
|
17
|
-
import "./dismiss.js";
|
|
18
|
-
import "./tab.js";
|
|
19
|
-
import "./tooltip.js";
|
|
20
|
-
import "./scrollspy.js";
|
|
21
|
-
import "./filter.js";
|
|
22
|
-
import "./mask.js";
|
|
23
|
-
import "./password.js";
|
|
24
|
-
import "./validation.js";
|
|
25
|
-
import "./status.js";
|
|
26
10
|
import { watchEnhancementManifests } from "./enhancement-loader.js";
|
|
27
11
|
|
|
28
12
|
watchEnhancementManifests();
|
package/src/js/surface.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import enhance from "./enhance.js";
|
|
2
|
+
import { registerEscapeDismissal } from "./escape.js";
|
|
2
3
|
import { EVENTS } from "./events.js";
|
|
3
4
|
import { autoUpdate, reposition, repositionAt } from "./floating.js";
|
|
4
5
|
|
|
@@ -418,37 +419,6 @@ function ensureDocumentClick(menu) {
|
|
|
418
419
|
doc.addEventListener("click", onDocumentClick);
|
|
419
420
|
}
|
|
420
421
|
|
|
421
|
-
const dismissableStacks = new WeakMap();
|
|
422
|
-
|
|
423
|
-
export function registerEscapeDismissal(element, dismiss) {
|
|
424
|
-
const doc = element.ownerDocument;
|
|
425
|
-
let stack = dismissableStacks.get(doc);
|
|
426
|
-
if (!stack) {
|
|
427
|
-
stack = [];
|
|
428
|
-
dismissableStacks.set(doc, stack);
|
|
429
|
-
doc.addEventListener("keydown", onDocumentEscape);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const entry = { element, dismiss };
|
|
433
|
-
stack.push(entry);
|
|
434
|
-
|
|
435
|
-
return () => {
|
|
436
|
-
const index = stack.indexOf(entry);
|
|
437
|
-
if (index >= 0) stack.splice(index, 1);
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
function onDocumentEscape(event) {
|
|
442
|
-
if (event.key !== "Escape" || event.ctrlKey || event.altKey || event.shiftKey) return;
|
|
443
|
-
|
|
444
|
-
const stack = dismissableStacks.get(event.currentTarget);
|
|
445
|
-
const entry = stack.at(-1);
|
|
446
|
-
if (!entry) return;
|
|
447
|
-
|
|
448
|
-
event.preventDefault();
|
|
449
|
-
entry.dismiss({ restoreFocus: true });
|
|
450
|
-
}
|
|
451
|
-
|
|
452
422
|
export function getSurfaceAutoClose(menu) {
|
|
453
423
|
return surfaceMap.get(menu)?.autoClose ?? "outside";
|
|
454
424
|
}
|
package/src/js/tooltip.js
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
30
|
import enhance from "./enhance.js";
|
|
31
|
+
import { registerEscapeDismissal } from "./escape.js";
|
|
31
32
|
import { autoUpdate, reposition } from "./floating.js";
|
|
32
33
|
import { CLASSES } from "./selectors.js";
|
|
33
34
|
|
|
@@ -40,6 +41,8 @@ const HIDE_DELAY_MS = 100;
|
|
|
40
41
|
* @property {Element | null} activeRef Trigger that last showed this tip.
|
|
41
42
|
* @property {AbortController} controller Tip-level event listener cleanup.
|
|
42
43
|
* @property {(() => void) | null} stopTracking Floating-position cleanup while visible.
|
|
44
|
+
* @property {(() => void) | null} unregisterEscape Escape-stack cleanup while visible and dismissable.
|
|
45
|
+
* @property {Element | null} escapeRef Trigger represented by the current Escape-stack entry.
|
|
43
46
|
* @property {boolean} generated True when the tip was created from data-tooltip text.
|
|
44
47
|
* @property {{ parent: Node, next: ChildNode | null } | null} mount Original DOM position for explicit tips moved into a dialog/body root.
|
|
45
48
|
* @property {ReturnType<typeof setTimeout> | null} timer Pending delayed show.
|
|
@@ -140,15 +143,27 @@ function repositionTip(ref, tip) {
|
|
|
140
143
|
});
|
|
141
144
|
}
|
|
142
145
|
|
|
146
|
+
function updateTrackedTip(tip, state) {
|
|
147
|
+
const ref = state.activeRef;
|
|
148
|
+
if (!ref) return;
|
|
149
|
+
|
|
150
|
+
const alwaysVisible = isAlwaysVisible(ref);
|
|
151
|
+
// Reveal before measuring: an always-visible tooltip may currently be
|
|
152
|
+
// hidden because its trigger was outside the positioning boundary.
|
|
153
|
+
if (alwaysVisible) tip.hidden = false;
|
|
154
|
+
if (tip.hidden || repositionTip(ref, tip)) {
|
|
155
|
+
syncEscapeDismissal(tip, state);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (alwaysVisible) tip.hidden = true;
|
|
160
|
+
else hideTip(tip, true);
|
|
161
|
+
}
|
|
162
|
+
|
|
143
163
|
function startTracking(tip, state) {
|
|
144
164
|
if (state.stopTracking) return;
|
|
145
165
|
|
|
146
|
-
state.stopTracking = autoUpdate(tip, () =>
|
|
147
|
-
if (isAlwaysVisible(state.activeRef)) tip.hidden = false;
|
|
148
|
-
if (state.activeRef && !tip.hidden && !repositionTip(state.activeRef, tip)) {
|
|
149
|
-
hideTip(tip, true);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
166
|
+
state.stopTracking = autoUpdate(tip, () => updateTrackedTip(tip, state));
|
|
152
167
|
}
|
|
153
168
|
|
|
154
169
|
function stopTracking(state) {
|
|
@@ -156,6 +171,22 @@ function stopTracking(state) {
|
|
|
156
171
|
if (state) state.stopTracking = null;
|
|
157
172
|
}
|
|
158
173
|
|
|
174
|
+
function syncEscapeDismissal(tip, state) {
|
|
175
|
+
const ref = state.activeRef;
|
|
176
|
+
const dismissable = !tip.hidden && !isAlwaysVisible(ref);
|
|
177
|
+
// Position tracking calls this after every successful update. Preserve the
|
|
178
|
+
// current entry so a scroll/resize tick cannot reorder the LIFO stack.
|
|
179
|
+
if (dismissable && state.unregisterEscape && state.escapeRef === ref) return;
|
|
180
|
+
|
|
181
|
+
state.unregisterEscape?.();
|
|
182
|
+
state.unregisterEscape = null;
|
|
183
|
+
state.escapeRef = null;
|
|
184
|
+
if (!dismissable) return;
|
|
185
|
+
|
|
186
|
+
state.unregisterEscape = registerEscapeDismissal(tip, () => hideTip(tip, true));
|
|
187
|
+
state.escapeRef = ref;
|
|
188
|
+
}
|
|
189
|
+
|
|
159
190
|
function hideTip(tip, force = false) {
|
|
160
191
|
const state = tipStates.get(tip);
|
|
161
192
|
if (!force && isAlwaysVisible(state?.activeRef)) return;
|
|
@@ -168,6 +199,11 @@ function hideTip(tip, force = false) {
|
|
|
168
199
|
state.hideTimer = null;
|
|
169
200
|
}
|
|
170
201
|
tip.hidden = true;
|
|
202
|
+
state?.unregisterEscape?.();
|
|
203
|
+
if (state) {
|
|
204
|
+
state.unregisterEscape = null;
|
|
205
|
+
state.escapeRef = null;
|
|
206
|
+
}
|
|
171
207
|
stopTracking(state);
|
|
172
208
|
}
|
|
173
209
|
|
|
@@ -203,6 +239,8 @@ function wireTip(tip, options = {}) {
|
|
|
203
239
|
activeRef: null,
|
|
204
240
|
controller,
|
|
205
241
|
stopTracking: null,
|
|
242
|
+
unregisterEscape: null,
|
|
243
|
+
escapeRef: null,
|
|
206
244
|
generated: options.generated === true,
|
|
207
245
|
mount: options.mount || null,
|
|
208
246
|
timer: null,
|
|
@@ -229,17 +267,6 @@ function wireTip(tip, options = {}) {
|
|
|
229
267
|
{ signal: controller.signal },
|
|
230
268
|
);
|
|
231
269
|
|
|
232
|
-
tip.ownerDocument.addEventListener(
|
|
233
|
-
"keydown",
|
|
234
|
-
(event) => {
|
|
235
|
-
if (event.key !== "Escape" || event.ctrlKey || event.altKey || event.shiftKey) return;
|
|
236
|
-
if (tip.hidden) return;
|
|
237
|
-
event.preventDefault();
|
|
238
|
-
hideTip(tip);
|
|
239
|
-
},
|
|
240
|
-
{ signal: controller.signal },
|
|
241
|
-
);
|
|
242
|
-
|
|
243
270
|
tipStates.set(tip, state);
|
|
244
271
|
return state;
|
|
245
272
|
}
|
|
@@ -340,13 +367,14 @@ function show(tip, ref, immediate = false) {
|
|
|
340
367
|
if (!state) return;
|
|
341
368
|
|
|
342
369
|
state.activeRef = ref;
|
|
370
|
+
syncEscapeDismissal(tip, state);
|
|
343
371
|
clearHide(tip);
|
|
344
372
|
if (state.timer) clearTimeout(state.timer);
|
|
345
373
|
const reveal = () => {
|
|
346
374
|
state.timer = null;
|
|
347
375
|
tip.hidden = false;
|
|
348
|
-
repositionTip(ref, tip);
|
|
349
376
|
startTracking(tip, state);
|
|
377
|
+
updateTrackedTip(tip, state);
|
|
350
378
|
};
|
|
351
379
|
|
|
352
380
|
if (immediate) reveal();
|
package/src/js/validation.js
CHANGED
|
@@ -391,7 +391,7 @@ export class FormValidator {
|
|
|
391
391
|
static setErrors(form, errors) {
|
|
392
392
|
if (!isFormElement(form)) return;
|
|
393
393
|
for (const [name, message] of Object.entries(errors)) {
|
|
394
|
-
const found = form.elements
|
|
394
|
+
const found = form.elements.namedItem(name);
|
|
395
395
|
if (!found) continue;
|
|
396
396
|
if (found instanceof Element) {
|
|
397
397
|
FormValidator.setFieldError(found, message);
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Shared CSS bundling helpers: inline @import chains, strip comments, minify.
|
|
3
|
+
* Used by build-dist.js (package artifacts), build-themes.js (demo asset),
|
|
4
|
+
* and the public CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync } from "node:fs";
|
|
7
|
+
import { readFile } from "node:fs/promises";
|
|
8
|
+
import { createRequire } from "node:module";
|
|
9
|
+
import { dirname, resolve } from "node:path";
|
|
10
|
+
import { pathToFileURL } from "node:url";
|
|
11
|
+
|
|
12
|
+
const IMPORT_PREFIX_RE = /^\s*@import\b/;
|
|
13
|
+
// Two or more characters before the colon: a Windows drive letter (D:/app.css)
|
|
14
|
+
// is a local path, not a URL scheme.
|
|
15
|
+
const EXTERNAL_SPECIFIER_RE = /^(?:[a-z][a-z0-9+.-]+:|\/\/|\/)/i;
|
|
16
|
+
const CHARSET_RE = /^\s*@charset\s+["'][^"']*["']\s*;[^\n]*\n?/;
|
|
17
|
+
const LAYER_TRAILER_RE = /^layer(?:\(\s*([A-Za-z_-][\w-]*(?:\.[A-Za-z_-][\w-]*)*)?\s*\))?$/;
|
|
18
|
+
const RESOLVER_STUB = "__actual_css_resolve__.js";
|
|
19
|
+
|
|
20
|
+
function skipWhitespace(source, index) {
|
|
21
|
+
let next = index;
|
|
22
|
+
|
|
23
|
+
while (next < source.length && /\s/.test(source[next])) {
|
|
24
|
+
next += 1;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return next;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function readQuoted(source, index) {
|
|
31
|
+
const quote = source[index];
|
|
32
|
+
|
|
33
|
+
if (quote !== '"' && quote !== "'") return null;
|
|
34
|
+
|
|
35
|
+
let value = "";
|
|
36
|
+
|
|
37
|
+
for (let cursor = index + 1; cursor < source.length; cursor += 1) {
|
|
38
|
+
const char = source[cursor];
|
|
39
|
+
|
|
40
|
+
if (char === "\\") {
|
|
41
|
+
const next = source[cursor + 1];
|
|
42
|
+
if (next === undefined) return null;
|
|
43
|
+
value += char;
|
|
44
|
+
value += next;
|
|
45
|
+
cursor += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (char === quote) {
|
|
50
|
+
return { value, index: cursor + 1 };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
value += char;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseImportLine(line) {
|
|
60
|
+
let index = skipWhitespace(line, 0);
|
|
61
|
+
|
|
62
|
+
if (!line.startsWith("@import", index)) return null;
|
|
63
|
+
|
|
64
|
+
index += "@import".length;
|
|
65
|
+
index = skipWhitespace(line, index);
|
|
66
|
+
|
|
67
|
+
let parsed = null;
|
|
68
|
+
|
|
69
|
+
if (line.startsWith("url(", index)) {
|
|
70
|
+
index += 4;
|
|
71
|
+
index = skipWhitespace(line, index);
|
|
72
|
+
|
|
73
|
+
if (line[index] === '"' || line[index] === "'") {
|
|
74
|
+
parsed = readQuoted(line, index);
|
|
75
|
+
if (!parsed) return null;
|
|
76
|
+
index = parsed.index;
|
|
77
|
+
} else {
|
|
78
|
+
const end = line.indexOf(")", index);
|
|
79
|
+
if (end === -1) return null;
|
|
80
|
+
parsed = { value: line.slice(index, end).trim(), index: end };
|
|
81
|
+
index = end;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
index = skipWhitespace(line, index);
|
|
85
|
+
if (line[index] !== ")") return null;
|
|
86
|
+
index += 1;
|
|
87
|
+
} else {
|
|
88
|
+
parsed = readQuoted(line, index);
|
|
89
|
+
if (!parsed) return null;
|
|
90
|
+
index = parsed.index;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const rest = line.slice(index);
|
|
94
|
+
|
|
95
|
+
// A comment opened on the import line and closed further down cannot be
|
|
96
|
+
// reasoned about line by line: treat the whole statement as unsupported.
|
|
97
|
+
if (hasUnterminatedComment(rest)) return null;
|
|
98
|
+
|
|
99
|
+
const trailer = stripComments(rest).replace(/;\s*$/, "").trim();
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
specifier: parsed.value,
|
|
103
|
+
trailer,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function hasUnterminatedComment(text) {
|
|
108
|
+
const open = text.lastIndexOf("/*");
|
|
109
|
+
return open !== -1 && text.indexOf("*/", open + 2) === -1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function isExternalImportSpecifier(specifier) {
|
|
113
|
+
return EXTERNAL_SPECIFIER_RE.test(specifier);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function resolveImportTarget(file, specifier) {
|
|
117
|
+
const dir = dirname(file);
|
|
118
|
+
|
|
119
|
+
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
120
|
+
return resolve(dir, specifier);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Plain CSS reads "app.css" as a relative URL, so a neighbouring file wins
|
|
124
|
+
// over package resolution; everything else goes through the exports map.
|
|
125
|
+
const local = resolve(dir, specifier);
|
|
126
|
+
if (existsSync(local)) return local;
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const require = createRequire(pathToFileURL(resolve(dir, RESOLVER_STUB)));
|
|
130
|
+
return require.resolve(specifier);
|
|
131
|
+
} catch {
|
|
132
|
+
throw new Error(`Cannot resolve CSS @import "${specifier}" from ${file}`);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function preservedImportStatement(line) {
|
|
137
|
+
const statement = line.trim();
|
|
138
|
+
return statement.endsWith(";") ? statement : `${statement};`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// `layer`, `layer()` and `layer(name)` are the only modifiers this bundler
|
|
142
|
+
// understands: dropping the @import means re-stating the layer, which an
|
|
143
|
+
// @layer block does exactly. Conditional modifiers stay out of scope.
|
|
144
|
+
function parseLayerTrailer(trailer) {
|
|
145
|
+
const match = trailer.match(LAYER_TRAILER_RE);
|
|
146
|
+
return match ? { name: match[1] ?? "" } : null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function wrapInLayer(css, name) {
|
|
150
|
+
const body = css
|
|
151
|
+
.split("\n")
|
|
152
|
+
.map((line) => (line.trim() === "" ? "" : ` ${line}`))
|
|
153
|
+
.join("\n")
|
|
154
|
+
.replace(/\n+$/, "");
|
|
155
|
+
const head = name ? `@layer ${name} {` : "@layer {";
|
|
156
|
+
|
|
157
|
+
return `${head}\n${body}\n}\n`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function inlineFile(path, stack, preserved, layered) {
|
|
161
|
+
if (stack.includes(path)) {
|
|
162
|
+
const chain = [...stack, path].map((item) => item.replace(/.*[/\\]/, ""));
|
|
163
|
+
throw new Error(`Circular CSS import: ${chain.join(" -> ")}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const css = await readFile(path, "utf8");
|
|
167
|
+
const nextStack = [...stack, path];
|
|
168
|
+
const chunks = [];
|
|
169
|
+
|
|
170
|
+
for (const line of css.split(/\r?\n/)) {
|
|
171
|
+
const parsed = parseImportLine(line);
|
|
172
|
+
|
|
173
|
+
if (!parsed) {
|
|
174
|
+
if (IMPORT_PREFIX_RE.test(line)) {
|
|
175
|
+
throw new Error(`Unsupported CSS @import syntax in ${path}: ${line.trim()}`);
|
|
176
|
+
}
|
|
177
|
+
chunks.push(line);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (isExternalImportSpecifier(parsed.specifier)) {
|
|
182
|
+
// Hoisting is what keeps a surviving @import valid, but hoisting it out
|
|
183
|
+
// of a layer would silently move its rules to another layer.
|
|
184
|
+
if (layered) {
|
|
185
|
+
throw new Error(
|
|
186
|
+
`Remote CSS @import inside a layered import cannot be hoisted in ${path}: ${line.trim()}`,
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const statement = preservedImportStatement(line);
|
|
191
|
+
if (!preserved.includes(statement)) preserved.push(statement);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const layer = parsed.trailer ? parseLayerTrailer(parsed.trailer) : null;
|
|
196
|
+
|
|
197
|
+
if (parsed.trailer && !layer) {
|
|
198
|
+
throw new Error(`Unsupported CSS @import modifiers in ${path}: ${line.trim()}`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const target = resolveImportTarget(path, parsed.specifier);
|
|
202
|
+
const inlined = await inlineFile(target, nextStack, preserved, layered || layer !== null);
|
|
203
|
+
chunks.push(layer ? wrapInLayer(inlined, layer.name) : inlined);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return `${chunks.join("\n").trim()}\n`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export async function inlineImports(file) {
|
|
210
|
+
const preserved = [];
|
|
211
|
+
const body = await inlineFile(resolve(file), [], preserved, false);
|
|
212
|
+
|
|
213
|
+
if (preserved.length === 0) return body;
|
|
214
|
+
|
|
215
|
+
// An @import that survives inlining must still precede every rule, so the
|
|
216
|
+
// preserved statements move to the top, after @charset if the entry has one.
|
|
217
|
+
const charset = body.match(CHARSET_RE);
|
|
218
|
+
const head = charset ? `${charset[0].trimEnd()}\n` : "";
|
|
219
|
+
const rest = (charset ? body.slice(charset[0].length) : body).replace(/^\n+/, "");
|
|
220
|
+
|
|
221
|
+
return `${head}${preserved.join("\n")}\n\n${rest}`;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function stripComments(css) {
|
|
225
|
+
let out = "";
|
|
226
|
+
let quote = "";
|
|
227
|
+
|
|
228
|
+
for (let i = 0; i < css.length; i += 1) {
|
|
229
|
+
const char = css[i];
|
|
230
|
+
const next = css[i + 1];
|
|
231
|
+
|
|
232
|
+
if (quote) {
|
|
233
|
+
out += char;
|
|
234
|
+
if (char === "\\") {
|
|
235
|
+
out += next ?? "";
|
|
236
|
+
i += 1;
|
|
237
|
+
} else if (char === quote) {
|
|
238
|
+
quote = "";
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (char === '"' || char === "'") {
|
|
244
|
+
quote = char;
|
|
245
|
+
out += char;
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (char === "/" && next === "*") {
|
|
250
|
+
i += 2;
|
|
251
|
+
while (i < css.length && !(css[i] === "*" && css[i + 1] === "/")) i += 1;
|
|
252
|
+
i += 1;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
out += char;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function minifyCss(css) {
|
|
263
|
+
const source = stripComments(css).trim();
|
|
264
|
+
let out = "";
|
|
265
|
+
let quote = "";
|
|
266
|
+
let previousWasSpace = false;
|
|
267
|
+
|
|
268
|
+
for (let i = 0; i < source.length; i += 1) {
|
|
269
|
+
const char = source[i];
|
|
270
|
+
const next = source[i + 1];
|
|
271
|
+
|
|
272
|
+
if (quote) {
|
|
273
|
+
out += char;
|
|
274
|
+
if (char === "\\") {
|
|
275
|
+
out += next ?? "";
|
|
276
|
+
i += 1;
|
|
277
|
+
} else if (char === quote) {
|
|
278
|
+
quote = "";
|
|
279
|
+
}
|
|
280
|
+
previousWasSpace = false;
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (/\s/.test(char)) {
|
|
285
|
+
if (!previousWasSpace) out += " ";
|
|
286
|
+
previousWasSpace = true;
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
out += char;
|
|
291
|
+
previousWasSpace = false;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return `${out.trim()}\n`;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function bundledCssIssues(css) {
|
|
298
|
+
const issues = [];
|
|
299
|
+
|
|
300
|
+
if (css.includes("@import")) issues.push("contains unresolved @import");
|
|
301
|
+
if (css.includes("--lightningcss")) issues.push("contains --lightningcss-* variables");
|
|
302
|
+
if (/color-mix\(in srgb/.test(css)) issues.push("contains color-mix(in srgb, ...)");
|
|
303
|
+
if (/@media[^{]*\(\s*width\s*[<>]=/.test(css)) {
|
|
304
|
+
issues.push("contains transpiled media query range syntax");
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return issues;
|
|
308
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
[data-theme="indigo"] { color-scheme: dark; --primary: hsl(220 90% 66%); --primary-fg: hsl(222 30% 8%); --secondary: hsl(270 65% 70%); --secondary-fg: hsl(270 30% 10%); --success: hsl(145 55% 54%); --success-fg: hsl(145 40% 8%); --warning: hsl(38 92% 62%); --warning-fg: hsl(35 35% 10%); --danger: hsl(0 75% 66%); --danger-fg: hsl(0 35% 10%); --neutral: hsl(220 10% 72%); --neutral-fg: hsl(222 24% 8%); --surface: hsl(222 24% 8%); --surface-raised: hsl(222 22% 11%); --surface-subtle: hsl(222 18% 15%); --surface-solid: hsl(0 0% 96%); --text: hsl(0 0% 96%); --text-muted: hsl(220 10% 68%); --text-subtle: hsl(220 8% 55%); --border: hsl(222 14% 24%); --focus: var(--primary); --focus-ring: hsl(220 90% 66% / 0.28); --hover-overlay: hsl(0 0% 100% / 0.06); } [data-theme="dim"] { color-scheme: dark; --primary: hsl(210 92% 70%); --primary-fg: hsl(218 28% 10%); --secondary: hsl(270 70% 74%); --secondary-fg: hsl(270 30% 10%); --success: hsl(150 56% 58%); --success-fg: hsl(150 38% 9%); --warning: hsl(40 92% 64%); --warning-fg: hsl(35 35% 10%); --danger: hsl(0 74% 68%); --danger-fg: hsl(0 35% 10%); --neutral: hsl(220 10% 72%); --neutral-fg: hsl(220 24% 10%); --surface: hsl(220 20% 13%); --surface-raised: hsl(220 18% 16%); --surface-subtle: hsl(220 16% 20%); --surface-solid: hsl(0 0% 96%); --text: hsl(220 18% 94%); --text-muted: hsl(220 10% 70%); --text-subtle: hsl(220 8% 58%); --border: hsl(220 12% 28%); --focus: var(--primary); --focus-ring: hsl(210 92% 70% / 0.28); --hover-overlay: hsl(0 0% 100% / 0.06); } [data-theme="corporate"] { color-scheme: light dark; --primary: hsl(214 82% 44%); --primary-fg: white; --secondary: hsl(250 45% 48%); --secondary-fg: white; --success: hsl(152 62% 32%); --success-fg: white; --warning: hsl(40 94% 48%); --warning-fg: hsl(35 30% 12%); --danger: hsl(355 70% 50%); --danger-fg: white; --neutral: hsl(220 12% 42%); --neutral-fg: white; --surface: hsl(0 0% 100%); --surface-raised: hsl(214 30% 98%); --surface-subtle: hsl(214 35% 95%); --surface-solid: hsl(220 24% 12%); --text: hsl(220 24% 12%); --text-muted: hsl(220 10% 42%); --text-subtle: hsl(220 8% 55%); --border: hsl(220 16% 86%); --focus: var(--primary); --focus-ring: hsl(214 82% 44% / 0.22); } @supports (color: light-dark(red, blue)) { [data-theme="corporate"] { --primary: light-dark(hsl(214 82% 44%), hsl(214 75% 80%)); --primary-fg: light-dark(white, hsl(214 30% 12%)); --secondary: light-dark(hsl(250 45% 48%), hsl(250 53% 80%)); --secondary-fg: light-dark(white, hsl(250 30% 12%)); --success: light-dark(hsl(152 62% 32%), hsl(152 70% 80%)); --success-fg: light-dark(white, hsl(152 30% 12%)); --warning: light-dark(hsl(40 94% 48%), hsl(40 75% 80%)); --warning-fg: light-dark(hsl(35 30% 12%), hsl(40 30% 12%)); --danger: light-dark(hsl(355 70% 50%), hsl(355 75% 80%)); --danger-fg: light-dark(white, hsl(355 30% 12%)); --neutral: light-dark(hsl(220 12% 42%), hsl(220 20% 80%)); --neutral-fg: light-dark(white, hsl(220 30% 12%)); --surface: light-dark(hsl(0 0% 100%), hsl(214 18% 8%)); --surface-raised: light-dark(hsl(214 30% 98%), hsl(214 16% 11%)); --surface-subtle: light-dark(hsl(214 35% 95%), hsl(214 14% 16%)); --surface-solid: light-dark(hsl(220 24% 12%), hsl(0 0% 96%)); --text: light-dark(hsl(220 24% 12%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(220 10% 42%), hsl(214 8% 68%)); --text-subtle: light-dark(hsl(220 8% 55%), hsl(214 7% 55%)); --border: light-dark(hsl(220 16% 86%), hsl(214 12% 24%)); --focus-ring: light-dark(hsl(214 82% 44% / 0.22), hsl(214 75% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(220 30% 10%), hsl(0 0% 0%)); } } [data-theme="forest"] { color-scheme: light dark; --primary: hsl(175 48% 26%); --primary-fg: white; --secondary: hsl(82 42% 34%); --secondary-fg: white; --success: hsl(148 58% 32%); --success-fg: white; --warning: hsl(42 88% 48%); --warning-fg: hsl(35 35% 12%); --danger: hsl(4 62% 48%); --danger-fg: white; --neutral: hsl(120 10% 34%); --neutral-fg: white; --surface: hsl(48 36% 96%); --surface-raised: hsl(45 36% 98%); --surface-subtle: hsl(112 26% 91%); --surface-solid: hsl(130 22% 15%); --text: hsl(130 20% 14%); --text-muted: hsl(125 10% 38%); --text-subtle: hsl(125 8% 50%); --border: hsl(105 18% 78%); --focus: var(--primary); --focus-ring: hsl(175 48% 26% / 0.22); --radius: 0.75rem; --radius-sm: 0.5rem; --radius-lg: 1.25rem; } @supports (color: light-dark(red, blue)) { [data-theme="forest"] { --primary: light-dark(hsl(175 48% 26%), hsl(175 45% 76%)); --primary-fg: light-dark(white, hsl(175 30% 12%)); --secondary: light-dark(hsl(82 42% 34%), hsl(82 50% 80%)); --secondary-fg: light-dark(white, hsl(82 30% 12%)); --success: light-dark(hsl(148 58% 32%), hsl(148 66% 80%)); --success-fg: light-dark(white, hsl(148 30% 12%)); --warning: light-dark(hsl(42 88% 48%), hsl(42 75% 80%)); --warning-fg: light-dark(hsl(35 35% 12%), hsl(42 30% 12%)); --danger: light-dark(hsl(4 62% 48%), hsl(4 70% 80%)); --danger-fg: light-dark(white, hsl(4 30% 12%)); --neutral: light-dark(hsl(120 10% 34%), hsl(120 18% 80%)); --neutral-fg: light-dark(white, hsl(120 30% 12%)); --surface: light-dark(hsl(48 36% 96%), hsl(130 18% 8%)); --surface-raised: light-dark(hsl(45 36% 98%), hsl(130 16% 11%)); --surface-subtle: light-dark(hsl(112 26% 91%), hsl(130 14% 16%)); --surface-solid: light-dark(hsl(130 22% 15%), hsl(0 0% 96%)); --text: light-dark(hsl(130 20% 14%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(125 10% 38%), hsl(130 8% 68%)); --text-subtle: light-dark(hsl(125 8% 50%), hsl(130 7% 55%)); --border: light-dark(hsl(105 18% 78%), hsl(130 12% 24%)); --focus-ring: light-dark(hsl(175 48% 26% / 0.22), hsl(175 45% 76% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(220 30% 10%), hsl(0 0% 0%)); } } [data-theme="ocean"] { color-scheme: light dark; --primary: hsl(198 82% 35%); --primary-fg: white; --secondary: hsl(174 58% 30%); --secondary-fg: white; --success: hsl(160 62% 30%); --success-fg: white; --warning: hsl(36 90% 50%); --warning-fg: hsl(35 35% 12%); --danger: hsl(350 70% 52%); --danger-fg: white; --neutral: hsl(205 12% 38%); --neutral-fg: white; --surface: hsl(200 50% 98%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(198 42% 94%); --surface-solid: hsl(204 38% 16%); --text: hsl(205 34% 14%); --text-muted: hsl(205 12% 42%); --text-subtle: hsl(205 10% 56%); --border: hsl(198 30% 84%); --focus: var(--primary); --focus-ring: hsl(198 82% 35% / 0.22); } @supports (color: light-dark(red, blue)) { [data-theme="ocean"] { --primary: light-dark(hsl(198 82% 35%), hsl(198 75% 80%)); --primary-fg: light-dark(white, hsl(198 30% 12%)); --secondary: light-dark(hsl(174 58% 30%), hsl(174 66% 80%)); --secondary-fg: light-dark(white, hsl(174 30% 12%)); --success: light-dark(hsl(160 62% 30%), hsl(160 70% 80%)); --success-fg: light-dark(white, hsl(160 30% 12%)); --warning: light-dark(hsl(36 90% 50%), hsl(36 75% 80%)); --warning-fg: light-dark(hsl(35 35% 12%), hsl(36 30% 12%)); --danger: light-dark(hsl(350 70% 52%), hsl(350 75% 80%)); --danger-fg: light-dark(white, hsl(350 30% 12%)); --neutral: light-dark(hsl(205 12% 38%), hsl(205 20% 80%)); --neutral-fg: light-dark(white, hsl(205 30% 12%)); --surface: light-dark(hsl(200 50% 98%), hsl(200 18% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(200 16% 11%)); --surface-subtle: light-dark(hsl(198 42% 94%), hsl(200 14% 16%)); --surface-solid: light-dark(hsl(204 38% 16%), hsl(0 0% 96%)); --text: light-dark(hsl(205 34% 14%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(205 12% 42%), hsl(200 8% 68%)); --text-subtle: light-dark(hsl(205 10% 56%), hsl(200 7% 55%)); --border: light-dark(hsl(198 30% 84%), hsl(200 12% 24%)); --focus-ring: light-dark(hsl(198 82% 35% / 0.22), hsl(198 75% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(220 30% 10%), hsl(0 0% 0%)); } } [data-theme="spruce"] { color-scheme: light dark; --primary: hsl(174 45% 24%); --primary-fg: hsl(160 30% 97%); --secondary: hsl(24 48% 42%); --secondary-fg: hsl(0 0% 98%); --success: hsl(135 38% 33%); --success-fg: hsl(0 0% 98%); --warning: hsl(42 72% 35%); --warning-fg: hsl(0 0% 98%); --danger: hsl(3 55% 44%); --danger-fg: hsl(0 0% 98%); --neutral: hsl(185 8% 40%); --neutral-fg: hsl(0 0% 98%); --surface: hsl(0 0% 100%); --surface-raised: hsl(160 20% 98%); --surface-subtle: hsl(168 18% 95%); --surface-solid: hsl(185 25% 11%); --text: hsl(185 25% 11%); --text-muted: hsl(183 9% 40%); --text-subtle: hsl(182 7% 55%); --border: hsl(170 12% 86%); --focus: var(--primary); --focus-ring: hsl(174 45% 24% / 0.22); } @supports (color: light-dark(red, blue)) { [data-theme="spruce"] { --primary: light-dark(hsl(174 45% 24%), hsl(170 35% 66%)); --primary-fg: light-dark(hsl(160 30% 97%), hsl(174 40% 9%)); --secondary: light-dark(hsl(24 48% 42%), hsl(26 50% 70%)); --secondary-fg: light-dark(hsl(0 0% 98%), hsl(26 35% 11%)); --success: light-dark(hsl(135 38% 33%), hsl(135 35% 60%)); --success-fg: light-dark(hsl(0 0% 98%), hsl(135 35% 8%)); --warning: light-dark(hsl(42 72% 35%), hsl(44 60% 62%)); --warning-fg: light-dark(hsl(0 0% 98%), hsl(42 35% 10%)); --danger: light-dark(hsl(3 55% 44%), hsl(3 58% 69%)); --danger-fg: light-dark(hsl(0 0% 98%), hsl(3 35% 10%)); --neutral: light-dark(hsl(185 8% 40%), hsl(183 10% 70%)); --neutral-fg: light-dark(hsl(0 0% 98%), hsl(185 18% 10%)); --surface: light-dark(hsl(0 0% 100%), hsl(182 20% 8%)); --surface-raised: light-dark(hsl(160 20% 98%), hsl(182 17% 11%)); --surface-subtle: light-dark(hsl(168 18% 95%), hsl(182 14% 15%)); --surface-solid: light-dark(hsl(185 25% 11%), hsl(0 0% 96%)); --text: light-dark(hsl(185 25% 11%), hsl(175 12% 94%)); --text-muted: light-dark(hsl(183 9% 40%), hsl(180 8% 66%)); --text-subtle: light-dark(hsl(182 7% 55%), hsl(180 7% 52%)); --border: light-dark(hsl(170 12% 86%), hsl(182 12% 23%)); --focus-ring: light-dark(hsl(174 45% 24% / 0.22), hsl(170 35% 66% / 0.28)); --hover-overlay: light-dark(hsl(185 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(185 30% 10%), hsl(0 0% 0%)); } } [data-theme="petrol"] { color-scheme: light dark; --primary: hsl(203 55% 30%); --primary-fg: hsl(0 0% 98%); --secondary: hsl(22 55% 47%); --secondary-fg: hsl(0 0% 98%); --success: hsl(155 45% 32%); --success-fg: hsl(0 0% 98%); --warning: hsl(38 70% 36%); --warning-fg: hsl(0 0% 98%); --danger: hsl(357 55% 45%); --danger-fg: hsl(0 0% 98%); --neutral: hsl(210 8% 43%); --neutral-fg: hsl(0 0% 98%); --surface: hsl(0 0% 100%); --surface-raised: hsl(204 30% 98%); --surface-subtle: hsl(204 25% 96%); --surface-solid: hsl(207 25% 12%); --text: hsl(207 25% 12%); --text-muted: hsl(206 9% 42%); --text-subtle: hsl(205 7% 57%); --border: hsl(205 15% 87%); --focus: var(--primary); --focus-ring: hsl(203 55% 30% / 0.22); } @supports (color: light-dark(red, blue)) { [data-theme="petrol"] { --primary: light-dark(hsl(203 55% 30%), hsl(202 55% 72%)); --primary-fg: light-dark(hsl(0 0% 98%), hsl(204 40% 10%)); --secondary: light-dark(hsl(22 55% 47%), hsl(24 55% 70%)); --secondary-fg: light-dark(hsl(0 0% 98%), hsl(24 35% 11%)); --success: light-dark(hsl(155 45% 32%), hsl(155 40% 60%)); --success-fg: light-dark(hsl(0 0% 98%), hsl(155 35% 8%)); --warning: light-dark(hsl(38 70% 36%), hsl(40 62% 63%)); --warning-fg: light-dark(hsl(0 0% 98%), hsl(38 35% 10%)); --danger: light-dark(hsl(357 55% 45%), hsl(357 58% 70%)); --danger-fg: light-dark(hsl(0 0% 98%), hsl(357 35% 10%)); --neutral: light-dark(hsl(210 8% 43%), hsl(208 10% 71%)); --neutral-fg: light-dark(hsl(0 0% 98%), hsl(208 18% 10%)); --surface: light-dark(hsl(0 0% 100%), hsl(206 22% 9%)); --surface-raised: light-dark(hsl(204 30% 98%), hsl(206 19% 12%)); --surface-subtle: light-dark(hsl(204 25% 96%), hsl(206 15% 16%)); --surface-solid: light-dark(hsl(207 25% 12%), hsl(0 0% 96%)); --text: light-dark(hsl(207 25% 12%), hsl(205 12% 95%)); --text-muted: light-dark(hsl(206 9% 42%), hsl(205 8% 67%)); --text-subtle: light-dark(hsl(205 7% 57%), hsl(205 7% 53%)); --border: light-dark(hsl(205 15% 87%), hsl(206 12% 24%)); --focus-ring: light-dark(hsl(203 55% 30% / 0.22), hsl(202 55% 72% / 0.28)); --hover-overlay: light-dark(hsl(207 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(207 30% 10%), hsl(0 0% 0%)); } } [data-theme="sunset"] { color-scheme: light dark; --primary: hsl(16 84% 43%); --primary-fg: white; --secondary: hsl(330 60% 52%); --secondary-fg: white; --success: hsl(142 52% 34%); --success-fg: white; --warning: hsl(42 94% 52%); --warning-fg: hsl(30 35% 12%); --danger: hsl(358 72% 52%); --danger-fg: white; --neutral: hsl(24 12% 38%); --neutral-fg: white; --surface: hsl(34 70% 97%); --surface-raised: hsl(30 80% 99%); --surface-subtle: hsl(28 62% 92%); --surface-solid: hsl(18 34% 18%); --text: hsl(20 34% 14%); --text-muted: hsl(20 12% 42%); --text-subtle: hsl(20 10% 55%); --border: hsl(25 38% 84%); --focus: var(--primary); --focus-ring: hsl(16 84% 43% / 0.22); --selection-bg: var(--secondary); --selection-fg: var(--secondary-fg); --shadow-color: hsl(20 60% 12%); } @supports (color: light-dark(red, blue)) { [data-theme="sunset"] { --primary: light-dark(hsl(16 84% 43%), hsl(16 75% 80%)); --primary-fg: light-dark(white, hsl(16 30% 12%)); --secondary: light-dark(hsl(330 60% 52%), hsl(330 68% 80%)); --secondary-fg: light-dark(white, hsl(330 30% 12%)); --success: light-dark(hsl(142 52% 34%), hsl(142 60% 80%)); --success-fg: light-dark(white, hsl(142 30% 12%)); --warning: light-dark(hsl(42 94% 52%), hsl(42 75% 80%)); --warning-fg: light-dark(hsl(30 35% 12%), hsl(42 30% 12%)); --danger: light-dark(hsl(358 72% 52%), hsl(358 75% 80%)); --danger-fg: light-dark(white, hsl(358 30% 12%)); --neutral: light-dark(hsl(24 12% 38%), hsl(24 20% 80%)); --neutral-fg: light-dark(white, hsl(24 30% 12%)); --surface: light-dark(hsl(34 70% 97%), hsl(20 18% 8%)); --surface-raised: light-dark(hsl(30 80% 99%), hsl(20 16% 11%)); --surface-subtle: light-dark(hsl(28 62% 92%), hsl(20 14% 16%)); --surface-solid: light-dark(hsl(18 34% 18%), hsl(0 0% 96%)); --text: light-dark(hsl(20 34% 14%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(20 12% 42%), hsl(20 8% 68%)); --text-subtle: light-dark(hsl(20 10% 55%), hsl(20 7% 55%)); --border: light-dark(hsl(25 38% 84%), hsl(20 12% 24%)); --focus-ring: light-dark(hsl(16 84% 43% / 0.22), hsl(16 75% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(20 60% 12%), hsl(20 40% 2%)); } } [data-theme="lavender"] { color-scheme: light dark; --primary: hsl(258 70% 58%); --primary-fg: white; --secondary: hsl(305 45% 48%); --secondary-fg: white; --success: hsl(150 50% 33%); --success-fg: white; --warning: hsl(42 90% 52%); --warning-fg: hsl(35 35% 12%); --danger: hsl(350 68% 52%); --danger-fg: white; --neutral: hsl(260 10% 42%); --neutral-fg: white; --surface: hsl(260 45% 98%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(260 35% 94%); --surface-solid: hsl(260 30% 18%); --text: hsl(260 28% 15%); --text-muted: hsl(260 12% 43%); --text-subtle: hsl(260 10% 57%); --border: hsl(260 28% 85%); --focus: var(--primary); --focus-ring: hsl(258 70% 58% / 0.22); --soft-bg-mix: 92%; --soft-hover-alpha: 8%; --shadow-color: hsl(260 45% 20%); } @supports (color: light-dark(red, blue)) { [data-theme="lavender"] { --primary: light-dark(hsl(258 70% 58%), hsl(258 75% 80%)); --primary-fg: light-dark(white, hsl(258 30% 12%)); --secondary: light-dark(hsl(305 45% 48%), hsl(305 53% 80%)); --secondary-fg: light-dark(white, hsl(305 30% 12%)); --success: light-dark(hsl(150 50% 33%), hsl(150 58% 80%)); --success-fg: light-dark(white, hsl(150 30% 12%)); --warning: light-dark(hsl(42 90% 52%), hsl(42 75% 80%)); --warning-fg: light-dark(hsl(35 35% 12%), hsl(42 30% 12%)); --danger: light-dark(hsl(350 68% 52%), hsl(350 75% 80%)); --danger-fg: light-dark(white, hsl(350 30% 12%)); --neutral: light-dark(hsl(260 10% 42%), hsl(260 18% 80%)); --neutral-fg: light-dark(white, hsl(260 30% 12%)); --surface: light-dark(hsl(260 45% 98%), hsl(260 18% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(260 16% 11%)); --surface-subtle: light-dark(hsl(260 35% 94%), hsl(260 14% 16%)); --surface-solid: light-dark(hsl(260 30% 18%), hsl(0 0% 96%)); --text: light-dark(hsl(260 28% 15%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(260 12% 43%), hsl(260 8% 68%)); --text-subtle: light-dark(hsl(260 10% 57%), hsl(260 7% 55%)); --border: light-dark(hsl(260 28% 85%), hsl(260 12% 24%)); --focus-ring: light-dark(hsl(258 70% 58% / 0.22), hsl(258 75% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(260 45% 20%), hsl(260 40% 2%)); } } [data-theme="mono"] { color-scheme: light dark; --primary: hsl(220 8% 18%); --primary-fg: white; --secondary: hsl(220 7% 34%); --secondary-fg: white; --success: hsl(145 42% 32%); --success-fg: white; --warning: hsl(40 70% 44%); --warning-fg: hsl(35 35% 10%); --danger: hsl(0 56% 46%); --danger-fg: white; --neutral: hsl(220 6% 45%); --neutral-fg: white; --surface: hsl(0 0% 99%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(220 8% 94%); --surface-solid: hsl(220 8% 15%); --text: hsl(220 8% 12%); --text-muted: hsl(220 6% 42%); --text-subtle: hsl(220 5% 58%); --border: hsl(220 8% 84%); --focus: var(--primary); --focus-ring: hsl(220 8% 18% / 0.22); } @supports (color: light-dark(red, blue)) { [data-theme="mono"] { --primary: light-dark(hsl(220 8% 18%), hsl(220 16% 80%)); --primary-fg: light-dark(white, hsl(220 30% 12%)); --secondary: light-dark(hsl(220 7% 34%), hsl(220 15% 80%)); --secondary-fg: light-dark(white, hsl(220 30% 12%)); --success: light-dark(hsl(145 42% 32%), hsl(145 50% 80%)); --success-fg: light-dark(white, hsl(145 30% 12%)); --warning: light-dark(hsl(40 70% 44%), hsl(40 75% 80%)); --warning-fg: light-dark(hsl(35 35% 10%), hsl(40 30% 12%)); --danger: light-dark(hsl(0 56% 46%), hsl(0 64% 80%)); --danger-fg: light-dark(white, hsl(0 30% 12%)); --neutral: light-dark(hsl(220 6% 45%), hsl(220 14% 80%)); --neutral-fg: light-dark(white, hsl(220 30% 12%)); --surface: light-dark(hsl(0 0% 99%), hsl(0 0% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(0 0% 11%)); --surface-subtle: light-dark(hsl(220 8% 94%), hsl(0 0% 16%)); --surface-solid: light-dark(hsl(220 8% 15%), hsl(0 0% 96%)); --text: light-dark(hsl(220 8% 12%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(220 6% 42%), hsl(0 0% 68%)); --text-subtle: light-dark(hsl(220 5% 58%), hsl(0 0% 55%)); --border: light-dark(hsl(220 8% 84%), hsl(0 0% 24%)); --focus-ring: light-dark(hsl(220 8% 18% / 0.22), hsl(220 16% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(220 30% 10%), hsl(0 0% 0%)); } } [data-theme="square"] { color-scheme: light dark; --primary: hsl(220 90% 56%); --primary-fg: white; --secondary: hsl(270 60% 56%); --secondary-fg: white; --success: hsl(145 60% 32%); --success-fg: white; --warning: hsl(38 92% 50%); --warning-fg: hsl(35 30% 12%); --danger: hsl(0 75% 51%); --danger-fg: white; --neutral: hsl(220 10% 42%); --neutral-fg: white; --surface: hsl(0 0% 100%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(220 20% 96%); --surface-solid: hsl(222 22% 12%); --text: hsl(222 22% 12%); --text-muted: hsl(220 10% 42%); --text-subtle: hsl(220 8% 55%); --border: hsl(220 15% 88%); --focus: var(--primary); --focus-ring: hsl(220 90% 56% / 0.22); --hover-overlay: hsl(220 30% 10% / 0.04); --radius: 0; --radius-sm: 0; --radius-lg: 0; } @supports (color: light-dark(red, blue)) { [data-theme="square"] { --primary: light-dark(hsl(220 90% 56%), hsl(220 75% 80%)); --primary-fg: light-dark(white, hsl(220 30% 12%)); --secondary: light-dark(hsl(270 60% 56%), hsl(270 68% 80%)); --secondary-fg: light-dark(white, hsl(270 30% 12%)); --success: light-dark(hsl(145 60% 32%), hsl(145 68% 80%)); --success-fg: light-dark(white, hsl(145 30% 12%)); --warning: light-dark(hsl(38 92% 50%), hsl(38 75% 80%)); --warning-fg: light-dark(hsl(35 30% 12%), hsl(38 30% 12%)); --danger: light-dark(hsl(0 75% 51%), hsl(0 75% 80%)); --danger-fg: light-dark(white, hsl(0 30% 12%)); --neutral: light-dark(hsl(220 10% 42%), hsl(220 18% 80%)); --neutral-fg: light-dark(white, hsl(220 30% 12%)); --surface: light-dark(hsl(0 0% 100%), hsl(222 18% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(222 16% 11%)); --surface-subtle: light-dark(hsl(220 20% 96%), hsl(222 14% 16%)); --surface-solid: light-dark(hsl(222 22% 12%), hsl(0 0% 96%)); --text: light-dark(hsl(222 22% 12%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(220 10% 42%), hsl(222 8% 68%)); --text-subtle: light-dark(hsl(220 8% 55%), hsl(222 7% 55%)); --border: light-dark(hsl(220 15% 88%), hsl(222 12% 24%)); --focus-ring: light-dark(hsl(220 90% 56% / 0.22), hsl(220 75% 80% / 0.28)); --hover-overlay: light-dark(hsl(220 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(220 30% 10%), hsl(0 0% 0%)); } } [data-theme="edge"] { color-scheme: light dark; --primary: hsl(224 72% 42%); --primary-fg: white; --secondary: hsl(166 54% 30%); --secondary-fg: white; --success: hsl(145 46% 32%); --success-fg: white; --warning: hsl(36 80% 38%); --warning-fg: hsl(34 35% 10%); --danger: hsl(354 62% 46%); --danger-fg: white; --neutral: hsl(228 9% 42%); --neutral-fg: white; --surface: hsl(40 20% 99%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(220 24% 95%); --surface-solid: hsl(228 26% 12%); --text: hsl(228 24% 12%); --text-muted: hsl(228 9% 42%); --text-subtle: hsl(228 7% 56%); --border: hsl(220 14% 86%); --focus: var(--primary); --focus-ring: hsl(224 72% 42% / 0.22); --hover-overlay: hsl(228 30% 10% / 0.04); --radius: 0.375rem; --radius-sm: 0.25rem; --radius-lg: 0.625rem; --btn-default-bg: var(--surface-subtle); --btn-default-border: transparent; --btn-border-color: transparent; --btn-border-block-end-width: 2px; --control-border-block-end-color: var(--primary); --control-border-block-end-width: 2px; } [data-theme="edge"] .btn:not(.link) { --btn-border-block-end-color: var(--intent, var(--primary)); } [data-theme="edge"] .btn:not(:where(.solid, .soft, .outline, .ghost, .link)) { --btn-default-fg: var(--intent, var(--text)); --ui-hover-bg: var(--surface-raised); } [data-theme="edge"] .btn:not( :where(:disabled, [aria-disabled="true"], .solid, .soft, .outline, .ghost, .link) ):hover { box-shadow: none; } [data-theme="edge"] .alert { --alert-border-inline-start-color: var(--intent, var(--primary)); --alert-border-inline-start-width: 4px; } [data-theme="edge"] :is(.input, .textarea, .select):focus-visible { --control-border: var(--border); --control-border-block-end-width: 3px; } @supports (color: light-dark(red, blue)) { [data-theme="edge"] { --primary: light-dark(hsl(224 72% 42%), hsl(220 80% 76%)); --primary-fg: light-dark(white, hsl(224 35% 10%)); --secondary: light-dark(hsl(166 54% 30%), hsl(166 58% 70%)); --secondary-fg: light-dark(white, hsl(166 35% 9%)); --success: light-dark(hsl(145 46% 32%), hsl(145 48% 64%)); --success-fg: light-dark(white, hsl(145 35% 8%)); --warning: light-dark(hsl(36 80% 38%), hsl(40 72% 66%)); --warning-fg: light-dark(hsl(34 35% 10%), hsl(38 35% 10%)); --danger: light-dark(hsl(354 62% 46%), hsl(354 66% 72%)); --danger-fg: light-dark(white, hsl(354 35% 10%)); --neutral: light-dark(hsl(228 9% 42%), hsl(228 12% 72%)); --neutral-fg: light-dark(white, hsl(228 24% 10%)); --surface: light-dark(hsl(40 20% 99%), hsl(228 20% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(228 17% 11%)); --surface-subtle: light-dark(hsl(220 24% 95%), hsl(228 14% 16%)); --surface-solid: light-dark(hsl(228 26% 12%), hsl(0 0% 96%)); --text: light-dark(hsl(228 24% 12%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(228 9% 42%), hsl(228 8% 68%)); --text-subtle: light-dark(hsl(228 7% 56%), hsl(228 7% 55%)); --border: light-dark(hsl(220 14% 86%), hsl(228 12% 24%)); --focus-ring: light-dark(hsl(224 72% 42% / 0.22), hsl(220 80% 76% / 0.28)); --hover-overlay: light-dark(hsl(228 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(228 30% 10%), hsl(0 0% 0%)); } } [data-theme="cyberpunk"] { color-scheme: light; --primary: hsl(330 100% 60%); --primary-fg: hsl(330 100% 10%); --secondary: hsl(187 100% 42%); --secondary-fg: hsl(187 100% 8%); --success: hsl(150 100% 35%); --success-fg: hsl(150 100% 6%); --warning: hsl(25 95% 50%); --warning-fg: hsl(25 100% 8%); --danger: hsl(0 85% 44%); --danger-fg: hsl(0 0% 98%); --neutral: hsl(56 30% 8%); --neutral-fg: hsl(56 100% 55%); --surface: hsl(56 100% 50%); --surface-raised: hsl(54 100% 64%); --surface-subtle: hsl(53 100% 80%); --surface-solid: hsl(56 30% 8%); --text: hsl(56 60% 6%); --text-muted: hsl(56 25% 22%); --text-subtle: hsl(56 14% 34%); --border: hsl(56 60% 6%); --focus: hsl(330 100% 42%); --focus-ring: hsl(330 100% 42% / 0.3); --hover-overlay: hsl(56 100% 8% / 0.08); --radius: 0; --radius-sm: 0; --radius-lg: 0; --border-width: 2px; --shadow: 0.25rem 0.25rem 0 hsl(56 60% 6%); --shadow-popout: 0.25rem 0.25rem 0 hsl(56 60% 6%); --shadow-color: hsl(56 60% 6%); --soft-bg-mix: 78%; --soft-border-mix: 40%; --selection-bg: hsl(56 60% 6%); --selection-fg: hsl(56 100% 50%); } [data-theme="neon"] { color-scheme: dark; --primary: hsl(315 95% 62%); --primary-fg: hsl(315 100% 8%); --secondary: hsl(182 100% 46%); --secondary-fg: hsl(182 100% 7%); --success: hsl(135 85% 52%); --success-fg: hsl(135 100% 6%); --warning: hsl(55 95% 55%); --warning-fg: hsl(55 100% 7%); --danger: hsl(350 100% 64%); --danger-fg: hsl(350 100% 8%); --neutral: hsl(260 12% 76%); --neutral-fg: hsl(260 25% 8%); --surface: hsl(260 25% 6%); --surface-raised: hsl(260 22% 9%); --surface-subtle: hsl(260 20% 13%); --surface-solid: hsl(0 0% 96%); --text: hsl(0 0% 97%); --text-muted: hsl(260 12% 70%); --text-subtle: hsl(260 8% 55%); --border: hsl(260 18% 24%); --focus: var(--secondary); --focus-ring: hsl(182 100% 46% / 0.35); --hover-overlay: hsl(0 0% 100% / 0.07); --shadow-color: hsl(260 60% 3%); --soft-bg-mix: 80%; --soft-border-mix: 45%; --soft-hover-alpha: 20%; --shadow-popout: 0 0 1rem hsl(315 95% 62% / 0.25); } @media (color-gamut: p3) { @supports (color: oklch(0% 0 0)) { [data-theme="neon"] { --primary: oklch(70% 0.32 340); --secondary: oklch(85% 0.17 195); --success: oklch(85% 0.28 148); --warning: oklch(92% 0.2 105); --danger: oklch(68% 0.26 15); --focus-ring: oklch(85% 0.17 195 / 0.35); --shadow-popout: 0 0 1rem oklch(70% 0.32 340 / 0.3); } } } [data-theme="gradient"] { color-scheme: light dark; --primary: hsl(211 100% 50%); --primary-fg: white; --secondary: hsl(208 7% 46%); --secondary-fg: white; --success: hsl(134 61% 41%); --success-fg: white; --warning: hsl(45 100% 51%); --warning-fg: hsl(45 100% 10%); --danger: hsl(354 70% 54%); --danger-fg: white; --neutral: hsl(210 10% 23%); --neutral-fg: white; --surface: hsl(0 0% 100%); --surface-raised: hsl(0 0% 100%); --surface-subtle: hsl(210 17% 95%); --surface-solid: hsl(210 10% 15%); --text: hsl(210 11% 15%); --text-muted: hsl(208 7% 46%); --text-subtle: hsl(210 9% 62%); --border: hsl(210 14% 89%); --focus: var(--primary); --focus-ring: hsl(211 100% 50% / 0.25); --hover-overlay: hsl(210 30% 10% / 0.04); --radius: 0.25rem; --radius-sm: 0.2rem; --radius-lg: 0.3rem; } @supports (color: light-dark(red, blue)) { [data-theme="gradient"] { --primary: light-dark(hsl(211 100% 50%), hsl(211 90% 72%)); --primary-fg: light-dark(white, hsl(211 40% 10%)); --secondary: light-dark(hsl(208 7% 46%), hsl(208 10% 72%)); --secondary-fg: light-dark(white, hsl(208 15% 10%)); --success: light-dark(hsl(134 61% 41%), hsl(134 55% 65%)); --success-fg: light-dark(white, hsl(134 40% 8%)); --warning: light-dark(hsl(45 100% 51%), hsl(45 90% 70%)); --warning-fg: light-dark(hsl(45 100% 10%), hsl(45 100% 10%)); --danger: light-dark(hsl(354 70% 54%), hsl(354 75% 74%)); --danger-fg: light-dark(white, hsl(354 40% 10%)); --neutral: light-dark(hsl(210 10% 23%), hsl(210 12% 75%)); --neutral-fg: light-dark(white, hsl(210 15% 10%)); --surface: light-dark(hsl(0 0% 100%), hsl(210 15% 8%)); --surface-raised: light-dark(hsl(0 0% 100%), hsl(210 13% 11%)); --surface-subtle: light-dark(hsl(210 17% 95%), hsl(210 12% 16%)); --surface-solid: light-dark(hsl(210 10% 15%), hsl(0 0% 96%)); --text: light-dark(hsl(210 11% 15%), hsl(0 0% 96%)); --text-muted: light-dark(hsl(208 7% 46%), hsl(210 8% 68%)); --text-subtle: light-dark(hsl(210 9% 62%), hsl(210 7% 55%)); --border: light-dark(hsl(210 14% 89%), hsl(210 12% 24%)); --focus-ring: light-dark(hsl(211 100% 50% / 0.25), hsl(211 90% 72% / 0.3)); --hover-overlay: light-dark(hsl(210 30% 10% / 0.04), hsl(0 0% 100% / 0.06)); --shadow-color: light-dark(hsl(210 30% 10%), hsl(0 0% 0%)); } } @supports (color: color-mix(in oklch, red, white)) { [data-theme="gradient"] .btn:not(:where(.soft, .outline, .ghost, .link)) { --gradient-hover-color: color-mix(in oklch, var(--intent, var(--neutral)) 88%, black); --ui-bg: linear-gradient( 180deg, color-mix(in oklch, white 15%, var(--intent, var(--neutral))), var(--intent, var(--neutral)) ); --btn-default-bg: var(--ui-bg); --ui-hover-bg: linear-gradient( 180deg, color-mix(in oklch, white 15%, var(--gradient-hover-color)), var(--gradient-hover-color) ); } }
|