actual-css 0.2.0 → 0.3.1
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 +49 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1532 -1114
- package/dist/actual.js +1 -3
- package/dist/actual.min.css +1 -1
- package/dist/optional.css +1048 -0
- package/dist/optional.min.css +1 -0
- package/docs/design-notes/browser-support.md +94 -14
- package/docs/design-notes/cascade-layer.md +7 -6
- package/docs/design-notes/enhancement-contract.md +11 -14
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +2 -1
- package/docs/design-notes/platform-alignment.md +492 -0
- package/docs/design-notes/references.md +8 -0
- package/docs/design-notes/widget-primitives.md +37 -1
- package/docs/navigation.json +135 -0
- package/docs/pages/components/accordion.md +80 -0
- package/docs/pages/components/alert.md +203 -0
- package/docs/pages/components/aura.md +35 -0
- package/docs/pages/components/avatar.md +95 -0
- package/docs/pages/components/badge.md +102 -0
- package/docs/pages/components/breadcrumb.md +19 -0
- package/docs/pages/components/button.md +210 -0
- package/docs/pages/components/card.md +195 -0
- package/docs/pages/components/chat.md +50 -0
- package/docs/pages/components/dialog.md +367 -0
- package/docs/pages/components/drawer.md +113 -0
- package/docs/pages/components/fab.md +118 -0
- package/docs/pages/components/key.md +33 -0
- package/docs/pages/components/meter.md +23 -0
- package/docs/pages/components/navbar.md +92 -0
- package/docs/pages/components/pagination.md +55 -0
- package/docs/pages/components/progress.md +29 -0
- package/docs/pages/components/skeleton.md +38 -0
- package/docs/pages/components/spinner.md +93 -0
- package/docs/pages/components/table.md +102 -0
- package/docs/pages/enhancements/flyout.md +391 -0
- package/docs/pages/enhancements/overview.md +36 -0
- package/docs/pages/enhancements/scrollspy.md +71 -0
- package/docs/pages/enhancements/status-bar.md +72 -0
- package/docs/pages/enhancements/tabs.md +80 -0
- package/docs/pages/enhancements/tooltip.md +130 -0
- package/docs/pages/examples/overview.md +43 -0
- package/docs/pages/forms/choice-cards.md +102 -0
- package/docs/pages/forms/controls.md +32 -0
- package/docs/pages/forms/detached-actions.md +59 -0
- package/docs/pages/forms/floating-field.md +88 -0
- package/docs/pages/forms/form-actions.md +56 -0
- package/docs/pages/forms/input-policy.md +91 -0
- package/docs/pages/forms/joined-controls.md +37 -0
- package/docs/pages/forms/labels.md +42 -0
- package/docs/pages/forms/otp.md +50 -0
- package/docs/pages/forms/overview.md +188 -0
- package/docs/pages/forms/password.md +40 -0
- package/docs/pages/forms/range.md +17 -0
- package/docs/pages/forms/states-and-sizes.md +321 -0
- package/docs/pages/forms/sticky-actions.md +187 -0
- package/docs/pages/forms/switch.md +31 -0
- package/docs/pages/forms/validation.md +241 -0
- package/docs/{mental-model.md → pages/foundations/philosophy.md} +33 -18
- package/docs/pages/foundations/theming.md +99 -0
- package/docs/pages/foundations/tokens.md +421 -0
- package/docs/{typography.md → pages/foundations/typography.md} +27 -9
- package/docs/pages/guides/bootstrap.md +438 -0
- package/docs/pages/guides/introduction.md +157 -0
- package/docs/pages/guides/optional-components.md +33 -0
- package/docs/pages/guides/progressive-enhancement.md +686 -0
- package/docs/pages/guides/tailwind.md +455 -0
- package/docs/pages/layout/app-shell.md +25 -0
- package/docs/pages/layout/center.md +29 -0
- package/docs/pages/layout/cluster.md +59 -0
- package/docs/pages/layout/frame.md +30 -0
- package/docs/pages/layout/grid.md +142 -0
- package/docs/pages/layout/list.md +41 -0
- package/docs/pages/layout/media.md +28 -0
- package/docs/pages/layout/overview.md +37 -0
- package/docs/pages/layout/scroll-snap.md +54 -0
- package/docs/pages/layout/sidebar-layout.md +27 -0
- package/docs/pages/layout/stack.md +55 -0
- package/docs/pages/layout/switcher.md +36 -0
- package/docs/pages/layout/topbar.md +23 -0
- package/docs/pages/patterns/actions.md +52 -0
- package/docs/pages/patterns/code-block.md +36 -0
- package/docs/pages/patterns/exclusive-accordion.md +16 -0
- package/docs/pages/patterns/hierarchical-nav.md +26 -0
- package/docs/pages/patterns/icon-input.md +25 -0
- package/docs/pages/patterns/intent-nesting.md +3 -0
- package/docs/pages/patterns/navigation-list.md +235 -0
- package/docs/pages/patterns/overview.md +58 -0
- package/docs/pages/patterns/structured-lists.md +47 -0
- package/docs/pages/utilities/accessibility.md +34 -0
- package/docs/pages/utilities/flex.md +105 -0
- package/docs/pages/utilities/links.md +18 -0
- package/docs/pages/utilities/list.md +32 -0
- package/docs/pages/utilities/overflow.md +43 -0
- package/docs/pages/utilities/overview.md +18 -0
- package/docs/pages/utilities/shape.md +25 -0
- package/docs/pages/utilities/sizing-wrapping.md +115 -0
- package/docs/pages/utilities/spacing.md +79 -0
- package/docs/pages/utilities/text.md +43 -0
- package/llms.txt +4 -4
- package/package.json +21 -12
- package/src/css/actual.css +16 -2
- package/src/css/base.css +3 -5
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +139 -102
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +69 -42
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +84 -34
- package/src/css/components/card.css +26 -38
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -109
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -2
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +125 -0
- package/src/css/components/meter.css +0 -23
- package/src/css/components/modal.css +162 -7
- package/src/css/components/navbar.css +30 -23
- package/src/css/components/overline.css +8 -9
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +6 -7
- package/src/css/components/status-bar.css +15 -24
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +19 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +14 -38
- package/src/css/forms/choice-card.css +13 -14
- package/src/css/forms/choice.css +21 -27
- package/src/css/forms/control.css +18 -17
- package/src/css/forms/custom-select.css +9 -11
- package/src/css/forms/form-actions.css +14 -3
- package/src/css/forms/form.css +7 -4
- package/src/css/forms/index.css +4 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +50 -11
- package/src/css/forms/range.css +17 -9
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -12
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +32 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +45 -2
- package/src/css/optional/aura.css +93 -0
- package/src/css/optional/chat.css +105 -0
- package/src/css/optional/fab.css +104 -0
- package/src/css/optional/floating-field.css +87 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +7 -4
- package/src/css/optional/otp.css +115 -0
- package/src/css/optional/scroll-snap.css +6 -0
- package/src/css/optional/scroller.css +13 -7
- package/src/css/optional/typography-fluid.css +5 -0
- package/src/css/optional/utilities-extra.css +17 -2
- package/src/css/prose.css +18 -8
- package/src/css/reset.css +0 -10
- package/src/css/theme.css +21 -5
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +8 -10
- package/src/css/themes/index.css +8 -4
- package/src/css/themes/{dark.css → indigo.css} +5 -4
- package/src/css/themes/neon.css +5 -5
- package/src/css/themes/square.css +0 -3
- package/src/css/tokens.css +74 -20
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +51 -66
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +67 -35
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +54 -23
- package/src/js/enhancement-loader.js +301 -0
- package/src/js/events.js +3 -0
- package/src/js/filter.js +3 -3
- package/src/js/floating.js +101 -131
- package/src/js/flyout.js +104 -87
- package/src/js/focus-group.js +116 -0
- package/src/js/focus.js +6 -1
- package/src/js/index.js +4 -2
- package/src/js/input.js +1 -1
- package/src/js/keys.js +27 -0
- package/src/js/mask.js +7 -6
- package/src/js/menu.js +87 -34
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +12 -4
- package/src/js/selectors.js +0 -7
- package/src/js/status.js +3 -1
- package/src/js/surface.js +187 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +70 -35
- package/src/js/validation.js +34 -8
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -28
- package/docs/components.md +0 -860
- package/docs/design-notes/previous-work.md +0 -5
- package/docs/forms.md +0 -1265
- package/docs/javascript.md +0 -496
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -504
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -929
- package/docs/utilities.md +0 -384
- package/src/css/dialog-fallback.css +0 -56
- package/src/js/dialog-fallback.js +0 -163
package/src/css/reset.css
CHANGED
|
@@ -24,16 +24,6 @@ select {
|
|
|
24
24
|
display: none !important;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/* Legacy dialog fallback only. Modern dialogs keep the browser's native closed
|
|
28
|
-
state so display/overlay transitions are not flattened by the reset.
|
|
29
|
-
The presentation for the dialog-fallback.js shim lives in the separate
|
|
30
|
-
dialog-fallback.css, so it can be dropped from custom bundles. */
|
|
31
|
-
@supports not (selector(dialog:modal)) {
|
|
32
|
-
dialog:not([open]) {
|
|
33
|
-
display: none;
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
27
|
:where(img, svg, video) {
|
|
38
28
|
max-inline-size: 100%;
|
|
39
29
|
block-size: auto;
|
package/src/css/theme.css
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Theme tokens — the palette, surfaces, text, borders, radius and shadow
|
|
3
|
+
* color. Named themes (themes/*.css) override this file; authors can set the
|
|
4
|
+
* same tokens on :root or on [data-theme="…"] islands.
|
|
5
|
+
*
|
|
6
|
+
* Public: Intent colors, Surfaces, Text, Lines and focus, Radius scale,
|
|
7
|
+
* Shadow color, Focus ring derivation.
|
|
8
|
+
* Derived: "Theme-derived aliases", Tone subsystem, Backdrop fill — reference
|
|
9
|
+
* other tokens; hard-coded overrides on a custom theme will break the intent.
|
|
10
|
+
* Internal: --hgroup-gap.
|
|
11
|
+
*/
|
|
1
12
|
:root {
|
|
2
13
|
color-scheme: light dark;
|
|
3
14
|
}
|
|
@@ -65,7 +76,6 @@
|
|
|
65
76
|
/* Pre-color-mix fallback only — superseded below by a derivation from
|
|
66
77
|
--focus so overriding --neutral/--focus never leaves a stale ring. */
|
|
67
78
|
--focus-ring: hsl(258 7% 43% / 0.3);
|
|
68
|
-
--focus-ring-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring);
|
|
69
79
|
--hover-overlay: hsl(260 20% 10% / 0.04);
|
|
70
80
|
|
|
71
81
|
/* Radius scale — themes may override the whole scale (e.g. [data-theme="square"]) */
|
|
@@ -76,13 +86,19 @@
|
|
|
76
86
|
/* Shadow color — consumed by --shadow / --shadow-popout in tokens.css */
|
|
77
87
|
--shadow-color: hsl(260 25% 10%);
|
|
78
88
|
|
|
79
|
-
/*
|
|
89
|
+
/* hgroup internal gap */
|
|
90
|
+
--hgroup-gap: 0.25em;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Theme-derived aliases — re-declared on every theme boundary (see tokens.css
|
|
94
|
+
for the custom-property resolution rationale): islands recompute these from
|
|
95
|
+
their own tokens instead of inheriting :root's resolved values. */
|
|
96
|
+
:root,
|
|
97
|
+
[data-theme] {
|
|
80
98
|
--heading: var(--text);
|
|
81
99
|
--selection-bg: var(--primary);
|
|
82
100
|
--selection-fg: var(--primary-fg);
|
|
83
|
-
|
|
84
|
-
/* hgroup internal gap */
|
|
85
|
-
--hgroup-gap: 0.25em;
|
|
101
|
+
--focus-ring-shadow: 0 0 0 var(--focus-ring-width) var(--focus-ring);
|
|
86
102
|
}
|
|
87
103
|
|
|
88
104
|
/* Tone subsystem — fixed-backdrop foreground for components placed over media
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* Cyberpunk — light-only stress-test theme (single block, color-scheme: light,
|
|
2
|
-
* same shape as
|
|
2
|
+
* same shape as indigo.css). Illustrative rather than production: it exists to
|
|
3
3
|
* prove the token contract survives an extreme spec — a saturated yellow
|
|
4
4
|
* canvas, near-black text and borders, dark-on-bright intent pairs, zero
|
|
5
5
|
* radius, 2px strokes, and hard offset shadows — without touching a single
|
package/src/css/themes/dim.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Dim — a dark theme variant that lifts the surface tones up a few percentage
|
|
2
|
-
* points. Same shape as
|
|
3
|
-
* it in when the canonical dark is too dense. Demonstrates how a theme
|
|
4
|
-
* recolor the same token set without changing structure. */
|
|
2
|
+
* points. Same shape as indigo.css (dark-only, single block) so authors can
|
|
3
|
+
* drop it in when the canonical dark is too dense. Demonstrates how a theme
|
|
4
|
+
* can recolor the same token set without changing structure. */
|
|
5
5
|
[data-theme="dim"] {
|
|
6
6
|
color-scheme: dark;
|
|
7
7
|
|
package/src/css/themes/edge.css
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* intent-colored lower edge (.solid remains available when an action needs a
|
|
4
4
|
* filled treatment), text controls (input/textarea/select) pick up the same
|
|
5
5
|
* lower-edge accent via --control-border-block-end-*, alerts get an
|
|
6
|
-
* intent-colored leading flag via --alert-border-inline-start
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* intent-colored leading flag via --alert-border-inline-start-*. The focus
|
|
7
|
+
* ring keeps the shared width — edge only drops the border-color flip so the
|
|
8
|
+
* intent-colored lower edge stays dominant. */
|
|
9
9
|
[data-theme="edge"] {
|
|
10
10
|
color-scheme: light dark;
|
|
11
11
|
|
|
@@ -61,13 +61,11 @@
|
|
|
61
61
|
--ui-hover-bg: var(--surface-raised);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
box-shadow: none;
|
|
70
|
-
}
|
|
64
|
+
[data-theme="edge"]
|
|
65
|
+
.btn:not(
|
|
66
|
+
:where(:disabled, [aria-disabled="true"], .solid, .soft, .outline, .ghost, .link)
|
|
67
|
+
):hover {
|
|
68
|
+
box-shadow: none;
|
|
71
69
|
}
|
|
72
70
|
|
|
73
71
|
/* Intent-dependent alert token, same reasoning as the button rule above:
|
package/src/css/themes/index.css
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/*
|
|
2
|
+
* Reference theme presets. Shipped for inspection and copying; not public
|
|
3
|
+
* package entry points (package.json blocks ./css/themes exports).
|
|
4
|
+
*
|
|
5
|
+
* Opt-in theme bundle. Importing this file pulls in every theme below, each
|
|
2
6
|
* gated by [data-theme="…"]. The light baseline is :root in src/css/theme.css —
|
|
3
7
|
* there is no light.css here.
|
|
4
8
|
*
|
|
5
9
|
* The themes are illustrative: each one demonstrates a different set of knobs
|
|
6
10
|
* the token contract exposes, beyond recoloring.
|
|
7
11
|
*
|
|
8
|
-
*
|
|
12
|
+
* indigo — deep blue/violet dark palette (single block)
|
|
9
13
|
* dim — dark variant with lifted surface tones
|
|
10
14
|
* corporate — reference paired light/dark recolor via light-dark()
|
|
11
15
|
* forest — paired recolor + scaled-up radius tokens
|
|
@@ -24,9 +28,9 @@
|
|
|
24
28
|
* gradient — paired recolor + Bootstrap 4 style gradient on solid buttons
|
|
25
29
|
* via component-local button tokens
|
|
26
30
|
*
|
|
27
|
-
* Single-block themes (
|
|
31
|
+
* Single-block themes (indigo, dim, cyberpunk, neon) pin one color-scheme and
|
|
28
32
|
* cannot adapt to prefers-color-scheme; the paired ones follow the OS. */
|
|
29
|
-
@import "./
|
|
33
|
+
@import "./indigo.css";
|
|
30
34
|
@import "./dim.css";
|
|
31
35
|
@import "./corporate.css";
|
|
32
36
|
@import "./forest.css";
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* does not adapt to prefers-color-scheme;
|
|
3
|
-
* dim.css is a darker variant with
|
|
4
|
-
|
|
1
|
+
/* Indigo — deep blue/violet palette, dark-only. Single-block shape
|
|
2
|
+
* (color-scheme: dark only) — it does not adapt to prefers-color-scheme;
|
|
3
|
+
* opt in via [data-theme="indigo"]. dim.css is a darker variant with
|
|
4
|
+
* lifted surface tones. */
|
|
5
|
+
[data-theme="indigo"] {
|
|
5
6
|
color-scheme: dark;
|
|
6
7
|
|
|
7
8
|
--primary: hsl(220 90% 66%);
|
package/src/css/themes/neon.css
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/* Neon — dark-only theme (single block, color-scheme: dark, same shape as
|
|
2
|
-
*
|
|
3
|
-
* block uses sRGB-safe hsl() and works everywhere
|
|
4
|
-
* displays with oklch() support the intents are re-declared with chroma
|
|
5
|
-
* sRGB. This is the pattern for shipping colors sRGB cannot express
|
|
6
|
-
* breaking older screens or browsers. Also demonstrates the soft-variant
|
|
2
|
+
* indigo.css) that demonstrates wide-gamut progressive enhancement. The
|
|
3
|
+
* baseline block uses sRGB-safe hsl() and works everywhere indigo.css works;
|
|
4
|
+
* on P3 displays with oklch() support the intents are re-declared with chroma
|
|
5
|
+
* beyond sRGB. This is the pattern for shipping colors sRGB cannot express
|
|
6
|
+
* without breaking older screens or browsers. Also demonstrates the soft-variant
|
|
7
7
|
* tuning knobs and glow shadows on popovers. */
|
|
8
8
|
[data-theme="neon"] {
|
|
9
9
|
color-scheme: dark;
|
|
@@ -34,9 +34,6 @@
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
@supports (color: light-dark(red, blue)) {
|
|
37
|
-
/* Square — paired light/dark theme that demonstrates overriding the full
|
|
38
|
-
* --radius scale to 0 for sharp-cornered applications. The recolor is close to
|
|
39
|
-
* the default blue palette; the radius override is the point. */
|
|
40
37
|
[data-theme="square"] {
|
|
41
38
|
--primary: light-dark(hsl(220 90% 56%), hsl(220 75% 80%));
|
|
42
39
|
--primary-fg: light-dark(white, hsl(220 30% 12%));
|
package/src/css/tokens.css
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
:root {
|
|
2
|
+
/*
|
|
3
|
+
* Global framework tokens.
|
|
4
|
+
*
|
|
5
|
+
* Public: properties in the named groups below are public API (typography,
|
|
6
|
+
* spacing, shape, motion, focus, controls, viewport, z-index, icons) unless
|
|
7
|
+
* a group is explicitly marked Internal or Derived.
|
|
8
|
+
*
|
|
9
|
+
* Derived: "Theme-derived aliases" and "State tokens" reference intent and
|
|
10
|
+
* surface tokens and follow the theme; do not hard-code values into them.
|
|
11
|
+
* Internal: indicator offsets, --bar-height, --disabled-opacity and the
|
|
12
|
+
* like are consumed by components, not authored.
|
|
13
|
+
*
|
|
14
|
+
* Component-local hooks and internal state relays live with their
|
|
15
|
+
* components. See docs/pages/foundations/tokens.md for the public/internal
|
|
16
|
+
* token contract.
|
|
17
|
+
*/
|
|
18
|
+
|
|
2
19
|
/* Typography */
|
|
3
20
|
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
4
21
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
@@ -16,20 +33,22 @@
|
|
|
16
33
|
--font-size-md: 1rem;
|
|
17
34
|
--font-size-lg: 1.125rem;
|
|
18
35
|
|
|
19
|
-
/* Spacing
|
|
36
|
+
/* Spacing — official steps are named in tens so the scale stays open for
|
|
37
|
+
application themes to intercalate intermediate values (--space-15,
|
|
38
|
+
--space-45…) without colliding with future framework steps. */
|
|
20
39
|
--gap: 0.75rem;
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
-
--space-
|
|
24
|
-
--space-
|
|
25
|
-
--space-
|
|
26
|
-
--space-
|
|
27
|
-
--space-
|
|
40
|
+
--density-space: var(--space-40);
|
|
41
|
+
--density-compact-size: 1.5rem;
|
|
42
|
+
--space-10: 0.25rem;
|
|
43
|
+
--space-20: 0.5rem;
|
|
44
|
+
--space-30: 0.75rem;
|
|
45
|
+
--space-40: 1rem;
|
|
46
|
+
--space-50: 1.5rem;
|
|
47
|
+
--space-60: 2rem;
|
|
28
48
|
|
|
29
49
|
/* Shape */
|
|
30
50
|
--border-width: 1px;
|
|
31
51
|
--radius-full: 9999px;
|
|
32
|
-
--shadow-xs: 0 1px 2px rgb(0 0 0 / 0.04);
|
|
33
52
|
--shadow: 0 1px 3px rgb(0 0 0 / 0.05), 0 4px 12px rgb(0 0 0 / 0.04);
|
|
34
53
|
--shadow-popout: 0 0.25rem 0.75rem rgb(0 0 0 / 0.15);
|
|
35
54
|
|
|
@@ -53,7 +72,6 @@
|
|
|
53
72
|
the circle-aware inset (1 - 1/√2) / 2 ≈ 14.65%; the ring surrounds the
|
|
54
73
|
dot with the parent surface color. */
|
|
55
74
|
--indicator-offset: 14.65%;
|
|
56
|
-
--indicator-ring: var(--surface);
|
|
57
75
|
|
|
58
76
|
/* Shared backdrop — consumed by modal, drawer, and mobile flyout sheets. */
|
|
59
77
|
--backdrop-color: rgb(0 0 0);
|
|
@@ -64,7 +82,8 @@
|
|
|
64
82
|
--bar-height: 0.65rem;
|
|
65
83
|
|
|
66
84
|
/* Controls — inputs and buttons share --control-size so heights always match.
|
|
67
|
-
.sm/.lg (variants.css) switch --control-size
|
|
85
|
+
.sm/.lg (variants.css) switch --control-size; --control-font-size stays
|
|
86
|
+
at its baseline because density does not change typography. */
|
|
68
87
|
--control-size-sm: 2rem;
|
|
69
88
|
--control-size-md: 2.375rem;
|
|
70
89
|
--control-size-lg: 2.75rem;
|
|
@@ -72,19 +91,38 @@
|
|
|
72
91
|
--control-pad-x: 1em;
|
|
73
92
|
--control-font-size: var(--font-size-md);
|
|
74
93
|
--disabled-opacity: 0.65;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* Theme-derived aliases. These reference intent/surface tokens, so they must
|
|
97
|
+
be re-declared on every theme boundary: a custom property resolves its
|
|
98
|
+
var() references at computed-value time on the element that declares it,
|
|
99
|
+
so an alias declared only on :root is inherited as an already-resolved
|
|
100
|
+
value and would not follow a [data-theme] island's overridden tokens.
|
|
101
|
+
Themes that want a distinct alias override it explicitly afterwards. */
|
|
102
|
+
:root,
|
|
103
|
+
[data-theme] {
|
|
104
|
+
/* State tokens — semantic colors for selected/pressed/current and disabled.
|
|
105
|
+
Components consume these instead of hard-wiring --primary/--text-subtle
|
|
106
|
+
so forced-colors can override them in one place. */
|
|
107
|
+
--state-selected: var(--primary);
|
|
108
|
+
--state-selected-fg: var(--primary-fg);
|
|
109
|
+
--state-disabled: var(--text-subtle);
|
|
110
|
+
|
|
111
|
+
/* Status dot ring — follows the island's surface. */
|
|
112
|
+
--indicator-ring: var(--surface);
|
|
113
|
+
}
|
|
75
114
|
|
|
115
|
+
:root {
|
|
76
116
|
/* Variant tuning — themes may adjust generated soft surfaces without
|
|
77
117
|
replacing the component rules. */
|
|
78
118
|
--soft-bg-mix: 88%;
|
|
79
119
|
--soft-border-mix: 65%;
|
|
80
120
|
--soft-hover-alpha: 12%;
|
|
81
121
|
|
|
82
|
-
/* Shared
|
|
83
|
-
--icon-chevron
|
|
84
|
-
--icon-check
|
|
85
|
-
|
|
86
|
-
The stroke matches the default theme's text-subtle (hue 258 neutral). */
|
|
87
|
-
--icon-chevron-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%238a8594' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
|
|
122
|
+
/* Shared icon assets. Override these URLs when a strict CSP disallows data:. */
|
|
123
|
+
--icon-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%238a8594' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
|
|
124
|
+
--icon-check: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E");
|
|
125
|
+
--icon-close: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='6' y1='6' x2='18' y2='18'/%3E%3Cline x1='18' y1='6' x2='6' y2='18'/%3E%3C/svg%3E");
|
|
88
126
|
|
|
89
127
|
/* Viewport size tokens — fallback vh/vw with dvh/vi enhancement.
|
|
90
128
|
Consumed by full-viewport components (app-shell, drawer, modal, flyout).
|
|
@@ -93,13 +131,24 @@
|
|
|
93
131
|
--viewport-block: 100vh;
|
|
94
132
|
--viewport-inline: 100vw;
|
|
95
133
|
|
|
96
|
-
/*
|
|
134
|
+
/* Z-index scale — used ONLY by non-dialog overlays (see the layering
|
|
135
|
+
note below for the full model). Actual CSS reserves multiples of 10 for
|
|
136
|
+
framework layers; applications may use intermediate values for local
|
|
137
|
+
layering. */
|
|
97
138
|
--z-sticky: 10;
|
|
98
139
|
--z-menu: 20;
|
|
99
140
|
--z-tooltip: 50;
|
|
100
141
|
--z-status: 60;
|
|
101
142
|
}
|
|
102
143
|
|
|
144
|
+
@media (forced-colors: active) {
|
|
145
|
+
:root {
|
|
146
|
+
--state-selected: Highlight;
|
|
147
|
+
--state-selected-fg: HighlightText;
|
|
148
|
+
--state-disabled: GrayText;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
103
152
|
@supports (block-size: 100dvh) {
|
|
104
153
|
:root {
|
|
105
154
|
--viewport-block: 100dvh;
|
|
@@ -113,12 +162,17 @@
|
|
|
113
162
|
}
|
|
114
163
|
|
|
115
164
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
116
|
-
:root
|
|
117
|
-
|
|
165
|
+
:root,
|
|
166
|
+
[data-theme] {
|
|
167
|
+
/* Shadows derive from --shadow-color (theme.css) — re-declared on every
|
|
168
|
+
theme boundary so islands follow their own shadow-color. */
|
|
118
169
|
--shadow:
|
|
119
170
|
0 1px 3px color-mix(in oklch, var(--shadow-color) 5%, transparent),
|
|
120
171
|
0 4px 12px color-mix(in oklch, var(--shadow-color) 4%, transparent);
|
|
121
172
|
--shadow-popout: 0 0.25rem 0.75rem color-mix(in oklch, var(--shadow-color) 15%, transparent);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:root {
|
|
122
176
|
--backdrop-fill: color-mix(
|
|
123
177
|
in oklch,
|
|
124
178
|
var(--backdrop-color) calc(var(--backdrop-opacity) * 100%),
|
package/src/css/utilities.css
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
min-inline-size: 0;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
.nowrap {
|
|
33
|
+
.text-nowrap {
|
|
34
34
|
white-space: nowrap;
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -125,15 +125,13 @@
|
|
|
125
125
|
text-decoration: none;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
color: var(--text);
|
|
131
|
-
}
|
|
128
|
+
.link-muted:hover {
|
|
129
|
+
color: var(--text);
|
|
132
130
|
}
|
|
133
131
|
|
|
134
132
|
/* Spacing step helpers — semantic scale (sm / default / lg).
|
|
135
133
|
Names map to logical properties for writing-direction safety. The default
|
|
136
|
-
step uses --space-
|
|
134
|
+
step uses --space-40, which matches the framework's built-in padding on
|
|
137
135
|
cards, dialogs, and form-actions. */
|
|
138
136
|
|
|
139
137
|
/* Gap */
|
|
@@ -143,20 +141,20 @@
|
|
|
143
141
|
|
|
144
142
|
/* Padding — block (vertical) */
|
|
145
143
|
.py {
|
|
146
|
-
padding-block: var(--
|
|
144
|
+
padding-block: var(--density-space);
|
|
147
145
|
}
|
|
148
146
|
|
|
149
147
|
/* Padding — inline (horizontal) */
|
|
150
148
|
.px {
|
|
151
|
-
padding-inline: var(--
|
|
149
|
+
padding-inline: var(--density-space);
|
|
152
150
|
}
|
|
153
151
|
|
|
154
152
|
/* Margin — block-start */
|
|
155
153
|
.mbs {
|
|
156
|
-
margin-block-start: var(--
|
|
154
|
+
margin-block-start: var(--density-space);
|
|
157
155
|
}
|
|
158
156
|
|
|
159
157
|
/* Margin — block-end */
|
|
160
158
|
.mbe {
|
|
161
|
-
margin-block-end: var(--
|
|
159
|
+
margin-block-end: var(--density-space);
|
|
162
160
|
}
|
package/src/css/variants.css
CHANGED
|
@@ -2,15 +2,24 @@
|
|
|
2
2
|
* Cross-cutting variant token mapping.
|
|
3
3
|
*
|
|
4
4
|
* Variant scope: .solid/.soft/.outline set --ui-* for components that opt into
|
|
5
|
-
* shared variants.
|
|
6
|
-
*
|
|
5
|
+
* shared variants. .inverted is a surface modifier, not a variant: it paints
|
|
6
|
+
* the element directly (background/color/border-color) so it works on any bare
|
|
7
|
+
* block, and remaps the shared --ui-* tokens so participating components
|
|
8
|
+
* (.card, .navbar, .alert, .badge) invert through their own rules. Loaded
|
|
9
|
+
* before components, so a component with its own explicit surface (e.g.
|
|
10
|
+
* .accordion) naturally keeps that surface — .inverted never forces a
|
|
11
|
+
* non-participant.
|
|
12
|
+
* Component-specific defaults (.btn solid-by-default, .badge
|
|
13
|
+
* soft-by-default, .alert soft-by-default) live with their components:
|
|
7
14
|
* components/button.css — .btn default solid + .btn.ghost + .btn.link
|
|
8
|
-
* components/badge.css — .badge default
|
|
9
|
-
* components/alert.css — .alert default
|
|
15
|
+
* components/badge.css — .badge default soft behind explicit --ui-*
|
|
16
|
+
* components/alert.css — .alert default soft behind explicit --ui-*
|
|
10
17
|
*
|
|
11
|
-
* .sm/.lg set shared
|
|
12
|
-
*
|
|
13
|
-
*
|
|
18
|
+
* .sm/.lg set shared density tokens: spacing rhythm and geometry only.
|
|
19
|
+
* Density never changes typography — controls keep their font-size and
|
|
20
|
+
* content components keep theirs. Controls consume --control-size; non-control
|
|
21
|
+
* components may consume --density-* when the density context should affect
|
|
22
|
+
* their local rhythm. Compact components may consume --density-compact-size.
|
|
14
23
|
* Components with bespoke sizing (spinner, avatar) define local .sm/.lg;
|
|
15
24
|
* applying .sm/.lg to card, dialog, accordion, navbar, table is
|
|
16
25
|
* a no-op.
|
|
@@ -32,31 +41,43 @@
|
|
|
32
41
|
|
|
33
42
|
.outline {
|
|
34
43
|
--ui-bg: transparent;
|
|
35
|
-
--ui-fg: var(--intent,
|
|
36
|
-
--ui-border: var(--intent,
|
|
44
|
+
--ui-fg: var(--intent, currentColor);
|
|
45
|
+
--ui-border: var(--intent, currentColor);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Inverse surface treatment. Paints the element directly (so it works on any
|
|
49
|
+
bare block) and remaps the shared --ui-* tokens so opt-in components
|
|
50
|
+
(.card, .navbar) invert through their own rules. Because this loads before
|
|
51
|
+
component base surfaces, components with their own explicit surface
|
|
52
|
+
(e.g. .accordion) keep it — participation is opt-in, never forced. --heading
|
|
53
|
+
is set so global headings (var(--heading, inherit)) do not inherit an outside
|
|
54
|
+
heading color onto the dark surface; surface-owning descendants derive
|
|
55
|
+
their contextual aliases from their own local surface. */
|
|
56
|
+
.inverted {
|
|
57
|
+
--ui-bg: var(--surface-solid);
|
|
58
|
+
--ui-fg: var(--surface);
|
|
59
|
+
--ui-border: transparent;
|
|
60
|
+
--ui-hover-bg: var(--surface-solid);
|
|
61
|
+
|
|
62
|
+
--heading: var(--surface);
|
|
63
|
+
--busy-overlay-bg: var(--surface-solid);
|
|
64
|
+
|
|
65
|
+
background: var(--ui-bg);
|
|
66
|
+
color: var(--ui-fg);
|
|
67
|
+
border-color: var(--ui-border);
|
|
37
68
|
}
|
|
38
69
|
|
|
39
70
|
.sm {
|
|
40
|
-
--gap: var(--space-
|
|
41
|
-
--
|
|
71
|
+
--gap: var(--space-20);
|
|
72
|
+
--density-space: var(--space-20);
|
|
42
73
|
--control-size: var(--control-size-sm);
|
|
43
|
-
--
|
|
44
|
-
--variant-font-size: var(--font-size-sm);
|
|
45
|
-
--variant-icon-size: 1rem;
|
|
46
|
-
--variant-pad-block: var(--space-3);
|
|
47
|
-
--variant-compact-size: 1.25rem;
|
|
48
|
-
--variant-compact-font-size: 0.75rem;
|
|
74
|
+
--density-compact-size: 1.25rem;
|
|
49
75
|
}
|
|
50
76
|
.lg {
|
|
51
|
-
--gap: var(--space-
|
|
52
|
-
--
|
|
77
|
+
--gap: var(--space-50);
|
|
78
|
+
--density-space: var(--space-50);
|
|
53
79
|
--control-size: var(--control-size-lg);
|
|
54
|
-
--
|
|
55
|
-
--variant-font-size: var(--font-size-lg);
|
|
56
|
-
--variant-icon-size: 1.5rem;
|
|
57
|
-
--variant-pad-block: var(--space-5);
|
|
58
|
-
--variant-compact-size: 1.875rem;
|
|
59
|
-
--variant-compact-font-size: var(--font-size-sm);
|
|
80
|
+
--density-compact-size: 1.875rem;
|
|
60
81
|
}
|
|
61
82
|
|
|
62
83
|
/* Modern color enhancement. Baseline variant values above remain usable
|
|
@@ -72,47 +93,11 @@
|
|
|
72
93
|
);
|
|
73
94
|
/* @sync soft-recipe */
|
|
74
95
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/* Interactive hover recipe shared by .btn and .badge. Declared outside :hover
|
|
78
|
-
on purpose: --ui-hover-bg is only consumed inside their @media (hover: hover)
|
|
79
|
-
rules, so these values are inert until hovered. :is() carries real
|
|
80
|
-
specificity so the components' :where() intent boundaries
|
|
81
|
-
(--ui-hover-bg: initial) cannot override the recipe. The solid/soft overlay
|
|
82
|
-
darkening lives in the consuming components. */
|
|
83
|
-
:is(.btn, a.badge, button.badge):is(.outline, .ghost) {
|
|
84
|
-
--ui-hover-bg: var(--surface-subtle);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
@supports (color: color-mix(in oklch, red, white)) {
|
|
88
|
-
/* Solid has no literal class requirement: bare .btn/.badge default to solid,
|
|
89
|
-
so this must match anything that isn't one of the other variants rather
|
|
90
|
-
than an explicit .solid class. Stacks with the box-shadow overlay the
|
|
91
|
-
consuming components apply on top for extra depth. */
|
|
92
|
-
:is(.btn, a.badge, button.badge):not(:where(.soft, .outline, .ghost, .link)) {
|
|
93
|
-
--ui-hover-bg: color-mix(in oklch, var(--intent, var(--neutral)) 88%, black);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/* Same recipe as the resting .soft bg with the surface share reduced by
|
|
97
|
-
--soft-hover-alpha: stays opaque, so it reads on any backdrop instead of
|
|
98
|
-
letting the container show through on hover. */
|
|
99
|
-
:is(.btn, a.badge, button.badge):is(.soft) {
|
|
100
|
-
--ui-hover-bg: color-mix(
|
|
101
|
-
in oklch,
|
|
102
|
-
var(--surface) calc(var(--soft-bg-mix) - var(--soft-hover-alpha)),
|
|
103
|
-
var(--intent, var(--neutral))
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
96
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
low-contrast on dark ones, since the same low alpha lands very
|
|
110
|
-
differently over a light vs. a near-black backdrop. */
|
|
111
|
-
:is(.btn, a.badge, button.badge):is(.outline) {
|
|
112
|
-
--ui-hover-bg: color-mix(in oklch, var(--surface-subtle) 92%, var(--intent, var(--neutral)));
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
:is(.btn, a.badge, button.badge):is(.ghost) {
|
|
116
|
-
--ui-hover-bg: color-mix(in oklch, var(--intent, var(--text)) 8%, transparent);
|
|
97
|
+
.inverted {
|
|
98
|
+
--ui-hover-bg: color-mix(in oklch, var(--surface-solid) 88%, black);
|
|
117
99
|
}
|
|
118
100
|
}
|
|
101
|
+
|
|
102
|
+
/* Interactive hover recipes live in the components that consume them:
|
|
103
|
+
components/button.css and components/badge.css. */
|
package/src/js/command.js
CHANGED
|
@@ -25,9 +25,7 @@ function commandNames(commands, caller) {
|
|
|
25
25
|
// Native command keywords are ASCII case-insensitive. Custom commands keep
|
|
26
26
|
// their exact spelling, as required by the command invoker contract.
|
|
27
27
|
function commandKey(command) {
|
|
28
|
-
return command.startsWith("--")
|
|
29
|
-
? command
|
|
30
|
-
: command.replace(/[A-Z]/g, (character) => character.toLowerCase());
|
|
28
|
+
return command.startsWith("--") ? command : command.toLowerCase();
|
|
31
29
|
}
|
|
32
30
|
|
|
33
31
|
/**
|