actual-css 0.2.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 +38 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1244 -915
- 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 +1 -1
- 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 +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 +4 -4
- package/package.json +20 -12
- package/src/css/actual.css +12 -1
- 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 +126 -99
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +55 -35
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +78 -32
- package/src/css/components/card.css +17 -37
- 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 +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/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 +16 -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 +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 +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 +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 +74 -20
- 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 +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 +185 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +53 -31
- 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
|
@@ -1,36 +1,54 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Input Icon —
|
|
2
|
+
* Input Icon — decorative icon inside a relative wrapper, leading or trailing.
|
|
3
3
|
*
|
|
4
|
-
* Icon-library agnostic:
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* the
|
|
8
|
-
*
|
|
4
|
+
* Icon-library agnostic: detects position by DOM order. First child that is
|
|
5
|
+
* not .input = leading icon; icon after .input = trailing. The icon keeps a
|
|
6
|
+
* fixed size; density contexts shrink the control geometry around it, not
|
|
7
|
+
* the pictogram.
|
|
8
|
+
*
|
|
9
|
+
* Public hooks:
|
|
10
|
+
* --input-icon-size
|
|
9
11
|
*/
|
|
10
12
|
.input-icon {
|
|
11
|
-
--input-icon-size:
|
|
13
|
+
--input-icon-size: 1.25rem;
|
|
12
14
|
|
|
13
15
|
display: block;
|
|
14
16
|
position: relative;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
/* Icon — shared by leading and trailing */
|
|
20
|
+
.input-icon > :where(:not(.input)) {
|
|
18
21
|
position: absolute;
|
|
19
22
|
inset-block-start: 50%;
|
|
20
|
-
inset-inline-start: var(--space-3);
|
|
21
23
|
transform: translateY(-50%);
|
|
22
24
|
font-size: var(--input-icon-size);
|
|
23
25
|
color: var(--text-muted);
|
|
24
26
|
pointer-events: none;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/* Leading: icon is the first child */
|
|
30
|
+
.input-icon > :first-child:where(:not(.input)) {
|
|
31
|
+
inset-inline-start: var(--space-30);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Trailing: input is the first child, icon follows */
|
|
35
|
+
.input-icon > .input:first-child ~ :where(:not(.input)) {
|
|
36
|
+
inset-inline-end: var(--space-30);
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
/* font-size only sizes text-metric icons (webfont <i>, <span>). An inline
|
|
28
40
|
<svg> with just a viewBox ignores it, so give it explicit dimensions. */
|
|
29
|
-
.input-icon > svg:
|
|
41
|
+
.input-icon > svg:where(:not(.input)) {
|
|
30
42
|
inline-size: var(--input-icon-size);
|
|
31
43
|
block-size: var(--input-icon-size);
|
|
32
44
|
}
|
|
33
45
|
|
|
34
|
-
|
|
35
|
-
|
|
46
|
+
/* Leading: input gets start padding to clear the icon */
|
|
47
|
+
.input-icon > :first-child:where(:not(.input)) ~ .input {
|
|
48
|
+
padding-inline-start: calc(var(--space-30) * 2 + var(--input-icon-size));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* Trailing: input is first child and has a sibling → end padding */
|
|
52
|
+
.input-icon > .input:first-child:where(:not(:last-child)) {
|
|
53
|
+
padding-inline-end: calc(var(--space-30) * 2 + var(--input-icon-size));
|
|
36
54
|
}
|
package/src/css/forms/native.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Native-only control polish: file input
|
|
3
|
-
* so the framework stays out of the way and just keeps
|
|
4
|
-
* theme-aware.
|
|
2
|
+
* Native-only control polish: the file input and color picker mostly defeat
|
|
3
|
+
* custom styling, so the framework stays out of the way and just keeps them
|
|
4
|
+
* readable and theme-aware.
|
|
5
5
|
*
|
|
6
6
|
* Range has its own custom-styled file (range.css) so the focus ring can
|
|
7
7
|
* target the thumb pseudo-element rather than the rectangular CSS box.
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
.file::file-selector-button {
|
|
14
|
-
margin-inline-end: var(--space-
|
|
15
|
-
padding-block: var(--space-
|
|
16
|
-
padding-inline: var(--space-
|
|
14
|
+
margin-inline-end: var(--space-30);
|
|
15
|
+
padding-block: var(--space-10);
|
|
16
|
+
padding-inline: var(--space-20);
|
|
17
17
|
border: var(--border-width) solid var(--border);
|
|
18
18
|
border-radius: var(--radius-sm);
|
|
19
19
|
background: var(--surface-subtle);
|
|
@@ -32,13 +32,52 @@
|
|
|
32
32
|
cursor: not-allowed;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
background: var(--border);
|
|
38
|
-
}
|
|
35
|
+
.file:not(:disabled)::file-selector-button:hover {
|
|
36
|
+
background: var(--border);
|
|
39
37
|
}
|
|
40
38
|
|
|
41
39
|
.file:focus-visible {
|
|
42
|
-
outline:
|
|
40
|
+
outline: 2px solid transparent;
|
|
41
|
+
box-shadow: var(--focus-ring-shadow);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Native color picker — keep the browser's dialog and selected-color UI. */
|
|
45
|
+
.color {
|
|
46
|
+
inline-size: var(--control-size);
|
|
47
|
+
block-size: var(--control-size);
|
|
48
|
+
padding: var(--space-10);
|
|
49
|
+
border: var(--border-width) solid var(--border);
|
|
50
|
+
border-radius: var(--radius);
|
|
51
|
+
background: var(--surface);
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.color::-webkit-color-swatch-wrapper {
|
|
56
|
+
padding: 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.color::-webkit-color-swatch {
|
|
60
|
+
border: 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.color::-moz-color-swatch {
|
|
64
|
+
border: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.color:disabled {
|
|
68
|
+
cursor: not-allowed;
|
|
69
|
+
opacity: var(--disabled-opacity);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.color:focus-visible {
|
|
73
|
+
outline: 2px solid transparent;
|
|
43
74
|
box-shadow: var(--focus-ring-shadow);
|
|
44
75
|
}
|
|
76
|
+
|
|
77
|
+
@media (forced-colors: active) {
|
|
78
|
+
.color {
|
|
79
|
+
border-color: ButtonText;
|
|
80
|
+
background: ButtonFace;
|
|
81
|
+
forced-color-adjust: none;
|
|
82
|
+
}
|
|
83
|
+
}
|
package/src/css/forms/range.css
CHANGED
|
@@ -5,19 +5,18 @@
|
|
|
5
5
|
* appearance: none gives us full control over track and thumb; without it,
|
|
6
6
|
* pseudo-element rules for ::-webkit-slider-thumb and ::-moz-range-thumb
|
|
7
7
|
* are not reliably applied across browsers.
|
|
8
|
+
*
|
|
9
|
+
* Public hooks:
|
|
10
|
+
* --range-thumb-size
|
|
11
|
+
* --range-track-height
|
|
12
|
+
* --range-thumb-bg
|
|
13
|
+
* --range-track-bg
|
|
8
14
|
*/
|
|
9
15
|
|
|
10
16
|
/* Intent boundary — inherited intents do not tint this component.
|
|
11
17
|
Local intent classes still win because :where() has zero specificity. */
|
|
12
18
|
:where(.range) {
|
|
13
|
-
/* @sync intent-boundary */
|
|
14
19
|
--intent: initial;
|
|
15
|
-
--intent-fg: initial;
|
|
16
|
-
--ui-bg: initial;
|
|
17
|
-
--ui-fg: initial;
|
|
18
|
-
--ui-border: initial;
|
|
19
|
-
--ui-hover-bg: initial;
|
|
20
|
-
/* @sync intent-boundary */
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
.range {
|
|
@@ -68,7 +67,7 @@
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
.range:focus-visible {
|
|
71
|
-
outline:
|
|
70
|
+
outline: 2px solid transparent;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
/*
|
|
@@ -89,7 +88,16 @@
|
|
|
89
88
|
}
|
|
90
89
|
|
|
91
90
|
.range:disabled {
|
|
92
|
-
--range-thumb-bg: var(--
|
|
91
|
+
--range-thumb-bg: var(--state-disabled);
|
|
93
92
|
cursor: not-allowed;
|
|
94
93
|
opacity: var(--disabled-opacity);
|
|
95
94
|
}
|
|
95
|
+
|
|
96
|
+
/* Forced colors: map the custom thumb/track to system colors. The focus
|
|
97
|
+
indicator stays visible through the transparent outline on :focus-visible. */
|
|
98
|
+
@media (forced-colors: active) {
|
|
99
|
+
.range {
|
|
100
|
+
--range-thumb-bg: ButtonText;
|
|
101
|
+
--range-track-bg: Canvas;
|
|
102
|
+
}
|
|
103
|
+
}
|
package/src/css/forms/select.css
CHANGED
|
@@ -8,19 +8,19 @@
|
|
|
8
8
|
* custom-select.css can be opted out independently. Add .native to a specific
|
|
9
9
|
* select to opt out of the enhancement.
|
|
10
10
|
*/
|
|
11
|
-
.select:
|
|
11
|
+
.select:not([multiple], [size]:not([size="1"])) {
|
|
12
12
|
appearance: none;
|
|
13
|
-
padding-inline-end: calc(var(--space-
|
|
14
|
-
background-image: var(--icon-chevron
|
|
15
|
-
background-position: center right var(--space-
|
|
13
|
+
padding-inline-end: calc(var(--space-30) + var(--space-60));
|
|
14
|
+
background-image: var(--icon-chevron);
|
|
15
|
+
background-position: center right var(--space-30);
|
|
16
16
|
background-size: 1rem auto;
|
|
17
17
|
background-repeat: no-repeat;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/* The chevron sits on the inline-end side; flip it in RTL so it follows
|
|
21
21
|
the padding-inline-end space reserved for it. */
|
|
22
|
-
.select:
|
|
23
|
-
background-position: center left var(--space-
|
|
22
|
+
.select:not([multiple], [size]:not([size="1"])):dir(rtl) {
|
|
23
|
+
background-position: center left var(--space-30);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
/* Both forced-colors and prefers-contrast hand the arrow back to the
|
|
@@ -28,9 +28,9 @@
|
|
|
28
28
|
simpler than maintaining contrast variants, and native rendering already
|
|
29
29
|
matches whatever contrast mode the user picked. */
|
|
30
30
|
@media (forced-colors: active), (prefers-contrast: more) {
|
|
31
|
-
.select:
|
|
31
|
+
.select:not([multiple], [size]:not([size="1"])) {
|
|
32
32
|
appearance: auto;
|
|
33
33
|
background-image: none;
|
|
34
|
-
padding-inline-end: var(--space-
|
|
34
|
+
padding-inline-end: var(--space-30);
|
|
35
35
|
}
|
|
36
36
|
}
|
package/src/css/forms/switch.css
CHANGED
|
@@ -3,18 +3,22 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The switch remains an input control, not a decorative toggle. Checked, hover,
|
|
5
5
|
* focus-visible, and disabled states stay clear.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --switch-bg
|
|
9
|
+
* --switch-border
|
|
10
|
+
* --switch-knob
|
|
11
|
+
* --switch-width
|
|
12
|
+
* --switch-block-size
|
|
13
|
+
* --switch-knob-margin
|
|
14
|
+
* --switch-knob-size
|
|
15
|
+
* --switch-travel
|
|
6
16
|
*/
|
|
7
17
|
/* Intent boundary — inherited intents do not tint this component.
|
|
8
18
|
Local intent classes still win because :where() has zero specificity. */
|
|
9
19
|
:where(.switch) {
|
|
10
|
-
/* @sync intent-boundary */
|
|
11
20
|
--intent: initial;
|
|
12
21
|
--intent-fg: initial;
|
|
13
|
-
--ui-bg: initial;
|
|
14
|
-
--ui-fg: initial;
|
|
15
|
-
--ui-border: initial;
|
|
16
|
-
--ui-hover-bg: initial;
|
|
17
|
-
/* @sync intent-boundary */
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
.switch {
|
|
@@ -62,10 +66,8 @@
|
|
|
62
66
|
box-shadow var(--duration);
|
|
63
67
|
}
|
|
64
68
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
--switch-border: var(--intent, var(--primary));
|
|
68
|
-
}
|
|
69
|
+
.switch:hover:not(:disabled) {
|
|
70
|
+
--switch-border: var(--intent, var(--primary));
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
.switch:checked {
|
|
@@ -86,14 +88,14 @@
|
|
|
86
88
|
|
|
87
89
|
.switch:focus-visible {
|
|
88
90
|
--switch-border: var(--focus);
|
|
89
|
-
outline:
|
|
91
|
+
outline: 2px solid transparent;
|
|
90
92
|
box-shadow: var(--focus-ring-shadow);
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
.switch:disabled {
|
|
94
96
|
--switch-bg: var(--surface-subtle);
|
|
95
97
|
--switch-border: var(--border);
|
|
96
|
-
--switch-knob: var(--
|
|
98
|
+
--switch-knob: var(--state-disabled);
|
|
97
99
|
opacity: 1;
|
|
98
100
|
cursor: not-allowed;
|
|
99
101
|
}
|
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Imported by default through forms/index.css. Custom builds may omit this
|
|
5
5
|
* file when an app wants to own validation styling completely.
|
|
6
|
+
*
|
|
7
|
+
* State coverage (which states each component ships) is audited in
|
|
8
|
+
* tests/validation.test.js and summarized in docs/pages/forms/validation.md —
|
|
9
|
+
* not kept as a source comment that can drift from the implementation.
|
|
10
|
+
*
|
|
11
|
+
* Public hooks:
|
|
12
|
+
* --form-invalid-border
|
|
13
|
+
*
|
|
14
|
+
* Internal:
|
|
15
|
+
* --choice-bg
|
|
16
|
+
* --switch-bg
|
|
6
17
|
*/
|
|
7
18
|
|
|
8
19
|
.field.danger {
|
|
@@ -25,17 +36,33 @@
|
|
|
25
36
|
--form-invalid-border: var(--danger);
|
|
26
37
|
}
|
|
27
38
|
|
|
28
|
-
/* Override checked/indeterminate
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
39
|
+
/* Override checked/indeterminate fill so both border and fill signal danger
|
|
40
|
+
instead of a red border around a primary-colored control. All three
|
|
41
|
+
invalid routes must converge: aria-invalid, was-validated :invalid, and
|
|
42
|
+
:user-invalid. */
|
|
43
|
+
.check:is(:checked, :indeterminate)[aria-invalid="true"],
|
|
44
|
+
.needs-validation.was-validated .check:is(:checked, :indeterminate):invalid,
|
|
45
|
+
.radio:checked[aria-invalid="true"],
|
|
46
|
+
.needs-validation.was-validated .radio:checked:invalid {
|
|
32
47
|
--choice-bg: var(--danger);
|
|
33
48
|
}
|
|
34
49
|
|
|
35
|
-
.switch[aria-invalid="true"]
|
|
50
|
+
.switch:checked[aria-invalid="true"],
|
|
51
|
+
.needs-validation.was-validated .switch:checked:invalid {
|
|
36
52
|
--switch-bg: var(--danger);
|
|
37
53
|
}
|
|
38
54
|
|
|
55
|
+
@supports selector(:user-invalid) {
|
|
56
|
+
.needs-validation .check:is(:checked, :indeterminate):user-invalid,
|
|
57
|
+
.needs-validation .radio:checked:user-invalid {
|
|
58
|
+
--choice-bg: var(--danger);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.needs-validation .switch:checked:user-invalid {
|
|
62
|
+
--switch-bg: var(--danger);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
39
66
|
/* Choice cards hide their native input, so invalid state must surface on the
|
|
40
67
|
card itself. Sets the same --form-invalid-border hook the card's border
|
|
41
68
|
consumes. */
|
package/src/css/grid.css
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Responsive equal-width grids, with fixed-column presets below.
|
|
3
|
+
*
|
|
4
|
+
* Public hooks:
|
|
5
|
+
* --grid-min
|
|
6
|
+
* --grid-columns
|
|
7
|
+
*/
|
|
1
8
|
.grid {
|
|
2
9
|
display: grid;
|
|
3
10
|
gap: var(--gap);
|
|
4
|
-
grid-template-columns:
|
|
11
|
+
grid-template-columns: var(
|
|
12
|
+
--grid-columns,
|
|
13
|
+
repeat(auto-fit, minmax(min(100%, var(--grid-min, 16rem)), 1fr))
|
|
14
|
+
);
|
|
5
15
|
}
|
|
6
16
|
|
|
7
|
-
/*
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* .grid-2: 2 cols
|
|
13
|
-
* .grid-3: 3 cols
|
|
14
|
-
* .grid-4: 4 cols
|
|
15
|
-
* .grid-6: 6 cols
|
|
16
|
-
* When placed inside .container-query, the column count collapses
|
|
17
|
-
* on narrow wrappers. The intermediate 2-col step applies to
|
|
18
|
-
* .grid-3/.grid-4; .grid-6 starts at 2 columns because it is meant
|
|
19
|
-
* for compact items that do not need a full single-column stack.
|
|
20
|
-
* .grid-2: 1 col -> 2 cols
|
|
21
|
-
* .grid-3: 1 col -> 2 cols -> 3 cols
|
|
22
|
-
* .grid-4: 1 col -> 2 cols -> 4 cols
|
|
23
|
-
* .grid-6: 2 cols -> 3 cols -> 6 cols */
|
|
17
|
+
/* Fixed-column grids at their full count by default: .grid-2/3/4/6 stay at
|
|
18
|
+
2/3/4/6 columns unless wrapped in .container-query, which collapses the
|
|
19
|
+
column count on narrow wrappers (a 2-col intermediate step for
|
|
20
|
+
.grid-3/.grid-4; .grid-6 starts at 2 columns because it is meant for
|
|
21
|
+
compact items that do not need a full single-column stack). */
|
|
24
22
|
.grid-2,
|
|
25
23
|
.grid-3,
|
|
26
24
|
.grid-4,
|
|
@@ -42,6 +40,9 @@
|
|
|
42
40
|
grid-template-columns: repeat(6, minmax(0, 1fr));
|
|
43
41
|
}
|
|
44
42
|
|
|
43
|
+
/* Container queries are the preferred responsive path; browsers without them
|
|
44
|
+
ignore these rules and get the equivalent @media rules from the
|
|
45
|
+
@supports not (container-type) block below — same columns, same breakpoints. */
|
|
45
46
|
@container (width < 28rem) {
|
|
46
47
|
.container-query .grid-2,
|
|
47
48
|
.container-query .grid-3,
|
package/src/css/intents.css
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Intent classes do not style elements directly.
|
|
3
3
|
* They only expose --intent and --intent-fg.
|
|
4
4
|
* Components and variants decide how to consume them. Each component that
|
|
5
|
-
* consumes --intent or --ui-*
|
|
6
|
-
* block that resets
|
|
5
|
+
* consumes --intent or --ui-* opens a local intent boundary in a :where()
|
|
6
|
+
* block that resets exactly the tokens it consumes to initial. Parent intents
|
|
7
7
|
* do not leak into nested components. Local intent classes (.primary, .danger,
|
|
8
8
|
* etc.) still apply because they have higher specificity than :where().
|
|
9
9
|
*/
|
package/src/css/layout.css
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Core layout primitives: stack, cluster, center, frame, app-shell, media,
|
|
3
|
+
* sidebar-layout. Each primitive owns a single, readable behavior; they are
|
|
4
|
+
* meant to compose in markup.
|
|
5
|
+
*
|
|
6
|
+
* Public hooks:
|
|
7
|
+
* --cluster-align
|
|
8
|
+
* --cluster-justify
|
|
9
|
+
* --cluster-wrap
|
|
10
|
+
* --center-size
|
|
11
|
+
* --center-pad
|
|
12
|
+
* --frame-ratio
|
|
13
|
+
* --sidebar-layout-size
|
|
14
|
+
*
|
|
15
|
+
* Child contracts:
|
|
16
|
+
* .stack owns vertical rhythm: direct-child margins are reset, spacing comes
|
|
17
|
+
* from --gap.
|
|
18
|
+
* .cluster owns inline rhythm: direct-child margins are reset, spacing comes
|
|
19
|
+
* from --gap.
|
|
20
|
+
* .frame sizes direct media children (img/video/iframe/canvas/svg) to fill the
|
|
21
|
+
* frame.
|
|
22
|
+
*/
|
|
1
23
|
.container-query {
|
|
2
24
|
container-type: inline-size;
|
|
3
25
|
}
|
|
@@ -14,12 +36,16 @@
|
|
|
14
36
|
|
|
15
37
|
.cluster {
|
|
16
38
|
display: flex;
|
|
17
|
-
flex-wrap: wrap;
|
|
39
|
+
flex-wrap: var(--cluster-wrap, wrap);
|
|
18
40
|
align-items: var(--cluster-align, center);
|
|
19
41
|
justify-content: var(--cluster-justify, flex-start);
|
|
20
42
|
gap: var(--gap);
|
|
21
43
|
}
|
|
22
44
|
|
|
45
|
+
.cluster > * {
|
|
46
|
+
margin: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
23
49
|
.center {
|
|
24
50
|
box-sizing: content-box;
|
|
25
51
|
max-inline-size: var(--center-size, 72rem);
|
|
@@ -63,6 +89,8 @@
|
|
|
63
89
|
grid-template-columns: minmax(0, 1fr);
|
|
64
90
|
}
|
|
65
91
|
|
|
92
|
+
/* Container queries are the preferred path; without them the @supports not
|
|
93
|
+
block below restores the same columns at the same viewport breakpoint. */
|
|
66
94
|
@container (width >= 64rem) {
|
|
67
95
|
.container-query .sidebar-layout {
|
|
68
96
|
grid-template-columns: minmax(0, 1fr) var(--sidebar-layout-size, 18rem);
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Decorative intent-colored frame for one direct child.
|
|
3
|
+
*
|
|
4
|
+
* Public hooks:
|
|
5
|
+
* --aura-color
|
|
6
|
+
* --aura-width
|
|
7
|
+
* --aura-blur
|
|
8
|
+
* --aura-radius
|
|
9
|
+
* --aura-duration
|
|
10
|
+
*/
|
|
11
|
+
@property --aura-angle {
|
|
12
|
+
syntax: "<angle>";
|
|
13
|
+
inherits: false;
|
|
14
|
+
initial-value: 0deg;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/* Intent boundary — an outer intent does not tint nested aura frames. */
|
|
18
|
+
:where(.aura) {
|
|
19
|
+
--intent: initial;
|
|
20
|
+
--intent-fg: initial;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.aura {
|
|
24
|
+
--aura-color: var(--intent, var(--primary));
|
|
25
|
+
--aura-width: 2px;
|
|
26
|
+
--aura-blur: 0.75rem;
|
|
27
|
+
--aura-radius: var(--radius-lg);
|
|
28
|
+
--aura-duration: 6s;
|
|
29
|
+
|
|
30
|
+
position: relative;
|
|
31
|
+
isolation: isolate;
|
|
32
|
+
display: inline-grid;
|
|
33
|
+
padding: var(--aura-width);
|
|
34
|
+
border-radius: calc(var(--aura-radius) + var(--aura-width));
|
|
35
|
+
background: var(--aura-color);
|
|
36
|
+
background: conic-gradient(from var(--aura-angle), transparent 0 65%, var(--aura-color));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.aura::before {
|
|
40
|
+
position: absolute;
|
|
41
|
+
z-index: -1;
|
|
42
|
+
inset: 0;
|
|
43
|
+
border-radius: inherit;
|
|
44
|
+
background: inherit;
|
|
45
|
+
filter: blur(var(--aura-blur));
|
|
46
|
+
opacity: 0.45;
|
|
47
|
+
pointer-events: none;
|
|
48
|
+
content: "";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.aura > * {
|
|
52
|
+
position: relative;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.aura-glow {
|
|
56
|
+
background: var(--aura-color);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
60
|
+
.aura:not(.aura-glow) {
|
|
61
|
+
animation: aura-rotate var(--aura-duration) linear infinite;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@keyframes aura-rotate {
|
|
66
|
+
to {
|
|
67
|
+
--aura-angle: 360deg;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@supports selector(:has(*)) {
|
|
72
|
+
.aura:has(> .btn) {
|
|
73
|
+
--aura-radius: var(--radius);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.aura:has(> :is(.card, .alert)) {
|
|
77
|
+
--aura-radius: var(--radius-lg);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.aura:has(> .badge) {
|
|
81
|
+
--aura-radius: var(--radius-full);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
@media (forced-colors: active) {
|
|
86
|
+
.aura {
|
|
87
|
+
background: CanvasText;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.aura::before {
|
|
91
|
+
display: none;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Message rows composed from an optional avatar, metadata, and bubble.
|
|
3
|
+
*
|
|
4
|
+
* Public hooks:
|
|
5
|
+
* --chat-gap
|
|
6
|
+
* --chat-max-size
|
|
7
|
+
*
|
|
8
|
+
* Internal:
|
|
9
|
+
* --chat-bubble-bg
|
|
10
|
+
* --chat-bubble-fg
|
|
11
|
+
* --chat-bubble-border
|
|
12
|
+
*/
|
|
13
|
+
.chat {
|
|
14
|
+
--chat-gap: var(--space-30);
|
|
15
|
+
--chat-max-size: min(85%, 40rem);
|
|
16
|
+
|
|
17
|
+
display: grid;
|
|
18
|
+
grid-auto-rows: min-content;
|
|
19
|
+
column-gap: var(--chat-gap);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.chat-start {
|
|
23
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
24
|
+
justify-items: start;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.chat-end {
|
|
28
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
29
|
+
justify-items: end;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.chat-avatar {
|
|
33
|
+
grid-row: 1 / span 3;
|
|
34
|
+
align-self: end;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.chat-start > .chat-avatar {
|
|
38
|
+
grid-column: 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.chat-end > .chat-avatar {
|
|
42
|
+
grid-column: 2;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.chat-header,
|
|
46
|
+
.chat-footer {
|
|
47
|
+
display: flex;
|
|
48
|
+
gap: var(--space-10);
|
|
49
|
+
color: var(--text-muted);
|
|
50
|
+
font-size: var(--font-size-xs);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.chat-start > :is(.chat-header, .chat-bubble, .chat-footer) {
|
|
54
|
+
grid-column: 2;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.chat-end > :is(.chat-header, .chat-bubble, .chat-footer) {
|
|
58
|
+
grid-column: 1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Intent boundary — an outer intent does not tint nested messages. */
|
|
62
|
+
:where(.chat-bubble) {
|
|
63
|
+
--intent: initial;
|
|
64
|
+
--intent-fg: initial;
|
|
65
|
+
--ui-bg: initial;
|
|
66
|
+
--ui-fg: initial;
|
|
67
|
+
--ui-border: initial;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.chat-bubble {
|
|
71
|
+
--chat-bubble-bg: var(--ui-bg, var(--intent, var(--surface-subtle)));
|
|
72
|
+
--chat-bubble-fg: var(--ui-fg, var(--intent-fg, var(--text)));
|
|
73
|
+
--chat-bubble-border: var(--ui-border, transparent);
|
|
74
|
+
|
|
75
|
+
inline-size: fit-content;
|
|
76
|
+
max-inline-size: var(--chat-max-size);
|
|
77
|
+
padding: var(--space-20) var(--space-30);
|
|
78
|
+
border: var(--border-width) solid var(--chat-bubble-border);
|
|
79
|
+
border-radius: var(--radius-lg);
|
|
80
|
+
background: var(--chat-bubble-bg);
|
|
81
|
+
color: var(--chat-bubble-fg);
|
|
82
|
+
overflow-wrap: anywhere;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.chat-start > .chat-bubble {
|
|
86
|
+
border-end-start-radius: var(--radius-sm);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.chat-end > .chat-bubble {
|
|
90
|
+
border-end-end-radius: var(--radius-sm);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* Remove the reserved avatar gutter when a message has no avatar. This is a
|
|
94
|
+
cosmetic enhancement; the two-column baseline remains fully readable. */
|
|
95
|
+
@supports selector(:has(*)) {
|
|
96
|
+
.chat:not(:has(> .chat-avatar)) {
|
|
97
|
+
column-gap: 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@media (forced-colors: active) {
|
|
102
|
+
.chat-bubble {
|
|
103
|
+
border-color: CanvasText;
|
|
104
|
+
}
|
|
105
|
+
}
|