actual-css 0.1.0 → 0.3.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 +90 -1
- package/README.md +25 -8
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1492 -931
- 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 +95 -6
- package/docs/design-notes/cascade-layer.md +1 -1
- package/docs/design-notes/enhancement-contract.md +101 -0
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +3 -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 +119 -0
- 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 +205 -0
- package/docs/pages/components/card.md +183 -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 +41 -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 +92 -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 +57 -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 +21 -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 +18 -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 +31 -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 +10 -4
- package/package.json +30 -16
- package/src/css/actual.css +12 -1
- package/src/css/base.css +3 -9
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +162 -49
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +82 -39
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +7 -0
- package/src/css/components/button.css +82 -38
- package/src/css/components/card.css +17 -37
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -110
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -3
- 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 +17 -18
- package/src/css/components/overline.css +0 -7
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/scrollspy.css +2 -2
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +10 -11
- package/src/css/components/status-bar.css +18 -28
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +20 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +16 -3
- package/src/css/forms/choice-card.css +13 -15
- package/src/css/forms/choice.css +21 -28
- package/src/css/forms/control.css +16 -26
- 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 +5 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +48 -33
- package/src/css/forms/range.css +103 -0
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -13
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +19 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +29 -1
- 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 +19 -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 +29 -13
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +11 -37
- package/src/css/themes/index.css +3 -3
- 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 +81 -21
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +37 -65
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +72 -53
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +76 -19
- 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 +106 -96
- 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 +89 -35
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +133 -62
- package/src/js/selectors.js +14 -31
- package/src/js/status.js +16 -14
- package/src/js/surface.js +219 -125
- package/src/js/tab.js +46 -66
- package/src/js/tooltip.js +53 -31
- package/src/js/validation.js +45 -51
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -26
- 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 -426
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -415
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -937
- 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
|
}
|
|
@@ -61,11 +72,10 @@
|
|
|
61
72
|
|
|
62
73
|
/* Lines and focus */
|
|
63
74
|
--border: hsl(260 15% 88%);
|
|
64
|
-
--focus: var(--
|
|
75
|
+
--focus: var(--neutral);
|
|
65
76
|
/* Pre-color-mix fallback only — superseded below by a derivation from
|
|
66
|
-
--focus so overriding --
|
|
67
|
-
--focus-ring: hsl(
|
|
68
|
-
--focus-ring-shadow: 0 0 0 3px var(--focus-ring);
|
|
77
|
+
--focus so overriding --neutral/--focus never leaves a stale ring. */
|
|
78
|
+
--focus-ring: hsl(258 7% 43% / 0.3);
|
|
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
|
|
@@ -106,7 +122,7 @@
|
|
|
106
122
|
:root,
|
|
107
123
|
[data-theme="light"],
|
|
108
124
|
[data-theme="dark"] {
|
|
109
|
-
--focus-ring: color-mix(in oklch, var(--focus)
|
|
125
|
+
--focus-ring: color-mix(in oklch, var(--focus) 30%, transparent);
|
|
110
126
|
}
|
|
111
127
|
}
|
|
112
128
|
|
|
@@ -146,7 +162,7 @@
|
|
|
146
162
|
--text-subtle: light-dark(hsl(258 7% 57%), hsl(258 7% 54%));
|
|
147
163
|
|
|
148
164
|
--border: light-dark(hsl(260 15% 88%), hsl(262 12% 24%));
|
|
149
|
-
--focus-ring: light-dark(hsl(
|
|
165
|
+
--focus-ring: light-dark(hsl(258 7% 43% / 0.3), hsl(258 10% 72% / 0.28));
|
|
150
166
|
--hover-overlay: light-dark(hsl(260 20% 10% / 0.04), hsl(0 0% 100% / 0.06));
|
|
151
167
|
--shadow-color: light-dark(hsl(260 25% 10%), hsl(262 40% 2%));
|
|
152
168
|
}
|
|
@@ -156,7 +172,7 @@
|
|
|
156
172
|
:root,
|
|
157
173
|
[data-theme="light"] {
|
|
158
174
|
--focus-ring: light-dark(
|
|
159
|
-
color-mix(in oklch, var(--focus)
|
|
175
|
+
color-mix(in oklch, var(--focus) 30%, transparent),
|
|
160
176
|
color-mix(in oklch, var(--focus) 28%, transparent)
|
|
161
177
|
);
|
|
162
178
|
}
|
|
@@ -166,7 +182,7 @@
|
|
|
166
182
|
:root,
|
|
167
183
|
[data-theme="light"],
|
|
168
184
|
[data-theme="dark"] {
|
|
169
|
-
--focus-outline:
|
|
185
|
+
--focus-outline-color: Highlight;
|
|
170
186
|
--focus-ring-shadow: none;
|
|
171
187
|
|
|
172
188
|
--backdrop-fill: Canvas;
|
|
@@ -179,7 +195,7 @@
|
|
|
179
195
|
[data-theme="dark"] {
|
|
180
196
|
--border-width: 2px;
|
|
181
197
|
--focus-outline-offset: 3px;
|
|
182
|
-
--focus-ring-
|
|
198
|
+
--focus-ring-width: 4px;
|
|
183
199
|
--text-muted: var(--text);
|
|
184
200
|
--text-subtle: var(--text);
|
|
185
201
|
}
|
|
@@ -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:
|
|
@@ -79,38 +77,14 @@
|
|
|
79
77
|
}
|
|
80
78
|
|
|
81
79
|
/* Focus recipe override — the base recipe (control.css) flips --control-border
|
|
82
|
-
to --focus
|
|
83
|
-
|
|
84
|
-
the
|
|
80
|
+
to --focus and draws a box-shadow ring. Edge drops the border-color flip and
|
|
81
|
+
thickens the accent edge instead so the intent-coloured lower edge stays
|
|
82
|
+
dominant; the focus ring and its 3px width remain the same as the default. */
|
|
85
83
|
[data-theme="edge"] :is(.input, .textarea, .select):focus-visible {
|
|
86
84
|
--control-border: var(--border);
|
|
87
85
|
--control-border-block-end-width: 3px;
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
/* The shared 2px-solid/2px-offset outline reads as a second ring on top of
|
|
91
|
-
the accent edge (inputs) or the box-shadow ring (buttons). Edge thins both
|
|
92
|
-
to the border width and tightens the offset so the outline hugs the
|
|
93
|
-
control instead of floating a second halo around it. Gated outside
|
|
94
|
-
forced-colors so that mode's Highlight-colored --focus-outline (theme.css)
|
|
95
|
-
stays in charge for inputs — a direct property on the element would
|
|
96
|
-
otherwise out-specificity that fallback regardless of the media condition
|
|
97
|
-
it was declared under. Buttons don't consume --focus-outline (they compute
|
|
98
|
-
their own outline so it can use --btn-focus-color's intent awareness), so
|
|
99
|
-
they get their own local width token, --btn-focus-outline-width. */
|
|
100
|
-
@media not (forced-colors: active) {
|
|
101
|
-
[data-theme="edge"] :is(.input, .textarea, .select, .btn) {
|
|
102
|
-
--focus-outline-offset: 1px;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
[data-theme="edge"] :is(.input, .textarea, .select) {
|
|
106
|
-
--focus-outline: var(--border-width) solid var(--focus);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
[data-theme="edge"] .btn {
|
|
110
|
-
--btn-focus-outline-width: var(--border-width);
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
88
|
@supports (color: light-dark(red, blue)) {
|
|
115
89
|
[data-theme="edge"] {
|
|
116
90
|
--primary: light-dark(hsl(224 72% 42%), hsl(220 80% 76%));
|
package/src/css/themes/index.css
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* The themes are illustrative: each one demonstrates a different set of knobs
|
|
6
6
|
* the token contract exposes, beyond recoloring.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
8
|
+
* indigo — deep blue/violet dark palette (single block)
|
|
9
9
|
* dim — dark variant with lifted surface tones
|
|
10
10
|
* corporate — reference paired light/dark recolor via light-dark()
|
|
11
11
|
* forest — paired recolor + scaled-up radius tokens
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
* gradient — paired recolor + Bootstrap 4 style gradient on solid buttons
|
|
25
25
|
* via component-local button tokens
|
|
26
26
|
*
|
|
27
|
-
* Single-block themes (
|
|
27
|
+
* Single-block themes (indigo, dim, cyberpunk, neon) pin one color-scheme and
|
|
28
28
|
* cannot adapt to prefers-color-scheme; the paired ones follow the OS. */
|
|
29
|
-
@import "./
|
|
29
|
+
@import "./indigo.css";
|
|
30
30
|
@import "./dim.css";
|
|
31
31
|
@import "./corporate.css";
|
|
32
32
|
@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,23 @@
|
|
|
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: 0 0
|
|
52
|
+
--shadow: 0 1px 3px rgb(0 0 0 / 0.05), 0 4px 12px rgb(0 0 0 / 0.04);
|
|
33
53
|
--shadow-popout: 0 0.25rem 0.75rem rgb(0 0 0 / 0.15);
|
|
34
54
|
|
|
35
55
|
/* Motion — see reset.css for the prefers-reduced-motion hard reset.
|
|
@@ -43,14 +63,15 @@
|
|
|
43
63
|
--ease: ease;
|
|
44
64
|
|
|
45
65
|
/* Focus ring — shared by every interactive component's :focus-visible */
|
|
46
|
-
--focus-outline:
|
|
66
|
+
--focus-outline-color: currentColor;
|
|
67
|
+
--focus-outline: calc(var(--border-width) * 2) solid var(--focus-outline-color);
|
|
47
68
|
--focus-outline-offset: 2px;
|
|
69
|
+
--focus-ring-width: 3px;
|
|
48
70
|
|
|
49
71
|
/* Status dot positioning — used by .avatar > .badge:empty. The offset is
|
|
50
72
|
the circle-aware inset (1 - 1/√2) / 2 ≈ 14.65%; the ring surrounds the
|
|
51
73
|
dot with the parent surface color. */
|
|
52
74
|
--indicator-offset: 14.65%;
|
|
53
|
-
--indicator-ring: var(--surface);
|
|
54
75
|
|
|
55
76
|
/* Shared backdrop — consumed by modal, drawer, and mobile flyout sheets. */
|
|
56
77
|
--backdrop-color: rgb(0 0 0);
|
|
@@ -61,7 +82,8 @@
|
|
|
61
82
|
--bar-height: 0.65rem;
|
|
62
83
|
|
|
63
84
|
/* Controls — inputs and buttons share --control-size so heights always match.
|
|
64
|
-
.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. */
|
|
65
87
|
--control-size-sm: 2rem;
|
|
66
88
|
--control-size-md: 2.375rem;
|
|
67
89
|
--control-size-lg: 2.75rem;
|
|
@@ -69,19 +91,38 @@
|
|
|
69
91
|
--control-pad-x: 1em;
|
|
70
92
|
--control-font-size: var(--font-size-md);
|
|
71
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
|
+
}
|
|
72
114
|
|
|
115
|
+
:root {
|
|
73
116
|
/* Variant tuning — themes may adjust generated soft surfaces without
|
|
74
117
|
replacing the component rules. */
|
|
75
118
|
--soft-bg-mix: 88%;
|
|
76
119
|
--soft-border-mix: 65%;
|
|
77
120
|
--soft-hover-alpha: 12%;
|
|
78
121
|
|
|
79
|
-
/* Shared
|
|
80
|
-
--icon-chevron
|
|
81
|
-
--icon-check
|
|
82
|
-
|
|
83
|
-
The stroke matches the default theme's text-subtle (hue 258 neutral). */
|
|
84
|
-
--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");
|
|
85
126
|
|
|
86
127
|
/* Viewport size tokens — fallback vh/vw with dvh/vi enhancement.
|
|
87
128
|
Consumed by full-viewport components (app-shell, drawer, modal, flyout).
|
|
@@ -90,13 +131,24 @@
|
|
|
90
131
|
--viewport-block: 100vh;
|
|
91
132
|
--viewport-inline: 100vw;
|
|
92
133
|
|
|
93
|
-
/*
|
|
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. */
|
|
94
138
|
--z-sticky: 10;
|
|
95
139
|
--z-menu: 20;
|
|
96
140
|
--z-tooltip: 50;
|
|
97
141
|
--z-status: 60;
|
|
98
142
|
}
|
|
99
143
|
|
|
144
|
+
@media (forced-colors: active) {
|
|
145
|
+
:root {
|
|
146
|
+
--state-selected: Highlight;
|
|
147
|
+
--state-selected-fg: HighlightText;
|
|
148
|
+
--state-disabled: GrayText;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
100
152
|
@supports (block-size: 100dvh) {
|
|
101
153
|
:root {
|
|
102
154
|
--viewport-block: 100dvh;
|
|
@@ -110,9 +162,17 @@
|
|
|
110
162
|
}
|
|
111
163
|
|
|
112
164
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
113
|
-
:root
|
|
114
|
-
|
|
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. */
|
|
169
|
+
--shadow:
|
|
170
|
+
0 1px 3px color-mix(in oklch, var(--shadow-color) 5%, transparent),
|
|
171
|
+
0 4px 12px color-mix(in oklch, var(--shadow-color) 4%, transparent);
|
|
115
172
|
--shadow-popout: 0 0.25rem 0.75rem color-mix(in oklch, var(--shadow-color) 15%, transparent);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:root {
|
|
116
176
|
--backdrop-fill: color-mix(
|
|
117
177
|
in oklch,
|
|
118
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,20 @@
|
|
|
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 also
|
|
6
|
+
* paints the element directly (background/color/border-color) so it works on
|
|
7
|
+
* any block, competing with component surface treatments (.card.subtle).
|
|
8
|
+
* Component-specific defaults (.btn solid-by-default, .badge
|
|
9
|
+
* soft-by-default, .alert soft-by-default) live with their components:
|
|
7
10
|
* components/button.css — .btn default solid + .btn.ghost + .btn.link
|
|
8
|
-
* components/badge.css — .badge default
|
|
9
|
-
* components/alert.css — .alert default
|
|
11
|
+
* components/badge.css — .badge default soft
|
|
12
|
+
* components/alert.css — .alert default soft (consumes --ui-* directly)
|
|
10
13
|
*
|
|
11
|
-
* .sm/.lg set shared
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
+
* .sm/.lg set shared density tokens: spacing rhythm and geometry only.
|
|
15
|
+
* Density never changes typography — controls keep their font-size and
|
|
16
|
+
* content components keep theirs. Controls consume --control-size; non-control
|
|
17
|
+
* components may consume --density-* when the density context should affect
|
|
18
|
+
* their local rhythm. Compact components may consume --density-compact-size.
|
|
14
19
|
* Components with bespoke sizing (spinner, avatar) define local .sm/.lg;
|
|
15
20
|
* applying .sm/.lg to card, dialog, accordion, navbar, table is
|
|
16
21
|
* a no-op.
|
|
@@ -36,27 +41,34 @@
|
|
|
36
41
|
--ui-border: var(--intent, var(--border));
|
|
37
42
|
}
|
|
38
43
|
|
|
44
|
+
/* Inverse surface treatment. Components (e.g. .card) compose through --ui-*;
|
|
45
|
+
the direct background/color/border-color also make .inverted useful on a
|
|
46
|
+
generic element. --heading is set so global headings (var(--heading, inherit))
|
|
47
|
+
do not inherit an outside heading color onto the dark surface. */
|
|
48
|
+
.inverted {
|
|
49
|
+
--ui-bg: var(--surface-solid);
|
|
50
|
+
--ui-fg: var(--surface);
|
|
51
|
+
--ui-border: transparent;
|
|
52
|
+
|
|
53
|
+
--heading: var(--surface);
|
|
54
|
+
--busy-overlay-bg: var(--surface-solid);
|
|
55
|
+
|
|
56
|
+
background: var(--ui-bg);
|
|
57
|
+
color: var(--ui-fg);
|
|
58
|
+
border-color: var(--ui-border);
|
|
59
|
+
}
|
|
60
|
+
|
|
39
61
|
.sm {
|
|
40
|
-
--gap: var(--space-
|
|
41
|
-
--
|
|
62
|
+
--gap: var(--space-20);
|
|
63
|
+
--density-space: var(--space-20);
|
|
42
64
|
--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;
|
|
65
|
+
--density-compact-size: 1.25rem;
|
|
49
66
|
}
|
|
50
67
|
.lg {
|
|
51
|
-
--gap: var(--space-
|
|
52
|
-
--
|
|
68
|
+
--gap: var(--space-50);
|
|
69
|
+
--density-space: var(--space-50);
|
|
53
70
|
--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);
|
|
71
|
+
--density-compact-size: 1.875rem;
|
|
60
72
|
}
|
|
61
73
|
|
|
62
74
|
/* Modern color enhancement. Baseline variant values above remain usable
|
|
@@ -74,45 +86,5 @@
|
|
|
74
86
|
}
|
|
75
87
|
}
|
|
76
88
|
|
|
77
|
-
/* Interactive hover
|
|
78
|
-
|
|
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
|
-
|
|
107
|
-
/* Mixed against the opaque --surface-subtle rather than transparent: a
|
|
108
|
-
transparent-based tint reads clean on light surfaces but goes muddy and
|
|
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);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
89
|
+
/* Interactive hover recipes live in the components that consume them:
|
|
90
|
+
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
|
/**
|