actual-css 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -1
- package/README.md +24 -9
- package/dist/actual-themes.min.css +1 -0
- package/dist/actual.css +1532 -1114
- package/dist/actual.js +1 -3
- package/dist/actual.min.css +1 -1
- package/dist/optional.css +1048 -0
- package/dist/optional.min.css +1 -0
- package/docs/design-notes/browser-support.md +94 -14
- package/docs/design-notes/cascade-layer.md +7 -6
- package/docs/design-notes/enhancement-contract.md +11 -14
- package/docs/design-notes/forced-colors.md +105 -0
- package/docs/design-notes/naming.md +2 -1
- package/docs/design-notes/platform-alignment.md +492 -0
- package/docs/design-notes/references.md +8 -0
- package/docs/design-notes/widget-primitives.md +37 -1
- package/docs/navigation.json +135 -0
- package/docs/pages/components/accordion.md +80 -0
- package/docs/pages/components/alert.md +203 -0
- package/docs/pages/components/aura.md +35 -0
- package/docs/pages/components/avatar.md +95 -0
- package/docs/pages/components/badge.md +102 -0
- package/docs/pages/components/breadcrumb.md +19 -0
- package/docs/pages/components/button.md +210 -0
- package/docs/pages/components/card.md +195 -0
- package/docs/pages/components/chat.md +50 -0
- package/docs/pages/components/dialog.md +367 -0
- package/docs/pages/components/drawer.md +113 -0
- package/docs/pages/components/fab.md +118 -0
- package/docs/pages/components/key.md +33 -0
- package/docs/pages/components/meter.md +23 -0
- package/docs/pages/components/navbar.md +92 -0
- package/docs/pages/components/pagination.md +55 -0
- package/docs/pages/components/progress.md +29 -0
- package/docs/pages/components/skeleton.md +38 -0
- package/docs/pages/components/spinner.md +93 -0
- package/docs/pages/components/table.md +102 -0
- package/docs/pages/enhancements/flyout.md +391 -0
- package/docs/pages/enhancements/overview.md +36 -0
- package/docs/pages/enhancements/scrollspy.md +71 -0
- package/docs/pages/enhancements/status-bar.md +72 -0
- package/docs/pages/enhancements/tabs.md +80 -0
- package/docs/pages/enhancements/tooltip.md +130 -0
- package/docs/pages/examples/overview.md +43 -0
- package/docs/pages/forms/choice-cards.md +102 -0
- package/docs/pages/forms/controls.md +32 -0
- package/docs/pages/forms/detached-actions.md +59 -0
- package/docs/pages/forms/floating-field.md +88 -0
- package/docs/pages/forms/form-actions.md +56 -0
- package/docs/pages/forms/input-policy.md +91 -0
- package/docs/pages/forms/joined-controls.md +37 -0
- package/docs/pages/forms/labels.md +42 -0
- package/docs/pages/forms/otp.md +50 -0
- package/docs/pages/forms/overview.md +188 -0
- package/docs/pages/forms/password.md +40 -0
- package/docs/pages/forms/range.md +17 -0
- package/docs/pages/forms/states-and-sizes.md +321 -0
- package/docs/pages/forms/sticky-actions.md +187 -0
- package/docs/pages/forms/switch.md +31 -0
- package/docs/pages/forms/validation.md +241 -0
- package/docs/{mental-model.md → pages/foundations/philosophy.md} +33 -18
- package/docs/pages/foundations/theming.md +99 -0
- package/docs/pages/foundations/tokens.md +421 -0
- package/docs/{typography.md → pages/foundations/typography.md} +27 -9
- package/docs/pages/guides/bootstrap.md +438 -0
- package/docs/pages/guides/introduction.md +157 -0
- package/docs/pages/guides/optional-components.md +33 -0
- package/docs/pages/guides/progressive-enhancement.md +686 -0
- package/docs/pages/guides/tailwind.md +455 -0
- package/docs/pages/layout/app-shell.md +25 -0
- package/docs/pages/layout/center.md +29 -0
- package/docs/pages/layout/cluster.md +59 -0
- package/docs/pages/layout/frame.md +30 -0
- package/docs/pages/layout/grid.md +142 -0
- package/docs/pages/layout/list.md +41 -0
- package/docs/pages/layout/media.md +28 -0
- package/docs/pages/layout/overview.md +37 -0
- package/docs/pages/layout/scroll-snap.md +54 -0
- package/docs/pages/layout/sidebar-layout.md +27 -0
- package/docs/pages/layout/stack.md +55 -0
- package/docs/pages/layout/switcher.md +36 -0
- package/docs/pages/layout/topbar.md +23 -0
- package/docs/pages/patterns/actions.md +52 -0
- package/docs/pages/patterns/code-block.md +36 -0
- package/docs/pages/patterns/exclusive-accordion.md +16 -0
- package/docs/pages/patterns/hierarchical-nav.md +26 -0
- package/docs/pages/patterns/icon-input.md +25 -0
- package/docs/pages/patterns/intent-nesting.md +3 -0
- package/docs/pages/patterns/navigation-list.md +235 -0
- package/docs/pages/patterns/overview.md +58 -0
- package/docs/pages/patterns/structured-lists.md +47 -0
- package/docs/pages/utilities/accessibility.md +34 -0
- package/docs/pages/utilities/flex.md +105 -0
- package/docs/pages/utilities/links.md +18 -0
- package/docs/pages/utilities/list.md +32 -0
- package/docs/pages/utilities/overflow.md +43 -0
- package/docs/pages/utilities/overview.md +18 -0
- package/docs/pages/utilities/shape.md +25 -0
- package/docs/pages/utilities/sizing-wrapping.md +115 -0
- package/docs/pages/utilities/spacing.md +79 -0
- package/docs/pages/utilities/text.md +43 -0
- package/llms.txt +4 -4
- package/package.json +21 -12
- package/src/css/actual.css +16 -2
- package/src/css/base.css +3 -5
- package/src/css/components/accordion.css +18 -30
- package/src/css/components/actions.css +4 -1
- package/src/css/components/alert.css +139 -102
- package/src/css/components/avatar.css +16 -10
- package/src/css/components/badge.css +69 -42
- package/src/css/components/breadcrumb.css +7 -15
- package/src/css/components/busy.css +6 -0
- package/src/css/components/button.css +84 -34
- package/src/css/components/card.css +26 -38
- package/src/css/components/drawer.css +30 -13
- package/src/css/components/flyout.css +39 -109
- package/src/css/components/index.css +1 -0
- package/src/css/components/join.css +14 -2
- package/src/css/components/key.css +2 -0
- package/src/css/components/menu.css +125 -0
- package/src/css/components/meter.css +0 -23
- package/src/css/components/modal.css +162 -7
- package/src/css/components/navbar.css +30 -23
- package/src/css/components/overline.css +8 -9
- package/src/css/components/pagination.css +1 -1
- package/src/css/components/progress.css +8 -26
- package/src/css/components/skeleton.css +7 -0
- package/src/css/components/spinner.css +6 -7
- package/src/css/components/status-bar.css +15 -24
- package/src/css/components/surface.css +2 -8
- package/src/css/components/tab.css +19 -48
- package/src/css/components/table.css +7 -5
- package/src/css/components/tooltip.css +14 -7
- package/src/css/focus.css +14 -38
- package/src/css/forms/choice-card.css +13 -14
- package/src/css/forms/choice.css +21 -27
- package/src/css/forms/control.css +18 -17
- package/src/css/forms/custom-select.css +9 -11
- package/src/css/forms/form-actions.css +14 -3
- package/src/css/forms/form.css +7 -4
- package/src/css/forms/index.css +4 -4
- package/src/css/forms/input-icon.css +30 -12
- package/src/css/forms/native.css +50 -11
- package/src/css/forms/range.css +17 -9
- package/src/css/forms/select.css +8 -8
- package/src/css/forms/switch.css +14 -12
- package/src/css/forms/validation.css +32 -5
- package/src/css/grid.css +32 -18
- package/src/css/intents.css +2 -2
- package/src/css/layout.css +45 -2
- package/src/css/optional/aura.css +93 -0
- package/src/css/optional/chat.css +105 -0
- package/src/css/optional/fab.css +104 -0
- package/src/css/optional/floating-field.css +87 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +7 -4
- package/src/css/optional/otp.css +115 -0
- package/src/css/optional/scroll-snap.css +6 -0
- package/src/css/optional/scroller.css +13 -7
- package/src/css/optional/typography-fluid.css +5 -0
- package/src/css/optional/utilities-extra.css +17 -2
- package/src/css/prose.css +18 -8
- package/src/css/reset.css +0 -10
- package/src/css/theme.css +21 -5
- package/src/css/themes/cyberpunk.css +1 -1
- package/src/css/themes/dim.css +3 -3
- package/src/css/themes/edge.css +8 -10
- package/src/css/themes/index.css +8 -4
- package/src/css/themes/{dark.css → indigo.css} +5 -4
- package/src/css/themes/neon.css +5 -5
- package/src/css/themes/square.css +0 -3
- package/src/css/tokens.css +74 -20
- package/src/css/utilities.css +8 -10
- package/src/css/variants.css +51 -66
- package/src/js/command.js +1 -3
- package/src/js/context-menu.js +67 -35
- package/src/js/dialog.js +68 -79
- package/src/js/dismiss.js +15 -0
- package/src/js/enhance.js +54 -23
- package/src/js/enhancement-loader.js +301 -0
- package/src/js/events.js +3 -0
- package/src/js/filter.js +3 -3
- package/src/js/floating.js +101 -131
- package/src/js/flyout.js +104 -87
- package/src/js/focus-group.js +116 -0
- package/src/js/focus.js +6 -1
- package/src/js/index.js +4 -2
- package/src/js/input.js +1 -1
- package/src/js/keys.js +27 -0
- package/src/js/mask.js +7 -6
- package/src/js/menu.js +87 -34
- package/src/js/parse-config.js +47 -0
- package/src/js/password.js +9 -1
- package/src/js/scrollspy.js +12 -4
- package/src/js/selectors.js +0 -7
- package/src/js/status.js +3 -1
- package/src/js/surface.js +187 -136
- package/src/js/tab.js +36 -53
- package/src/js/tooltip.js +70 -35
- package/src/js/validation.js +34 -8
- package/dist/actual.js.map +0 -31
- package/docs/README.md +0 -28
- package/docs/components.md +0 -860
- package/docs/design-notes/previous-work.md +0 -5
- package/docs/forms.md +0 -1265
- package/docs/javascript.md +0 -496
- package/docs/layout.md +0 -480
- package/docs/patterns.md +0 -504
- package/docs/reserved.md +0 -7
- package/docs/tokens.md +0 -455
- package/docs/ui.md +0 -929
- package/docs/utilities.md +0 -384
- package/src/css/dialog-fallback.css +0 -56
- package/src/js/dialog-fallback.js +0 -163
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Menu — action list primitive consumed by flyout and context-menu.
|
|
3
|
+
*
|
|
4
|
+
* Strict anatomy: .menu > li > .menu-item. Separators and section labels
|
|
5
|
+
* sit directly under .menu as siblings of <li>.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --menu-item-icon-size
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
.menu {
|
|
12
|
+
display: grid;
|
|
13
|
+
gap: var(--space-10);
|
|
14
|
+
margin: 0;
|
|
15
|
+
padding: var(--space-10);
|
|
16
|
+
list-style: none;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.menu > li {
|
|
20
|
+
margin: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.menu-item {
|
|
24
|
+
--menu-item-icon-size: 1.25em;
|
|
25
|
+
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
gap: var(--space-20);
|
|
29
|
+
inline-size: 100%;
|
|
30
|
+
min-block-size: var(--menu-item-size, var(--control-size));
|
|
31
|
+
padding-inline: var(--space-20);
|
|
32
|
+
border: 0;
|
|
33
|
+
border-radius: var(--radius-sm);
|
|
34
|
+
background: transparent;
|
|
35
|
+
color: var(--text);
|
|
36
|
+
font: inherit;
|
|
37
|
+
text-align: start;
|
|
38
|
+
text-decoration: none;
|
|
39
|
+
white-space: nowrap;
|
|
40
|
+
cursor: pointer;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.menu-item-icon {
|
|
44
|
+
display: grid;
|
|
45
|
+
flex: 0 0 var(--menu-item-icon-size);
|
|
46
|
+
inline-size: var(--menu-item-icon-size);
|
|
47
|
+
place-items: center;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.menu-item-text {
|
|
51
|
+
flex: 1;
|
|
52
|
+
min-inline-size: 0;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
text-overflow: ellipsis;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.menu-item-end {
|
|
58
|
+
display: inline-flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
gap: var(--space-10);
|
|
61
|
+
margin-inline-start: auto;
|
|
62
|
+
color: var(--text-muted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* Checkable menu items are one command with one accessible state. Their
|
|
66
|
+
indicator is generated so authors do not add a second interactive input. */
|
|
67
|
+
.menu-item:is([role="menuitemcheckbox"], [role="menuitemradio"])::before {
|
|
68
|
+
display: grid;
|
|
69
|
+
flex: 0 0 var(--menu-item-icon-size);
|
|
70
|
+
inline-size: var(--menu-item-icon-size);
|
|
71
|
+
place-items: center;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.menu-item[role="menuitemcheckbox"]::before {
|
|
75
|
+
content: "";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.menu-item[role="menuitemcheckbox"][aria-checked="true"]::before {
|
|
79
|
+
content: "✓";
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.menu-item[role="menuitemcheckbox"][aria-checked="mixed"]::before {
|
|
83
|
+
content: "−";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.menu-item[role="menuitemradio"]::before {
|
|
87
|
+
content: "○";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.menu-item[role="menuitemradio"][aria-checked="true"]::before {
|
|
91
|
+
content: "●";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.menu-item:focus-visible {
|
|
95
|
+
background: var(--surface-subtle);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.menu-item:hover:not(:where(:disabled, [aria-disabled="true"])) {
|
|
99
|
+
background: var(--surface-subtle);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.menu-item:is(:disabled, [aria-disabled="true"]) {
|
|
103
|
+
cursor: not-allowed;
|
|
104
|
+
opacity: var(--disabled-opacity);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.menu-label {
|
|
108
|
+
padding: var(--space-20);
|
|
109
|
+
color: var(--text-muted);
|
|
110
|
+
font-size: var(--font-size-xs);
|
|
111
|
+
font-weight: var(--font-weight-strong);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.menu-separator {
|
|
115
|
+
margin: 0;
|
|
116
|
+
border: 0;
|
|
117
|
+
border-block-start: var(--border-width) solid var(--border);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@media (forced-colors: active) {
|
|
121
|
+
.menu-item:focus-visible {
|
|
122
|
+
outline: var(--border-width) solid ButtonText;
|
|
123
|
+
outline-offset: -1px;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -4,18 +4,6 @@
|
|
|
4
4
|
* Maps the three standard meter zones (optimum / suboptimum / even-less-good)
|
|
5
5
|
* to the shared success / warning / danger intent colors.
|
|
6
6
|
*/
|
|
7
|
-
/* Intent boundary — inherited intents do not tint this component.
|
|
8
|
-
Local intent classes still win because :where() has zero specificity. */
|
|
9
|
-
:where(.meter) {
|
|
10
|
-
/* @sync intent-boundary */
|
|
11
|
-
--intent: initial;
|
|
12
|
-
--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
|
-
}
|
|
19
7
|
|
|
20
8
|
.meter {
|
|
21
9
|
appearance: none;
|
|
@@ -61,21 +49,10 @@
|
|
|
61
49
|
}
|
|
62
50
|
|
|
63
51
|
@media (forced-colors: active) {
|
|
64
|
-
.meter {
|
|
65
|
-
border: var(--border-width) solid ButtonText;
|
|
66
|
-
background: Canvas;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
.meter::-webkit-meter-bar {
|
|
70
|
-
border: 0;
|
|
71
|
-
background: Canvas;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
52
|
.meter::-webkit-meter-optimum-value,
|
|
75
53
|
.meter::-webkit-meter-suboptimum-value,
|
|
76
54
|
.meter::-webkit-meter-even-less-good-value,
|
|
77
55
|
.meter::-moz-meter-bar {
|
|
78
56
|
background: Highlight;
|
|
79
|
-
forced-color-adjust: none;
|
|
80
57
|
}
|
|
81
58
|
}
|
|
@@ -3,12 +3,30 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Spacing, radius, transitions, and focus treatment come from shared tokens.
|
|
5
5
|
* Opening behavior and intent-specific decisions stay outside this component.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --modal-size
|
|
9
|
+
* --dialog-viewport-gap
|
|
10
|
+
* --dialog-icon-size
|
|
11
|
+
* --dialog-icon-glyph-size
|
|
12
|
+
*
|
|
13
|
+
* Internal:
|
|
14
|
+
* --dialog-close-icon-size
|
|
15
|
+
* --dialog-viewport-gap-2x
|
|
6
16
|
*/
|
|
7
17
|
dialog.modal {
|
|
8
18
|
--modal-size: 32rem;
|
|
19
|
+
--dialog-viewport-gap: var(--space-40);
|
|
20
|
+
/* calc() multiplication is not in the supported browser range, so the
|
|
21
|
+
doubled gap is spelled out with an additive calc. */
|
|
22
|
+
--dialog-viewport-gap-2x: calc(var(--dialog-viewport-gap) + var(--dialog-viewport-gap));
|
|
23
|
+
|
|
24
|
+
/* Keep the surface anchored to the viewport in the top layer. This also
|
|
25
|
+
provides the containing block for the absolutely positioned close button. */
|
|
26
|
+
position: fixed;
|
|
9
27
|
|
|
10
|
-
max-inline-size: min(100% -
|
|
11
|
-
max-block-size: calc(var(--viewport-block) -
|
|
28
|
+
max-inline-size: min(calc(100% - var(--dialog-viewport-gap-2x)), var(--modal-size));
|
|
29
|
+
max-block-size: calc(var(--viewport-block) - var(--dialog-viewport-gap-2x));
|
|
12
30
|
border: var(--border-width) solid var(--border);
|
|
13
31
|
border-radius: var(--radius-lg);
|
|
14
32
|
background: var(--surface-raised);
|
|
@@ -32,11 +50,18 @@ dialog.modal {
|
|
|
32
50
|
dialog.modal > form,
|
|
33
51
|
dialog.modal > .stack {
|
|
34
52
|
display: grid;
|
|
35
|
-
gap: var(--space-
|
|
36
|
-
max-block-size: calc(var(--viewport-block) -
|
|
53
|
+
gap: var(--space-40);
|
|
54
|
+
max-block-size: calc(var(--viewport-block) - var(--dialog-viewport-gap-2x));
|
|
37
55
|
overflow: auto;
|
|
38
56
|
overscroll-behavior: contain;
|
|
39
|
-
padding: var(--space-
|
|
57
|
+
padding: var(--space-40);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Keep the dialog off the viewport edges on small screens. */
|
|
61
|
+
@media (max-width: 30rem) {
|
|
62
|
+
dialog.modal {
|
|
63
|
+
--dialog-viewport-gap: var(--space-30);
|
|
64
|
+
}
|
|
40
65
|
}
|
|
41
66
|
|
|
42
67
|
dialog.modal.scrollable > form,
|
|
@@ -62,6 +87,13 @@ dialog.modal footer > :last-child {
|
|
|
62
87
|
margin-block-end: 0;
|
|
63
88
|
}
|
|
64
89
|
|
|
90
|
+
/* The close button is anchored to the dialog at top inline-end, out of the
|
|
91
|
+
content flow; headers reserve inline room so titles never run under it. */
|
|
92
|
+
dialog.modal > form > header,
|
|
93
|
+
dialog.modal > .stack > header {
|
|
94
|
+
padding-inline-end: calc(var(--control-size) + var(--space-30));
|
|
95
|
+
}
|
|
96
|
+
|
|
65
97
|
dialog.modal footer {
|
|
66
98
|
display: flex;
|
|
67
99
|
flex-wrap: wrap;
|
|
@@ -69,6 +101,65 @@ dialog.modal footer {
|
|
|
69
101
|
gap: var(--gap);
|
|
70
102
|
}
|
|
71
103
|
|
|
104
|
+
/* Confirmation layout — a focused message followed by a visually distinct
|
|
105
|
+
action band. The media primitive owns icon/content alignment; this variant
|
|
106
|
+
only removes the standard form inset so both regions can own their padding. */
|
|
107
|
+
dialog.modal.dialog-confirmation > form {
|
|
108
|
+
gap: 0;
|
|
109
|
+
padding: 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
dialog.modal.dialog-confirmation > form > .media {
|
|
113
|
+
gap: var(--space-40);
|
|
114
|
+
padding: var(--space-50);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
dialog.modal.dialog-confirmation > form > footer {
|
|
118
|
+
padding: var(--space-40) var(--space-50);
|
|
119
|
+
border-end-start-radius: calc(var(--radius-lg) - var(--border-width));
|
|
120
|
+
border-end-end-radius: calc(var(--radius-lg) - var(--border-width));
|
|
121
|
+
background: var(--surface-subtle);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/* Intent boundary — inherited intents do not tint the icon well. A local
|
|
125
|
+
intent plus .soft opts into the shared soft-variant recipe. */
|
|
126
|
+
:where(.dialog-icon) {
|
|
127
|
+
--intent: initial;
|
|
128
|
+
--intent-fg: initial;
|
|
129
|
+
--ui-bg: initial;
|
|
130
|
+
--ui-fg: initial;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.dialog-icon {
|
|
134
|
+
--dialog-icon-size: 3rem;
|
|
135
|
+
--dialog-icon-glyph-size: 1.5rem;
|
|
136
|
+
|
|
137
|
+
display: inline-grid;
|
|
138
|
+
place-items: center;
|
|
139
|
+
inline-size: var(--dialog-icon-size);
|
|
140
|
+
block-size: var(--dialog-icon-size);
|
|
141
|
+
flex: none;
|
|
142
|
+
border-radius: var(--radius-full);
|
|
143
|
+
background: var(--ui-bg, var(--surface-subtle));
|
|
144
|
+
color: var(--ui-fg, var(--intent, var(--text-muted)));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.dialog-icon > * {
|
|
148
|
+
display: inline-grid;
|
|
149
|
+
place-items: center;
|
|
150
|
+
inline-size: var(--dialog-icon-glyph-size);
|
|
151
|
+
block-size: var(--dialog-icon-glyph-size);
|
|
152
|
+
font-size: var(--dialog-icon-glyph-size);
|
|
153
|
+
line-height: 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
@media (max-width: 30rem) {
|
|
157
|
+
dialog.modal.dialog-confirmation > form > .media,
|
|
158
|
+
dialog.modal.dialog-confirmation > form > footer {
|
|
159
|
+
padding: var(--space-40);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
72
163
|
dialog.modal[open] {
|
|
73
164
|
opacity: 1;
|
|
74
165
|
transform: none;
|
|
@@ -124,7 +215,7 @@ html.has-modal-open.had-scrollbar {
|
|
|
124
215
|
|
|
125
216
|
@media (prefers-reduced-motion: no-preference) {
|
|
126
217
|
dialog.modal.is-static {
|
|
127
|
-
animation: actual-
|
|
218
|
+
animation: actual-dialog-static var(--duration-slow) var(--ease);
|
|
128
219
|
}
|
|
129
220
|
|
|
130
221
|
::view-transition-group(actual-dialog) {
|
|
@@ -133,7 +224,7 @@ html.has-modal-open.had-scrollbar {
|
|
|
133
224
|
}
|
|
134
225
|
}
|
|
135
226
|
|
|
136
|
-
@keyframes actual-
|
|
227
|
+
@keyframes actual-dialog-static {
|
|
137
228
|
0%,
|
|
138
229
|
100% {
|
|
139
230
|
transform: none;
|
|
@@ -159,4 +250,68 @@ html.has-modal-open.had-scrollbar {
|
|
|
159
250
|
dialog.modal::backdrop {
|
|
160
251
|
background: Canvas;
|
|
161
252
|
}
|
|
253
|
+
|
|
254
|
+
.dialog-icon {
|
|
255
|
+
border: var(--border-width) solid CanvasText;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Close controls. A close button is an action attached to a surface, so it
|
|
260
|
+
never participates in the content flow. The modal and the drawer share the
|
|
261
|
+
same simple placement — absolute at the panel's top inline-end, inside the
|
|
262
|
+
surface — so both close buttons look and behave identically. The glyph comes
|
|
263
|
+
from --icon-close, masked to currentColor, so no icon font or text glyph is
|
|
264
|
+
required in the markup. */
|
|
265
|
+
.dialog-close,
|
|
266
|
+
.drawer-close {
|
|
267
|
+
--dialog-close-icon-size: 1rem;
|
|
268
|
+
|
|
269
|
+
display: inline-grid;
|
|
270
|
+
place-items: center;
|
|
271
|
+
padding: 0;
|
|
272
|
+
border: 0;
|
|
273
|
+
border-radius: var(--radius);
|
|
274
|
+
color: var(--text-muted);
|
|
275
|
+
cursor: pointer;
|
|
276
|
+
|
|
277
|
+
/* Out of flow, anchored to the positioned dialog surface, not the header or
|
|
278
|
+
any scroll container inside it. */
|
|
279
|
+
position: absolute;
|
|
280
|
+
z-index: 1;
|
|
281
|
+
inset-block-start: var(--space-20);
|
|
282
|
+
inset-inline-end: var(--space-20);
|
|
283
|
+
|
|
284
|
+
inline-size: var(--control-size);
|
|
285
|
+
block-size: var(--control-size);
|
|
286
|
+
|
|
287
|
+
background: var(--surface-subtle);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.dialog-close::before,
|
|
291
|
+
.drawer-close::before {
|
|
292
|
+
content: "";
|
|
293
|
+
inline-size: var(--dialog-close-icon-size);
|
|
294
|
+
block-size: var(--dialog-close-icon-size);
|
|
295
|
+
background: currentColor;
|
|
296
|
+
-webkit-mask: var(--icon-close) center / contain no-repeat;
|
|
297
|
+
mask: var(--icon-close) center / contain no-repeat;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@media (hover: hover) {
|
|
301
|
+
.dialog-close:hover,
|
|
302
|
+
.drawer-close:hover {
|
|
303
|
+
box-shadow: inset 0 0 0 999px var(--hover-overlay);
|
|
304
|
+
color: var(--text);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.dialog-close:active,
|
|
309
|
+
.drawer-close:active {
|
|
310
|
+
box-shadow: inset 0 0 0 999px var(--hover-overlay);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.dialog-close:focus-visible,
|
|
314
|
+
.drawer-close:focus-visible {
|
|
315
|
+
outline: 2px solid transparent;
|
|
316
|
+
box-shadow: var(--focus-ring-shadow);
|
|
162
317
|
}
|
|
@@ -4,26 +4,37 @@
|
|
|
4
4
|
* .navbar is a horizontal bar; .navbar-brand is the brand link; .navbar-nav is
|
|
5
5
|
* the inline link list using .nav-link items. .nav-list is the vertical nav
|
|
6
6
|
* list shared with .drawer, fed by the shared --gap token.
|
|
7
|
+
*
|
|
8
|
+
* Internal:
|
|
9
|
+
* --gap (local value for the shared gap token)
|
|
7
10
|
*/
|
|
11
|
+
/* Intent boundary — inherited intents do not tint this component.
|
|
12
|
+
Local intent classes still win because :where() has zero specificity. */
|
|
13
|
+
:where(.navbar) {
|
|
14
|
+
--ui-bg: initial;
|
|
15
|
+
--ui-fg: initial;
|
|
16
|
+
--ui-border: initial;
|
|
17
|
+
}
|
|
18
|
+
|
|
8
19
|
.navbar {
|
|
9
20
|
display: flex;
|
|
10
21
|
flex-wrap: wrap;
|
|
11
22
|
align-items: center;
|
|
12
23
|
justify-content: space-between;
|
|
13
24
|
gap: var(--gap);
|
|
14
|
-
padding-block: var(--space-
|
|
15
|
-
padding-inline: var(--space-
|
|
16
|
-
border: var(--border-width) solid var(--border);
|
|
25
|
+
padding-block: var(--space-30);
|
|
26
|
+
padding-inline: var(--space-40);
|
|
27
|
+
border: var(--border-width) solid var(--ui-border, var(--border));
|
|
17
28
|
border-radius: var(--radius-lg);
|
|
18
|
-
background: var(--surface-raised);
|
|
19
|
-
color: var(--text);
|
|
29
|
+
background: var(--ui-bg, var(--surface-raised));
|
|
30
|
+
color: var(--ui-fg, var(--text));
|
|
20
31
|
}
|
|
21
32
|
|
|
22
33
|
.navbar-brand {
|
|
23
34
|
display: inline-flex;
|
|
24
35
|
align-items: center;
|
|
25
|
-
gap: var(--space-
|
|
26
|
-
color: var(--text);
|
|
36
|
+
gap: var(--space-20);
|
|
37
|
+
color: var(--ui-fg, var(--text));
|
|
27
38
|
font-weight: var(--font-weight-bold);
|
|
28
39
|
text-decoration: none;
|
|
29
40
|
}
|
|
@@ -36,7 +47,7 @@
|
|
|
36
47
|
display: flex;
|
|
37
48
|
flex-wrap: wrap;
|
|
38
49
|
align-items: center;
|
|
39
|
-
gap: var(--space-
|
|
50
|
+
gap: var(--space-10);
|
|
40
51
|
margin: 0;
|
|
41
52
|
padding: 0;
|
|
42
53
|
list-style: none;
|
|
@@ -46,9 +57,9 @@
|
|
|
46
57
|
display: inline-flex;
|
|
47
58
|
align-items: center;
|
|
48
59
|
min-block-size: var(--control-size-sm);
|
|
49
|
-
padding-inline: var(--space-
|
|
60
|
+
padding-inline: var(--space-20);
|
|
50
61
|
border-radius: var(--radius);
|
|
51
|
-
color: var(--text-muted);
|
|
62
|
+
color: var(--ui-fg, var(--text-muted));
|
|
52
63
|
font-weight: var(--font-weight-medium);
|
|
53
64
|
text-decoration: none;
|
|
54
65
|
}
|
|
@@ -58,21 +69,19 @@
|
|
|
58
69
|
color: var(--text);
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
color: var(--text);
|
|
65
|
-
}
|
|
72
|
+
.nav-link:hover {
|
|
73
|
+
background: var(--surface-subtle);
|
|
74
|
+
color: var(--text);
|
|
66
75
|
}
|
|
67
76
|
|
|
68
77
|
/* Nav list — a vertical navigation list. Used by .drawer for stacked links. */
|
|
69
78
|
.nav-list {
|
|
70
79
|
display: grid;
|
|
80
|
+
--gap: var(--space-20);
|
|
71
81
|
gap: var(--gap);
|
|
72
82
|
margin: 0;
|
|
73
83
|
padding: 0;
|
|
74
84
|
list-style: none;
|
|
75
|
-
--gap: var(--space-2);
|
|
76
85
|
}
|
|
77
86
|
|
|
78
87
|
.nav-list > li {
|
|
@@ -87,12 +96,10 @@
|
|
|
87
96
|
forced-color-adjust: none;
|
|
88
97
|
}
|
|
89
98
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
color: CanvasText;
|
|
96
|
-
}
|
|
99
|
+
.nav-link:hover:not(:where([aria-current]:not([aria-current="false"]))) {
|
|
100
|
+
outline: var(--border-width) solid ButtonText;
|
|
101
|
+
outline-offset: 2px;
|
|
102
|
+
background: Canvas;
|
|
103
|
+
color: CanvasText;
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -4,22 +4,17 @@
|
|
|
4
4
|
* Base form is unstyled chrome that takes its surrounding color. Add .pill for
|
|
5
5
|
* the bordered rounded shape, and combine with an intent class (.primary,
|
|
6
6
|
* .success, etc.) to tint the text, border, and background.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --overline-radius
|
|
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(.overline) {
|
|
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
|
.overline {
|
|
22
|
-
align-self: flex-start;
|
|
23
18
|
color: var(--text-muted);
|
|
24
19
|
font-size: var(--font-size-sm);
|
|
25
20
|
font-weight: var(--font-weight-medium);
|
|
@@ -28,14 +23,18 @@
|
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
.overline.pill {
|
|
26
|
+
--overline-radius: var(--radius-full);
|
|
27
|
+
|
|
31
28
|
display: inline-flex;
|
|
32
29
|
align-items: center;
|
|
33
30
|
gap: 0.5em;
|
|
34
31
|
padding-inline: 0.6em;
|
|
35
32
|
padding-block: 0.25em;
|
|
33
|
+
inline-size: fit-content;
|
|
34
|
+
max-inline-size: 100%;
|
|
36
35
|
color: var(--intent, var(--text-muted));
|
|
37
36
|
border: var(--border-width) solid var(--border);
|
|
38
|
-
border-radius: var(--radius
|
|
37
|
+
border-radius: var(--overline-radius);
|
|
39
38
|
background: var(--surface);
|
|
40
39
|
}
|
|
41
40
|
|
|
@@ -3,26 +3,21 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Consumes the shared --intent/--primary for the value bar and --bar-height
|
|
5
5
|
* for thickness. Indeterminate state animates a shimmer using --duration-shimmer.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --progress-track
|
|
9
|
+
* --progress-value
|
|
6
10
|
*/
|
|
7
11
|
/* Intent boundary — inherited intents do not tint this component.
|
|
8
12
|
Local intent classes still win because :where() has zero specificity. */
|
|
9
13
|
:where(.progress) {
|
|
10
|
-
/* @sync intent-boundary */
|
|
11
14
|
--intent: initial;
|
|
12
|
-
--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
15
|
}
|
|
19
16
|
|
|
20
17
|
.progress {
|
|
21
18
|
--progress-track: var(--surface-subtle);
|
|
22
19
|
--progress-value: var(--intent, var(--primary));
|
|
23
|
-
}
|
|
24
20
|
|
|
25
|
-
.progress {
|
|
26
21
|
appearance: none;
|
|
27
22
|
-webkit-appearance: none;
|
|
28
23
|
display: block;
|
|
@@ -101,26 +96,13 @@
|
|
|
101
96
|
}
|
|
102
97
|
|
|
103
98
|
@media (forced-colors: active) {
|
|
104
|
-
.progress
|
|
105
|
-
|
|
106
|
-
background: Canvas;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.progress::-webkit-progress-bar {
|
|
110
|
-
background: Canvas;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.progress::-webkit-progress-value {
|
|
99
|
+
.progress::-webkit-progress-value,
|
|
100
|
+
.progress:indeterminate::-webkit-progress-value {
|
|
114
101
|
background: Highlight;
|
|
115
|
-
forced-color-adjust: none;
|
|
116
102
|
}
|
|
117
103
|
|
|
118
|
-
.progress::-moz-progress-bar
|
|
104
|
+
.progress::-moz-progress-bar,
|
|
105
|
+
.progress:indeterminate::-moz-progress-bar {
|
|
119
106
|
background: Highlight;
|
|
120
|
-
forced-color-adjust: none;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
.progress:indeterminate {
|
|
124
|
-
background: Canvas;
|
|
125
107
|
}
|
|
126
108
|
}
|
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Shows approximate loading structure without implying real content hierarchy.
|
|
5
5
|
* Geometry, animation, and color stay theme-aware.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --skeleton-size
|
|
9
|
+
* --skeleton-width
|
|
10
|
+
* --skeleton-radius
|
|
11
|
+
* --skeleton-track
|
|
12
|
+
* --skeleton-highlight
|
|
6
13
|
*/
|
|
7
14
|
.skeleton {
|
|
8
15
|
--skeleton-size: 1rem;
|
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Uses currentColor so it adapts to buttons, alerts, badges, and text. The
|
|
5
5
|
* [aria-busy] overlay composition lives in components/busy.css.
|
|
6
|
+
*
|
|
7
|
+
* Public hooks:
|
|
8
|
+
* --spinner-size
|
|
9
|
+
* --spinner-width
|
|
10
|
+
* --spinner-track
|
|
11
|
+
* --spinner-value
|
|
6
12
|
*/
|
|
7
13
|
/* Intent boundary — inherited intents do not tint this component.
|
|
8
14
|
Local intent classes still win because :where() has zero specificity. */
|
|
9
15
|
:where(.spinner) {
|
|
10
|
-
/* @sync intent-boundary */
|
|
11
16
|
--intent: initial;
|
|
12
|
-
--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
17
|
}
|
|
19
18
|
|
|
20
19
|
.spinner {
|