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
|
@@ -4,24 +4,20 @@
|
|
|
4
4
|
* JavaScript owns roving tabindex, aria-selected, panel visibility,
|
|
5
5
|
* and arrow-key navigation. CSS owns the tab strip appearance and
|
|
6
6
|
* active indicator.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --tab-gap
|
|
7
10
|
*/
|
|
8
11
|
/* Intent boundary — inherited intents do not tint this component.
|
|
9
12
|
Local intent classes still win because :where() has zero specificity. */
|
|
10
13
|
:where(.tab) {
|
|
11
|
-
/* @sync intent-boundary */
|
|
12
14
|
--intent: initial;
|
|
13
|
-
--intent-fg: initial;
|
|
14
|
-
--ui-bg: initial;
|
|
15
|
-
--ui-fg: initial;
|
|
16
|
-
--ui-border: initial;
|
|
17
|
-
--ui-hover-bg: initial;
|
|
18
|
-
/* @sync intent-boundary */
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
.tabs {
|
|
22
18
|
display: flex;
|
|
23
19
|
flex-wrap: wrap;
|
|
24
|
-
gap: var(--space-
|
|
20
|
+
gap: var(--space-10);
|
|
25
21
|
margin: 0;
|
|
26
22
|
padding: 0;
|
|
27
23
|
border-block-end: var(--border-width) solid var(--border);
|
|
@@ -39,8 +35,9 @@
|
|
|
39
35
|
.tab {
|
|
40
36
|
display: inline-flex;
|
|
41
37
|
align-items: center;
|
|
38
|
+
gap: var(--tab-gap, 0.375em);
|
|
42
39
|
min-block-size: var(--control-size);
|
|
43
|
-
padding-inline: var(--space-
|
|
40
|
+
padding-inline: var(--space-30);
|
|
44
41
|
border: 0;
|
|
45
42
|
border-block-end: 2px solid transparent;
|
|
46
43
|
border-radius: 0;
|
|
@@ -56,7 +53,7 @@
|
|
|
56
53
|
justify-content: flex-start;
|
|
57
54
|
border-block-end: 0;
|
|
58
55
|
border-inline-end: 2px solid transparent;
|
|
59
|
-
padding-inline-end: var(--space-
|
|
56
|
+
padding-inline-end: var(--space-40);
|
|
60
57
|
}
|
|
61
58
|
|
|
62
59
|
.tab:is(:disabled, [aria-disabled="true"]) {
|
|
@@ -64,10 +61,8 @@
|
|
|
64
61
|
opacity: var(--disabled-opacity);
|
|
65
62
|
}
|
|
66
63
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
color: var(--text);
|
|
70
|
-
}
|
|
64
|
+
.tab:hover:not(:where(:disabled, [aria-disabled="true"])) {
|
|
65
|
+
color: var(--text);
|
|
71
66
|
}
|
|
72
67
|
|
|
73
68
|
.tab:focus-visible {
|
|
@@ -77,52 +72,28 @@
|
|
|
77
72
|
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
|
|
78
73
|
}
|
|
79
74
|
|
|
80
|
-
.tab[aria-selected="true"]
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
border-block-end-color: var(--intent, var(--primary));
|
|
84
|
-
color: var(--intent, var(--primary));
|
|
75
|
+
.tab[aria-selected="true"] {
|
|
76
|
+
border-block-end-color: var(--intent, var(--state-selected));
|
|
77
|
+
color: var(--intent, var(--state-selected));
|
|
85
78
|
}
|
|
86
79
|
|
|
87
|
-
.tabs[aria-orientation="vertical"] .tab[aria-selected="true"]
|
|
88
|
-
.tabs[aria-orientation="vertical"] .tab[aria-current]:not([aria-current="false"]),
|
|
89
|
-
.tabs[aria-orientation="vertical"] .tab[aria-pressed="true"] {
|
|
80
|
+
.tabs[aria-orientation="vertical"] .tab[aria-selected="true"] {
|
|
90
81
|
border-block-end-color: transparent;
|
|
91
|
-
border-inline-end-color: var(--intent, var(--
|
|
82
|
+
border-inline-end-color: var(--intent, var(--state-selected));
|
|
92
83
|
}
|
|
93
84
|
|
|
94
85
|
@media (forced-colors: active) {
|
|
95
|
-
.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.tabs[aria-orientation="vertical"] {
|
|
100
|
-
border-block-end-color: transparent;
|
|
101
|
-
border-inline-end-color: ButtonText;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.tab {
|
|
105
|
-
color: ButtonText;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
@media (hover: hover) {
|
|
109
|
-
.tab:hover:not(:where(:disabled, [aria-disabled="true"])) {
|
|
110
|
-
color: ButtonText;
|
|
111
|
-
text-decoration: underline;
|
|
112
|
-
text-underline-offset: 0.18em;
|
|
113
|
-
}
|
|
86
|
+
.tab:hover:not(:where(:disabled, [aria-disabled="true"])) {
|
|
87
|
+
text-decoration: underline;
|
|
88
|
+
text-underline-offset: 0.18em;
|
|
114
89
|
}
|
|
115
90
|
|
|
116
|
-
.tab[aria-selected="true"]
|
|
117
|
-
.tab[aria-current]:not([aria-current="false"]),
|
|
118
|
-
.tab[aria-pressed="true"] {
|
|
91
|
+
.tab[aria-selected="true"] {
|
|
119
92
|
border-block-end-color: Highlight;
|
|
120
93
|
color: Highlight;
|
|
121
94
|
}
|
|
122
95
|
|
|
123
|
-
.tabs[aria-orientation="vertical"] .tab[aria-selected="true"]
|
|
124
|
-
.tabs[aria-orientation="vertical"] .tab[aria-current]:not([aria-current="false"]),
|
|
125
|
-
.tabs[aria-orientation="vertical"] .tab[aria-pressed="true"] {
|
|
96
|
+
.tabs[aria-orientation="vertical"] .tab[aria-selected="true"] {
|
|
126
97
|
border-block-end-color: transparent;
|
|
127
98
|
border-inline-end-color: Highlight;
|
|
128
99
|
}
|
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* .table-wrap provides the scroll container and outer chrome; .table owns row
|
|
5
5
|
* and cell rules. Tokens are sourced from the shared scale.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --table-min
|
|
9
|
+
* --table-cell-pad
|
|
6
10
|
*/
|
|
7
11
|
.table-wrap {
|
|
8
12
|
inline-size: 100%;
|
|
@@ -16,7 +20,7 @@
|
|
|
16
20
|
|
|
17
21
|
.table {
|
|
18
22
|
--table-min: 100%;
|
|
19
|
-
--table-cell-pad: var(--space-
|
|
23
|
+
--table-cell-pad: var(--space-30);
|
|
20
24
|
|
|
21
25
|
inline-size: max(var(--table-min), 100%);
|
|
22
26
|
border-collapse: collapse;
|
|
@@ -52,10 +56,8 @@
|
|
|
52
56
|
background: var(--surface-subtle);
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
background-color: var(--hover-overlay);
|
|
58
|
-
}
|
|
59
|
+
.table tbody tr:hover {
|
|
60
|
+
background-color: var(--hover-overlay);
|
|
59
61
|
}
|
|
60
62
|
|
|
61
63
|
.table > tr:last-child > *,
|
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
* Position, placement, and arrow position are managed by JavaScript
|
|
5
5
|
* via position: fixed, left, top, data-placement, and --arrow-x.
|
|
6
6
|
* Visibility is managed with hidden; CSS owns entry and exit animation.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --tooltip-bg
|
|
10
|
+
* --tooltip-fg
|
|
11
|
+
* --tooltip-arrow-size
|
|
12
|
+
*
|
|
13
|
+
* Internal:
|
|
14
|
+
* --arrow-x (arrow position, written by floating.js)
|
|
15
|
+
* --arrow-y (arrow position, written by floating.js)
|
|
7
16
|
*/
|
|
8
17
|
.tooltip {
|
|
9
18
|
--tooltip-bg: var(--surface-solid);
|
|
@@ -25,8 +34,8 @@
|
|
|
25
34
|
opacity: 1;
|
|
26
35
|
scale: 1;
|
|
27
36
|
transition:
|
|
28
|
-
opacity var(--duration-fast
|
|
29
|
-
scale var(--duration-fast
|
|
37
|
+
opacity var(--duration-fast) var(--ease),
|
|
38
|
+
scale var(--duration-fast) var(--ease);
|
|
30
39
|
}
|
|
31
40
|
|
|
32
41
|
.tooltip[hidden] {
|
|
@@ -45,9 +54,9 @@
|
|
|
45
54
|
@supports (transition-behavior: allow-discrete) {
|
|
46
55
|
.tooltip {
|
|
47
56
|
transition:
|
|
48
|
-
opacity var(--duration-fast
|
|
49
|
-
scale var(--duration-fast
|
|
50
|
-
display var(--duration-fast
|
|
57
|
+
opacity var(--duration-fast) var(--ease),
|
|
58
|
+
scale var(--duration-fast) var(--ease),
|
|
59
|
+
display var(--duration-fast) allow-discrete;
|
|
51
60
|
}
|
|
52
61
|
}
|
|
53
62
|
|
|
@@ -97,8 +106,6 @@
|
|
|
97
106
|
.tooltip {
|
|
98
107
|
--tooltip-bg: Canvas;
|
|
99
108
|
--tooltip-fg: CanvasText;
|
|
100
|
-
|
|
101
|
-
border: var(--border-width) solid ButtonText;
|
|
102
109
|
}
|
|
103
110
|
|
|
104
111
|
.tooltip::before {
|
package/src/css/focus.css
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
/* Focus baseline —
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/* Focus baseline — a visible outline is the guaranteed focus affordance. The
|
|
2
|
+
:focus outline covers legacy browsers; modern browsers hide it for
|
|
3
|
+
pointer/mouse focus and interactive components layer their ring on top.
|
|
4
|
+
|
|
5
|
+
Invariant: an interactive component must never rely on box-shadow alone
|
|
6
|
+
for its keyboard focus indicator. Components that remove the native
|
|
7
|
+
outline on :focus-visible replace it with a transparent outline — invisible
|
|
8
|
+
normally, forced to the system focus color under forced-colors. */
|
|
4
9
|
:focus {
|
|
5
10
|
outline: var(--focus-outline);
|
|
6
11
|
outline-offset: var(--focus-outline-offset);
|
|
@@ -10,41 +15,12 @@
|
|
|
10
15
|
:focus:not(:focus-visible) {
|
|
11
16
|
outline: none;
|
|
12
17
|
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/*
|
|
16
|
-
* Forced-colors focus — centralised so individual components do not need
|
|
17
|
-
* their own fallback. The double :focus keeps specificity high enough
|
|
18
|
-
* (0,0,2,0) to beat a single :focus-visible; against a class selector like
|
|
19
|
-
* .input:focus-visible it ties, but this file loads last so it wins on
|
|
20
|
-
* source order.
|
|
21
|
-
*
|
|
22
|
-
* .choice-card and .join receive focus indirectly (:has on a wrapper that
|
|
23
|
-
* never matches :focus), so they are listed explicitly.
|
|
24
|
-
*
|
|
25
|
-
* .range is excluded from the rectangular fallback: its focus is drawn on
|
|
26
|
-
* the thumb pseudo-element, which is the manipulated surface.
|
|
27
|
-
*
|
|
28
|
-
* box-shadow: none is redundant when forced-color-adjust is auto, but safe
|
|
29
|
-
* when a component uses forced-color-adjust: none (e.g. checked switches /
|
|
30
|
-
* checkboxes).
|
|
31
|
-
*/
|
|
32
|
-
@media (forced-colors: active) {
|
|
33
|
-
:focus:focus-visible:not(.range),
|
|
34
|
-
.choice-card:has(:focus-visible),
|
|
35
|
-
.join:has(> :is(.input, .textarea, .select):focus-visible) {
|
|
36
|
-
outline: var(--focus-outline);
|
|
37
|
-
outline-offset: var(--focus-outline-offset);
|
|
38
|
-
box-shadow: none;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
.range:focus-visible::-webkit-slider-thumb {
|
|
42
|
-
outline: var(--focus-outline);
|
|
43
|
-
outline-offset: var(--focus-outline-offset);
|
|
44
|
-
}
|
|
45
18
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
19
|
+
/* Pointer focus must still signal in high-contrast mode, where the shared
|
|
20
|
+
box-shadow rings are disabled (--focus-ring-shadow: none). */
|
|
21
|
+
@media (forced-colors: active) {
|
|
22
|
+
:focus:not(:focus-visible) {
|
|
23
|
+
outline: var(--focus-outline);
|
|
24
|
+
}
|
|
49
25
|
}
|
|
50
26
|
}
|
|
@@ -10,20 +10,21 @@
|
|
|
10
10
|
* The badge overhangs the top-right corner by 0.375em; ancestors with
|
|
11
11
|
* overflow: hidden will clip it. Pair with grid or flex utilities for group
|
|
12
12
|
* layout.
|
|
13
|
+
*
|
|
14
|
+
* Public hooks:
|
|
15
|
+
* --choice-card-pad
|
|
16
|
+
* --choice-card-radius
|
|
17
|
+
* --choice-card-border
|
|
18
|
+
* --choice-card-bg
|
|
19
|
+
* --choice-card-check-size
|
|
13
20
|
*/
|
|
14
21
|
:where(.choice-card) {
|
|
15
|
-
/* @sync intent-boundary */
|
|
16
22
|
--intent: initial;
|
|
17
23
|
--intent-fg: initial;
|
|
18
|
-
--ui-bg: initial;
|
|
19
|
-
--ui-fg: initial;
|
|
20
|
-
--ui-border: initial;
|
|
21
|
-
--ui-hover-bg: initial;
|
|
22
|
-
/* @sync intent-boundary */
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
.choice-card {
|
|
26
|
-
--choice-card-pad: var(--
|
|
27
|
+
--choice-card-pad: var(--density-space, var(--space-40));
|
|
27
28
|
--choice-card-radius: var(--radius);
|
|
28
29
|
--choice-card-border: var(--border);
|
|
29
30
|
--choice-card-bg: var(--surface);
|
|
@@ -63,7 +64,7 @@
|
|
|
63
64
|
|
|
64
65
|
/* Focus ring on the label follows the hidden input's focus. */
|
|
65
66
|
.choice-card:has(:focus-visible) {
|
|
66
|
-
outline:
|
|
67
|
+
outline: 2px solid transparent;
|
|
67
68
|
box-shadow: var(--focus-ring-shadow);
|
|
68
69
|
}
|
|
69
70
|
|
|
@@ -72,10 +73,8 @@
|
|
|
72
73
|
cursor: not-allowed;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
--choice-card-border: var(--text-subtle);
|
|
78
|
-
}
|
|
76
|
+
.choice-card:hover:not(:has(:disabled)) {
|
|
77
|
+
--choice-card-border: var(--text-subtle);
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
/* Checked border — shared by radio and checkbox */
|
|
@@ -122,8 +121,8 @@
|
|
|
122
121
|
/* Check mark */
|
|
123
122
|
.choice-card::after {
|
|
124
123
|
background: var(--intent-fg, var(--primary-fg));
|
|
125
|
-
-webkit-mask: var(--icon-check
|
|
126
|
-
mask: var(--icon-check
|
|
124
|
+
-webkit-mask: var(--icon-check) center / 60% no-repeat;
|
|
125
|
+
mask: var(--icon-check) center / 60% no-repeat;
|
|
127
126
|
z-index: 2;
|
|
128
127
|
}
|
|
129
128
|
|
package/src/css/forms/choice.css
CHANGED
|
@@ -8,23 +8,23 @@
|
|
|
8
8
|
*
|
|
9
9
|
* Switches (input[role="switch"]) are excluded so switch.css owns their
|
|
10
10
|
* geometry and states. switch.css is imported after this file.
|
|
11
|
+
*
|
|
12
|
+
* Public hooks:
|
|
13
|
+
* --choice-control-offset
|
|
14
|
+
* --choice-border
|
|
15
|
+
* --choice-bg
|
|
16
|
+
* --choice-mark
|
|
11
17
|
*/
|
|
12
18
|
/* Intent boundary — inherited intents do not tint this component.
|
|
13
19
|
Local intent classes still win because :where() has zero specificity. */
|
|
14
20
|
:where(.choice, .check, .radio) {
|
|
15
|
-
/* @sync intent-boundary */
|
|
16
21
|
--intent: initial;
|
|
17
22
|
--intent-fg: initial;
|
|
18
|
-
--ui-bg: initial;
|
|
19
|
-
--ui-fg: initial;
|
|
20
|
-
--ui-border: initial;
|
|
21
|
-
--ui-hover-bg: initial;
|
|
22
|
-
/* @sync intent-boundary */
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/* A classed .choice is the component surface. Let its
|
|
25
|
+
/* A classed .choice is the component surface. Let its direct input consume a
|
|
26
26
|
local intent without reopening inherited page-level intents. */
|
|
27
|
-
:where(.choice) :where(input[type="checkbox"]:not([role="switch"]), input[type="radio"]) {
|
|
27
|
+
:where(.choice) > :where(input[type="checkbox"]:not([role="switch"]), input[type="radio"]) {
|
|
28
28
|
--intent: inherit;
|
|
29
29
|
--intent-fg: inherit;
|
|
30
30
|
}
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
|
|
35
35
|
display: inline-flex;
|
|
36
36
|
align-items: flex-start;
|
|
37
|
-
gap: var(--space-
|
|
37
|
+
gap: var(--space-20);
|
|
38
38
|
color: var(--text);
|
|
39
39
|
font-size: var(--control-font-size);
|
|
40
40
|
cursor: pointer;
|
|
@@ -57,8 +57,11 @@
|
|
|
57
57
|
display: block;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
/* Progressive enhancement: dim the whole row when one of its controls is
|
|
61
|
+
disabled. Without :has() the native disabled control keeps its own state
|
|
62
|
+
styling — the row-level dim is lost but the field stays clearly disabled. */
|
|
63
|
+
.choice:has(> :disabled) {
|
|
64
|
+
color: var(--state-disabled);
|
|
62
65
|
cursor: not-allowed;
|
|
63
66
|
}
|
|
64
67
|
|
|
@@ -75,8 +78,7 @@
|
|
|
75
78
|
place-content: center;
|
|
76
79
|
inline-size: 1.125em;
|
|
77
80
|
block-size: 1.125em;
|
|
78
|
-
margin
|
|
79
|
-
margin-block-end: 0;
|
|
81
|
+
margin: 0;
|
|
80
82
|
border: var(--border-width) solid var(--form-invalid-border, var(--choice-border));
|
|
81
83
|
background: var(--choice-bg);
|
|
82
84
|
color: var(--choice-mark);
|
|
@@ -117,7 +119,7 @@
|
|
|
117
119
|
background: currentColor;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
.check:checked,
|
|
122
|
+
.check:is(:checked, :indeterminate),
|
|
121
123
|
.radio:checked {
|
|
122
124
|
--choice-border: var(--intent, var(--primary));
|
|
123
125
|
--choice-bg: var(--intent, var(--primary));
|
|
@@ -128,12 +130,6 @@
|
|
|
128
130
|
transform: translateY(-0.06em) rotate(-45deg) scale(1);
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
.check:indeterminate {
|
|
132
|
-
--choice-border: var(--intent, var(--primary));
|
|
133
|
-
--choice-bg: var(--intent, var(--primary));
|
|
134
|
-
--choice-mark: var(--intent-fg, var(--primary-fg));
|
|
135
|
-
}
|
|
136
|
-
|
|
137
133
|
.check:indeterminate::before {
|
|
138
134
|
border-inline-start: 0;
|
|
139
135
|
inline-size: 0.6em;
|
|
@@ -146,17 +142,15 @@
|
|
|
146
142
|
transform: scale(1);
|
|
147
143
|
}
|
|
148
144
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
--choice-border: var(--text-subtle);
|
|
153
|
-
}
|
|
145
|
+
.check:hover:not(:checked, :indeterminate, :disabled),
|
|
146
|
+
.radio:hover:not(:checked, :indeterminate, :disabled) {
|
|
147
|
+
--choice-border: var(--text-subtle);
|
|
154
148
|
}
|
|
155
149
|
|
|
156
150
|
.check:focus-visible,
|
|
157
151
|
.radio:focus-visible {
|
|
158
152
|
--choice-border: var(--focus);
|
|
159
|
-
outline:
|
|
153
|
+
outline: 2px solid transparent;
|
|
160
154
|
box-shadow: var(--focus-ring-shadow);
|
|
161
155
|
}
|
|
162
156
|
|
|
@@ -164,7 +158,7 @@
|
|
|
164
158
|
.radio:disabled {
|
|
165
159
|
--choice-bg: var(--surface-subtle);
|
|
166
160
|
--choice-border: var(--border);
|
|
167
|
-
--choice-mark: var(--
|
|
161
|
+
--choice-mark: var(--state-disabled);
|
|
168
162
|
cursor: not-allowed;
|
|
169
163
|
opacity: 1;
|
|
170
164
|
}
|
|
@@ -14,6 +14,12 @@
|
|
|
14
14
|
* --control-border-block-end-color/-width are unset extension points, mirroring
|
|
15
15
|
* --btn-border-block-end-* (button.css), for themes that give text controls an
|
|
16
16
|
* underline-style lower edge instead of a uniform border.
|
|
17
|
+
*
|
|
18
|
+
* Public hooks:
|
|
19
|
+
* --control-border
|
|
20
|
+
* --control-bg
|
|
21
|
+
* --control-fg
|
|
22
|
+
* --control-cursor
|
|
17
23
|
*/
|
|
18
24
|
.input,
|
|
19
25
|
.textarea,
|
|
@@ -21,14 +27,12 @@
|
|
|
21
27
|
--control-border: var(--border);
|
|
22
28
|
--control-bg: var(--surface);
|
|
23
29
|
--control-fg: var(--text);
|
|
24
|
-
--control-ring: none;
|
|
25
30
|
--control-cursor: auto;
|
|
26
|
-
--control-opacity: 1;
|
|
27
31
|
|
|
28
32
|
appearance: none;
|
|
29
33
|
inline-size: 100%;
|
|
30
34
|
min-block-size: var(--control-size);
|
|
31
|
-
padding-inline: var(--space-
|
|
35
|
+
padding-inline: var(--space-30);
|
|
32
36
|
border: var(--border-width) solid var(--form-invalid-border, var(--control-border));
|
|
33
37
|
border-block-end-color: var(
|
|
34
38
|
--form-invalid-border,
|
|
@@ -39,9 +43,7 @@
|
|
|
39
43
|
background: var(--control-bg);
|
|
40
44
|
color: var(--control-fg);
|
|
41
45
|
font-size: var(--control-font-size);
|
|
42
|
-
box-shadow: var(--control-ring);
|
|
43
46
|
cursor: var(--control-cursor);
|
|
44
|
-
opacity: var(--control-opacity);
|
|
45
47
|
outline: none;
|
|
46
48
|
transition:
|
|
47
49
|
border-color var(--duration),
|
|
@@ -52,26 +54,24 @@
|
|
|
52
54
|
|
|
53
55
|
.textarea {
|
|
54
56
|
min-block-size: 6rem;
|
|
55
|
-
padding-block: var(--space-
|
|
57
|
+
padding-block: var(--space-20);
|
|
56
58
|
resize: vertical;
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
61
|
+
.input:hover:not(:disabled),
|
|
62
|
+
.textarea:hover:not(:disabled) {
|
|
63
|
+
--control-border: var(--text-subtle);
|
|
64
|
+
}
|
|
64
65
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
66
|
+
.select:hover:not(:disabled) {
|
|
67
|
+
--control-bg: var(--surface-subtle);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
.input:focus-visible,
|
|
71
71
|
.textarea:focus-visible,
|
|
72
72
|
.select:focus-visible {
|
|
73
73
|
--control-border: var(--focus);
|
|
74
|
-
outline:
|
|
74
|
+
outline: 2px solid transparent;
|
|
75
75
|
box-shadow: var(--focus-ring-shadow);
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -85,10 +85,9 @@
|
|
|
85
85
|
.textarea:disabled,
|
|
86
86
|
.select:disabled {
|
|
87
87
|
--control-bg: var(--surface-subtle);
|
|
88
|
-
--control-fg: var(--
|
|
88
|
+
--control-fg: var(--state-disabled);
|
|
89
89
|
--control-border: var(--border);
|
|
90
90
|
--control-cursor: not-allowed;
|
|
91
|
-
--control-opacity: 1;
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
.input::placeholder,
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
*
|
|
8
8
|
* No layout or interaction contract may depend on appearance: base-select.
|
|
9
9
|
* Arbitrary menu and popover behavior belongs elsewhere.
|
|
10
|
+
*
|
|
11
|
+
* Internal:
|
|
12
|
+
* --control-border
|
|
13
|
+
* --control-bg
|
|
10
14
|
*/
|
|
11
15
|
@media (forced-colors: none) and (prefers-contrast: no-preference) and (hover: hover) and (
|
|
12
16
|
pointer: fine
|
|
@@ -19,7 +23,7 @@
|
|
|
19
23
|
&::picker(select) {
|
|
20
24
|
appearance: base-select;
|
|
21
25
|
max-height: min(24rem, calc(var(--viewport-block) * 0.7));
|
|
22
|
-
margin-block: var(--space-
|
|
26
|
+
margin-block: var(--space-20);
|
|
23
27
|
padding: 0;
|
|
24
28
|
border: var(--border-width) solid var(--border);
|
|
25
29
|
border-radius: var(--radius);
|
|
@@ -41,8 +45,8 @@
|
|
|
41
45
|
|
|
42
46
|
& option {
|
|
43
47
|
position: relative;
|
|
44
|
-
padding-block: var(--space-
|
|
45
|
-
padding-inline: var(--space-
|
|
48
|
+
padding-block: var(--space-20);
|
|
49
|
+
padding-inline: var(--space-30);
|
|
46
50
|
white-space: normal;
|
|
47
51
|
transition-property: color, background-color;
|
|
48
52
|
transition-duration: var(--duration);
|
|
@@ -70,14 +74,8 @@
|
|
|
70
74
|
inline-size: 1rem;
|
|
71
75
|
block-size: 1rem;
|
|
72
76
|
background-color: currentColor;
|
|
73
|
-
-webkit-mask
|
|
74
|
-
mask
|
|
75
|
-
-webkit-mask-repeat: no-repeat;
|
|
76
|
-
mask-repeat: no-repeat;
|
|
77
|
-
-webkit-mask-size: contain;
|
|
78
|
-
mask-size: contain;
|
|
79
|
-
-webkit-mask-position: center;
|
|
80
|
-
mask-position: center;
|
|
77
|
+
-webkit-mask: var(--icon-check) center / contain no-repeat;
|
|
78
|
+
mask: var(--icon-check) center / contain no-repeat;
|
|
81
79
|
}
|
|
82
80
|
}
|
|
83
81
|
|
|
@@ -4,13 +4,24 @@
|
|
|
4
4
|
* A flex cluster of buttons/actions that closes a form. The sticky variant
|
|
5
5
|
* docks to the viewport bottom with a translucent blur where supported; at
|
|
6
6
|
* rest it stays visually neutral so it does not double as a separator.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --form-actions-align
|
|
10
|
+
* --form-actions-justify
|
|
11
|
+
* --form-actions-margin-block-start
|
|
12
|
+
*
|
|
13
|
+
* Internal:
|
|
14
|
+
* --form-actions-sticky-block-offset (owned by .form-actions.sticky)
|
|
15
|
+
* --form-actions-sticky-inline-offset (owned by .form-actions.sticky)
|
|
16
|
+
* --form-actions-sticky-padding (owned by .form-actions.sticky)
|
|
7
17
|
*/
|
|
8
18
|
.form-actions {
|
|
9
19
|
display: flex;
|
|
10
20
|
flex-wrap: wrap;
|
|
11
21
|
gap: var(--gap);
|
|
12
|
-
align-items: center;
|
|
13
|
-
|
|
22
|
+
align-items: var(--form-actions-align, center);
|
|
23
|
+
justify-content: var(--form-actions-justify, flex-start);
|
|
24
|
+
margin-block-start: var(--form-actions-margin-block-start, var(--space-50));
|
|
14
25
|
}
|
|
15
26
|
|
|
16
27
|
/* Opt-in sticky variant. When the bar is not stuck (at rest) the translucent
|
|
@@ -24,7 +35,7 @@
|
|
|
24
35
|
isolation: isolate;
|
|
25
36
|
|
|
26
37
|
margin-inline: calc(var(--form-actions-sticky-inline-offset, 0px) * -1);
|
|
27
|
-
padding: var(--form-actions-sticky-padding, var(--space-
|
|
38
|
+
padding: var(--form-actions-sticky-padding, var(--space-30));
|
|
28
39
|
|
|
29
40
|
border-block-start: var(--border-width) solid var(--border);
|
|
30
41
|
background: var(--surface);
|
package/src/css/forms/form.css
CHANGED
|
@@ -6,23 +6,26 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Public API: .field, .field-label, .field-help, .field-error, .field-group,
|
|
8
8
|
* .required-mark.
|
|
9
|
+
*
|
|
10
|
+
* Public hooks:
|
|
11
|
+
* --fieldset-legend-padding-inline
|
|
9
12
|
*/
|
|
10
13
|
.field {
|
|
11
14
|
display: grid;
|
|
12
|
-
gap: var(--space-
|
|
15
|
+
gap: var(--space-10);
|
|
13
16
|
color: var(--text);
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
.field-group {
|
|
17
20
|
min-inline-size: 0;
|
|
18
21
|
margin: 0;
|
|
19
|
-
padding: var(--space-
|
|
22
|
+
padding: var(--space-30);
|
|
20
23
|
border: var(--border-width) solid var(--border);
|
|
21
24
|
border-radius: var(--radius);
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
.field-group + .field-group {
|
|
25
|
-
margin-block-start: var(--space-
|
|
28
|
+
margin-block-start: var(--space-40);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
.field-label,
|
|
@@ -33,7 +36,7 @@
|
|
|
33
36
|
|
|
34
37
|
.field-group > legend {
|
|
35
38
|
padding-block: 0;
|
|
36
|
-
padding-inline: var(--fieldset-legend-padding-inline, var(--space-
|
|
39
|
+
padding-inline: var(--fieldset-legend-padding-inline, var(--space-10));
|
|
37
40
|
font-size: var(--font-size-xs);
|
|
38
41
|
}
|
|
39
42
|
|
package/src/css/forms/index.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/* Forms — import order matters: switch.css
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
/* Forms — import order matters: switch.css follows choice.css so its rules
|
|
2
|
+
land after the shared choice recipe. validation.css is part of the default
|
|
3
|
+
forms bundle, but custom builds may omit it when validation styling is
|
|
4
|
+
app-owned. */
|
|
5
5
|
@import "./form.css";
|
|
6
6
|
@import "./control.css";
|
|
7
7
|
@import "./input-icon.css";
|