actual-css 0.1.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 +11 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/dist/actual.css +4929 -0
- package/dist/actual.js +3 -0
- package/dist/actual.js.map +31 -0
- package/dist/actual.min.css +1 -0
- package/docs/README.md +26 -0
- package/docs/components.md +860 -0
- package/docs/design-notes/accessibility-decisions.md +32 -0
- package/docs/design-notes/browser-support.md +93 -0
- package/docs/design-notes/cascade-layer.md +52 -0
- package/docs/design-notes/css-anchor.md +33 -0
- package/docs/design-notes/naming.md +37 -0
- package/docs/design-notes/previous-work.md +5 -0
- package/docs/design-notes/references.md +324 -0
- package/docs/forms.md +1265 -0
- package/docs/javascript.md +426 -0
- package/docs/layout.md +480 -0
- package/docs/mental-model.md +73 -0
- package/docs/patterns.md +415 -0
- package/docs/reserved.md +7 -0
- package/docs/tokens.md +455 -0
- package/docs/typography.md +159 -0
- package/docs/ui.md +937 -0
- package/docs/utilities.md +384 -0
- package/llms.txt +17 -0
- package/package.json +101 -0
- package/src/css/actual.css +17 -0
- package/src/css/actual.full.css +2 -0
- package/src/css/actual.layer.css +3 -0
- package/src/css/base.css +70 -0
- package/src/css/components/accordion.css +97 -0
- package/src/css/components/actions.css +21 -0
- package/src/css/components/alert.css +137 -0
- package/src/css/components/avatar.css +199 -0
- package/src/css/components/badge.css +143 -0
- package/src/css/components/breadcrumb.css +56 -0
- package/src/css/components/busy.css +44 -0
- package/src/css/components/button.css +216 -0
- package/src/css/components/card.css +140 -0
- package/src/css/components/drawer.css +122 -0
- package/src/css/components/flyout.css +243 -0
- package/src/css/components/index.css +41 -0
- package/src/css/components/join.css +106 -0
- package/src/css/components/key.css +25 -0
- package/src/css/components/meter.css +81 -0
- package/src/css/components/modal.css +162 -0
- package/src/css/components/navbar.css +98 -0
- package/src/css/components/overline.css +49 -0
- package/src/css/components/pagination.css +30 -0
- package/src/css/components/progress.css +126 -0
- package/src/css/components/scrollspy.css +27 -0
- package/src/css/components/skeleton.css +67 -0
- package/src/css/components/spinner.css +60 -0
- package/src/css/components/status-bar.css +82 -0
- package/src/css/components/surface.css +48 -0
- package/src/css/components/tab.css +128 -0
- package/src/css/components/table.css +64 -0
- package/src/css/components/tooltip.css +107 -0
- package/src/css/dialog-fallback.css +56 -0
- package/src/css/focus.css +13 -0
- package/src/css/forms/choice-card.css +158 -0
- package/src/css/forms/choice.css +196 -0
- package/src/css/forms/control.css +106 -0
- package/src/css/forms/custom-select.css +93 -0
- package/src/css/forms/form-actions.css +43 -0
- package/src/css/forms/form.css +57 -0
- package/src/css/forms/index.css +15 -0
- package/src/css/forms/input-icon.css +36 -0
- package/src/css/forms/native.css +68 -0
- package/src/css/forms/select.css +36 -0
- package/src/css/forms/switch.css +127 -0
- package/src/css/forms/validation.css +63 -0
- package/src/css/grid.css +95 -0
- package/src/css/intents.css +33 -0
- package/src/css/layout.css +80 -0
- package/src/css/optional/index.css +5 -0
- package/src/css/optional/layout-extra.css +55 -0
- package/src/css/optional/scroll-snap.css +51 -0
- package/src/css/optional/scroller.css +51 -0
- package/src/css/optional/typography-fluid.css +48 -0
- package/src/css/optional/utilities-extra.css +289 -0
- package/src/css/print.css +47 -0
- package/src/css/prose.css +187 -0
- package/src/css/reset.css +56 -0
- package/src/css/theme.css +186 -0
- package/src/css/themes/corporate.css +60 -0
- package/src/css/themes/cyberpunk.css +60 -0
- package/src/css/themes/dark.css +32 -0
- package/src/css/themes/dim.css +33 -0
- package/src/css/themes/edge.css +143 -0
- package/src/css/themes/forest.css +65 -0
- package/src/css/themes/gradient.css +97 -0
- package/src/css/themes/index.css +43 -0
- package/src/css/themes/lavender.css +66 -0
- package/src/css/themes/mono.css +60 -0
- package/src/css/themes/neon.css +66 -0
- package/src/css/themes/ocean.css +60 -0
- package/src/css/themes/petrol.css +64 -0
- package/src/css/themes/spruce.css +64 -0
- package/src/css/themes/square.css +68 -0
- package/src/css/themes/sunset.css +66 -0
- package/src/css/tokens.css +122 -0
- package/src/css/utilities.css +162 -0
- package/src/css/variants.css +118 -0
- package/src/js/command.js +165 -0
- package/src/js/context-menu.js +291 -0
- package/src/js/dialog-fallback.js +163 -0
- package/src/js/dialog.js +503 -0
- package/src/js/enhance.js +208 -0
- package/src/js/events.js +22 -0
- package/src/js/filter.js +122 -0
- package/src/js/floating.js +462 -0
- package/src/js/flyout.js +187 -0
- package/src/js/focus.js +35 -0
- package/src/js/index.js +26 -0
- package/src/js/input.js +47 -0
- package/src/js/keys.js +30 -0
- package/src/js/mask.js +184 -0
- package/src/js/menu.js +88 -0
- package/src/js/password.js +98 -0
- package/src/js/scrollspy.js +121 -0
- package/src/js/selectors.js +59 -0
- package/src/js/status.js +158 -0
- package/src/js/surface.js +358 -0
- package/src/js/tab.js +173 -0
- package/src/js/tooltip.js +374 -0
- package/src/js/validation.js +419 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/* Controls */
|
|
2
|
+
@import "button.css";
|
|
3
|
+
@import "badge.css";
|
|
4
|
+
@import "alert.css";
|
|
5
|
+
@import "actions.css";
|
|
6
|
+
|
|
7
|
+
/* Surfaces */
|
|
8
|
+
@import "card.css";
|
|
9
|
+
@import "surface.css";
|
|
10
|
+
@import "modal.css";
|
|
11
|
+
@import "drawer.css";
|
|
12
|
+
|
|
13
|
+
/* Overlays */
|
|
14
|
+
@import "flyout.css";
|
|
15
|
+
@import "tooltip.css";
|
|
16
|
+
|
|
17
|
+
/* Disclosure */
|
|
18
|
+
@import "accordion.css";
|
|
19
|
+
|
|
20
|
+
/* Feedback */
|
|
21
|
+
@import "spinner.css";
|
|
22
|
+
@import "skeleton.css";
|
|
23
|
+
@import "busy.css";
|
|
24
|
+
@import "progress.css";
|
|
25
|
+
@import "status-bar.css";
|
|
26
|
+
|
|
27
|
+
/* Display */
|
|
28
|
+
@import "avatar.css";
|
|
29
|
+
@import "key.css";
|
|
30
|
+
@import "overline.css";
|
|
31
|
+
|
|
32
|
+
/* Navigation */
|
|
33
|
+
@import "navbar.css";
|
|
34
|
+
@import "breadcrumb.css";
|
|
35
|
+
@import "pagination.css";
|
|
36
|
+
@import "tab.css";
|
|
37
|
+
@import "scrollspy.css";
|
|
38
|
+
|
|
39
|
+
/* Data */
|
|
40
|
+
@import "table.css";
|
|
41
|
+
@import "meter.css";
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Join — visually groups adjacent controls into a single unit.
|
|
3
|
+
*
|
|
4
|
+
* This is a cross-cutting control primitive, not a forms-only component:
|
|
5
|
+
* it applies equally to inputs, selects, buttons, and button-like links.
|
|
6
|
+
*
|
|
7
|
+
* Cascade note: .join writes border-radius longhands on its direct children.
|
|
8
|
+
* Keep this file loaded after control/component styles so those corners win at
|
|
9
|
+
* equal specificity.
|
|
10
|
+
*/
|
|
11
|
+
.join {
|
|
12
|
+
--join-radius: var(--radius);
|
|
13
|
+
--join-ss: 0;
|
|
14
|
+
--join-se: 0;
|
|
15
|
+
--join-es: 0;
|
|
16
|
+
--join-ee: 0;
|
|
17
|
+
|
|
18
|
+
align-items: stretch;
|
|
19
|
+
display: inline-flex;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* The .circle utility cannot round a join: corners are written as longhands
|
|
23
|
+
on the children below, so the group radius must flow through the token. */
|
|
24
|
+
.join.circle {
|
|
25
|
+
--join-radius: var(--radius-full);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.join-addon {
|
|
29
|
+
--control-border: var(--border);
|
|
30
|
+
--control-bg: var(--surface-subtle);
|
|
31
|
+
--control-fg: var(--text-muted);
|
|
32
|
+
|
|
33
|
+
align-items: center;
|
|
34
|
+
display: inline-flex;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
min-block-size: var(--control-size);
|
|
37
|
+
padding-inline: var(--space-3);
|
|
38
|
+
border: var(--border-width) solid var(--control-border);
|
|
39
|
+
border-radius: var(--radius);
|
|
40
|
+
background: var(--control-bg);
|
|
41
|
+
color: var(--control-fg);
|
|
42
|
+
font-size: var(--control-font-size);
|
|
43
|
+
line-height: 1;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.join > * {
|
|
48
|
+
border-start-start-radius: var(--join-ss);
|
|
49
|
+
border-start-end-radius: var(--join-se);
|
|
50
|
+
border-end-end-radius: var(--join-ee);
|
|
51
|
+
border-end-start-radius: var(--join-es);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.join > :first-child {
|
|
55
|
+
--join-ss: var(--join-radius);
|
|
56
|
+
--join-es: var(--join-radius);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.join > :last-child {
|
|
60
|
+
--join-se: var(--join-radius);
|
|
61
|
+
--join-ee: var(--join-radius);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.join > :only-child {
|
|
65
|
+
--join-ss: var(--join-radius);
|
|
66
|
+
--join-se: var(--join-radius);
|
|
67
|
+
--join-es: var(--join-radius);
|
|
68
|
+
--join-ee: var(--join-radius);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.join > * + * {
|
|
72
|
+
margin-inline-start: calc(var(--border-width) * -1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.join > :is(:hover, :focus, :focus-within) {
|
|
76
|
+
z-index: 1;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Keep an active focus ring above an adjacent hovered control. This matters
|
|
80
|
+
on platforms where clicking a button does not move focus from the input. */
|
|
81
|
+
.join > :is(:focus, :focus-within) {
|
|
82
|
+
z-index: 2;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* An input's border must read as the "primary" edge against an attached
|
|
86
|
+
action (e.g. a password-reveal button) at all times, not only while
|
|
87
|
+
hovered or focused — otherwise the shared edge flips ownership as the
|
|
88
|
+
user's pointer moves, which reads as a rendering glitch. */
|
|
89
|
+
.join > :is(.input, .textarea, .select) {
|
|
90
|
+
z-index: 3;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/* An input/select with an attached action reads as one composite field. Move
|
|
94
|
+
its outer focus treatment to the join; button-only groups keep per-button
|
|
95
|
+
focus, and unsupported :has() browsers retain the control's normal ring. */
|
|
96
|
+
.join:has(> :is(.input, .textarea, .select):focus-visible) {
|
|
97
|
+
border-radius: var(--join-radius);
|
|
98
|
+
outline: var(--focus-outline);
|
|
99
|
+
outline-offset: var(--focus-outline-offset);
|
|
100
|
+
box-shadow: var(--focus-ring-shadow);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.join:has(> :is(.input, .textarea, .select)) > :is(.input, .textarea, .select):focus-visible {
|
|
104
|
+
outline: none;
|
|
105
|
+
box-shadow: none;
|
|
106
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Key — keyboard keys and shortcut tokens for UI chrome.
|
|
3
|
+
*
|
|
4
|
+
* Use .key outside prose. Plain kbd inside .prose gets the same visual
|
|
5
|
+
* treatment from prose.css so authored content stays convenient.
|
|
6
|
+
*/
|
|
7
|
+
.key {
|
|
8
|
+
display: inline-flex;
|
|
9
|
+
align-items: center;
|
|
10
|
+
justify-content: center;
|
|
11
|
+
min-inline-size: 1.75em;
|
|
12
|
+
min-block-size: 1.6em;
|
|
13
|
+
padding-inline: 0.45em;
|
|
14
|
+
border: var(--border-width) solid var(--border);
|
|
15
|
+
border-block-end-width: calc(var(--border-width) * 2);
|
|
16
|
+
border-radius: var(--radius-sm);
|
|
17
|
+
background: var(--surface-raised);
|
|
18
|
+
color: var(--text);
|
|
19
|
+
font-family: var(--font-mono);
|
|
20
|
+
font-size: 0.875em;
|
|
21
|
+
font-weight: var(--font-weight-medium);
|
|
22
|
+
line-height: 1;
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
vertical-align: 0.08em;
|
|
25
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Meter — native gauge for known-range values.
|
|
3
|
+
*
|
|
4
|
+
* Maps the three standard meter zones (optimum / suboptimum / even-less-good)
|
|
5
|
+
* to the shared success / warning / danger intent colors.
|
|
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
|
+
|
|
20
|
+
.meter {
|
|
21
|
+
appearance: none;
|
|
22
|
+
-webkit-appearance: none;
|
|
23
|
+
display: block;
|
|
24
|
+
inline-size: 100%;
|
|
25
|
+
block-size: var(--bar-height);
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
border: 0;
|
|
28
|
+
border-radius: var(--radius-full);
|
|
29
|
+
background: var(--surface-subtle);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.meter::-webkit-meter-bar {
|
|
33
|
+
-webkit-appearance: none;
|
|
34
|
+
block-size: var(--bar-height);
|
|
35
|
+
border: 0;
|
|
36
|
+
border-radius: var(--radius-full);
|
|
37
|
+
background: var(--surface-subtle);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.meter::-webkit-meter-optimum-value {
|
|
41
|
+
block-size: var(--bar-height);
|
|
42
|
+
border-radius: var(--radius-full);
|
|
43
|
+
background: var(--success);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.meter::-webkit-meter-suboptimum-value {
|
|
47
|
+
block-size: var(--bar-height);
|
|
48
|
+
border-radius: var(--radius-full);
|
|
49
|
+
background: var(--warning);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.meter::-webkit-meter-even-less-good-value {
|
|
53
|
+
block-size: var(--bar-height);
|
|
54
|
+
border-radius: var(--radius-full);
|
|
55
|
+
background: var(--danger);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.meter::-moz-meter-bar {
|
|
59
|
+
block-size: var(--bar-height);
|
|
60
|
+
border-radius: var(--radius-full);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
@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
|
+
.meter::-webkit-meter-optimum-value,
|
|
75
|
+
.meter::-webkit-meter-suboptimum-value,
|
|
76
|
+
.meter::-webkit-meter-even-less-good-value,
|
|
77
|
+
.meter::-moz-meter-bar {
|
|
78
|
+
background: Highlight;
|
|
79
|
+
forced-color-adjust: none;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Modal shell styling for native dialog elements.
|
|
3
|
+
*
|
|
4
|
+
* Spacing, radius, transitions, and focus treatment come from shared tokens.
|
|
5
|
+
* Opening behavior and intent-specific decisions stay outside this component.
|
|
6
|
+
*/
|
|
7
|
+
dialog.modal {
|
|
8
|
+
--modal-size: 32rem;
|
|
9
|
+
|
|
10
|
+
max-inline-size: min(100% - 2rem, var(--modal-size));
|
|
11
|
+
max-block-size: calc(var(--viewport-block) - 2rem);
|
|
12
|
+
border: var(--border-width) solid var(--border);
|
|
13
|
+
border-radius: var(--radius-lg);
|
|
14
|
+
background: var(--surface-raised);
|
|
15
|
+
color: var(--text);
|
|
16
|
+
box-shadow: var(--shadow);
|
|
17
|
+
padding: 0;
|
|
18
|
+
overflow: visible;
|
|
19
|
+
opacity: 0;
|
|
20
|
+
/*
|
|
21
|
+
* Keep the open dialog root untransformed. Fixed overlays mounted inside a
|
|
22
|
+
* modal dialog use viewport coordinates; transform/translate/scale on this
|
|
23
|
+
* element would make them position against the dialog instead. The closed
|
|
24
|
+
* state can still carry a small transform for enter/exit motion.
|
|
25
|
+
*/
|
|
26
|
+
transform: translateY(0.35rem) scale(0.98);
|
|
27
|
+
transition:
|
|
28
|
+
opacity var(--duration),
|
|
29
|
+
transform var(--duration);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
dialog.modal > form,
|
|
33
|
+
dialog.modal > .stack {
|
|
34
|
+
display: grid;
|
|
35
|
+
gap: var(--space-4);
|
|
36
|
+
max-block-size: calc(var(--viewport-block) - 2rem);
|
|
37
|
+
overflow: auto;
|
|
38
|
+
overscroll-behavior: contain;
|
|
39
|
+
padding: var(--space-4);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
dialog.modal.scrollable > form,
|
|
43
|
+
dialog.modal.scrollable > .stack {
|
|
44
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
dialog.modal.scrollable > form > :not(header, footer),
|
|
49
|
+
dialog.modal.scrollable > .stack > :not(header, footer) {
|
|
50
|
+
min-block-size: 0;
|
|
51
|
+
overflow: auto;
|
|
52
|
+
overscroll-behavior: contain;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
dialog.modal header > :first-child,
|
|
56
|
+
dialog.modal footer > :first-child {
|
|
57
|
+
margin-block-start: 0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
dialog.modal header > :last-child,
|
|
61
|
+
dialog.modal footer > :last-child {
|
|
62
|
+
margin-block-end: 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
dialog.modal footer {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-wrap: wrap;
|
|
68
|
+
justify-content: flex-end;
|
|
69
|
+
gap: var(--gap);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
dialog.modal[open] {
|
|
73
|
+
opacity: 1;
|
|
74
|
+
transform: none;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
@starting-style {
|
|
78
|
+
dialog.modal[open] {
|
|
79
|
+
opacity: 0;
|
|
80
|
+
transform: translateY(0.35rem) scale(0.98);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
dialog.modal::backdrop {
|
|
85
|
+
background: var(--backdrop-fill);
|
|
86
|
+
opacity: 0;
|
|
87
|
+
transition: opacity var(--duration);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@supports (transition-behavior: allow-discrete) {
|
|
91
|
+
dialog.modal {
|
|
92
|
+
transition:
|
|
93
|
+
opacity var(--duration),
|
|
94
|
+
transform var(--duration),
|
|
95
|
+
overlay var(--duration) allow-discrete,
|
|
96
|
+
display var(--duration) allow-discrete;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
dialog.modal::backdrop {
|
|
100
|
+
transition:
|
|
101
|
+
opacity var(--duration),
|
|
102
|
+
overlay var(--duration) allow-discrete,
|
|
103
|
+
display var(--duration) allow-discrete;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
dialog.modal[open]::backdrop {
|
|
108
|
+
opacity: 1;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
html.has-modal-open {
|
|
112
|
+
overflow: hidden;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
html.has-modal-open.had-scrollbar {
|
|
116
|
+
scrollbar-gutter: stable;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@starting-style {
|
|
120
|
+
dialog.modal[open]::backdrop {
|
|
121
|
+
opacity: 0;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
126
|
+
dialog.modal.is-static {
|
|
127
|
+
animation: actual-modal-static 180ms var(--ease);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
::view-transition-group(actual-dialog) {
|
|
131
|
+
animation-duration: var(--duration);
|
|
132
|
+
animation-timing-function: var(--ease);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
@keyframes actual-modal-static {
|
|
137
|
+
0%,
|
|
138
|
+
100% {
|
|
139
|
+
transform: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
35% {
|
|
143
|
+
transform: translateX(-0.35rem);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
70% {
|
|
147
|
+
transform: translateX(0.35rem);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
@media (forced-colors: active) {
|
|
152
|
+
dialog.modal {
|
|
153
|
+
border-color: ButtonText;
|
|
154
|
+
background: Canvas;
|
|
155
|
+
color: CanvasText;
|
|
156
|
+
box-shadow: none;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
dialog.modal::backdrop {
|
|
160
|
+
background: Canvas;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Navbar — top-level navigation bar.
|
|
3
|
+
*
|
|
4
|
+
* .navbar is a horizontal bar; .navbar-brand is the brand link; .navbar-nav is
|
|
5
|
+
* the inline link list using .nav-link items. .nav-list is the vertical nav
|
|
6
|
+
* list shared with .drawer, fed by the shared --gap token.
|
|
7
|
+
*/
|
|
8
|
+
.navbar {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-wrap: wrap;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: space-between;
|
|
13
|
+
gap: var(--gap);
|
|
14
|
+
padding-block: var(--space-3);
|
|
15
|
+
padding-inline: var(--space-4);
|
|
16
|
+
border: var(--border-width) solid var(--border);
|
|
17
|
+
border-radius: var(--radius-lg);
|
|
18
|
+
background: var(--surface-raised);
|
|
19
|
+
color: var(--text);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.navbar-brand {
|
|
23
|
+
display: inline-flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: var(--space-2);
|
|
26
|
+
color: var(--text);
|
|
27
|
+
font-weight: var(--font-weight-bold);
|
|
28
|
+
text-decoration: none;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.navbar-brand:focus-visible {
|
|
32
|
+
border-radius: var(--radius-sm);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.navbar-nav {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-wrap: wrap;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: var(--space-1);
|
|
40
|
+
margin: 0;
|
|
41
|
+
padding: 0;
|
|
42
|
+
list-style: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.nav-link {
|
|
46
|
+
display: inline-flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
min-block-size: var(--control-size-sm);
|
|
49
|
+
padding-inline: var(--space-2);
|
|
50
|
+
border-radius: var(--radius);
|
|
51
|
+
color: var(--text-muted);
|
|
52
|
+
font-weight: var(--font-weight-medium);
|
|
53
|
+
text-decoration: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.nav-link:where([aria-current]:not([aria-current="false"])) {
|
|
57
|
+
background: var(--surface-subtle);
|
|
58
|
+
color: var(--text);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@media (hover: hover) {
|
|
62
|
+
.nav-link:hover {
|
|
63
|
+
background: var(--surface-subtle);
|
|
64
|
+
color: var(--text);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Nav list — a vertical navigation list. Used by .drawer for stacked links. */
|
|
69
|
+
.nav-list {
|
|
70
|
+
display: grid;
|
|
71
|
+
gap: var(--gap);
|
|
72
|
+
margin: 0;
|
|
73
|
+
padding: 0;
|
|
74
|
+
list-style: none;
|
|
75
|
+
--gap: var(--space-2);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.nav-list > li {
|
|
79
|
+
margin: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@media (forced-colors: active) {
|
|
83
|
+
.nav-link:where([aria-current]:not([aria-current="false"])) {
|
|
84
|
+
outline: var(--border-width) solid Highlight;
|
|
85
|
+
background: Highlight;
|
|
86
|
+
color: HighlightText;
|
|
87
|
+
forced-color-adjust: none;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@media (hover: hover) {
|
|
91
|
+
.nav-link:hover:not(:where([aria-current]:not([aria-current="false"]))) {
|
|
92
|
+
outline: var(--border-width) solid ButtonText;
|
|
93
|
+
outline-offset: 2px;
|
|
94
|
+
background: Canvas;
|
|
95
|
+
color: CanvasText;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Overline — editorial small-cap label for section openers.
|
|
3
|
+
*
|
|
4
|
+
* Base form is unstyled chrome that takes its surrounding color. Add .pill for
|
|
5
|
+
* the bordered rounded shape, and combine with an intent class (.primary,
|
|
6
|
+
* .success, etc.) to tint the text, border, and background.
|
|
7
|
+
*/
|
|
8
|
+
/* Intent boundary — inherited intents do not tint this component.
|
|
9
|
+
Local intent classes still win because :where() has zero specificity. */
|
|
10
|
+
:where(.overline) {
|
|
11
|
+
/* @sync intent-boundary */
|
|
12
|
+
--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
|
+
}
|
|
20
|
+
|
|
21
|
+
.overline {
|
|
22
|
+
align-self: flex-start;
|
|
23
|
+
color: var(--text-muted);
|
|
24
|
+
font-size: var(--font-size-sm);
|
|
25
|
+
font-weight: var(--font-weight-medium);
|
|
26
|
+
letter-spacing: 0.04em;
|
|
27
|
+
text-transform: uppercase;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.overline.pill {
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: 0.5em;
|
|
34
|
+
padding-inline: 0.6em;
|
|
35
|
+
padding-block: 0.25em;
|
|
36
|
+
color: var(--intent, var(--text-muted));
|
|
37
|
+
border: var(--border-width) solid var(--border);
|
|
38
|
+
border-radius: var(--radius-full);
|
|
39
|
+
background: var(--surface);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Tinted pill surface where color-mix is available; the flat fallback above
|
|
43
|
+
keeps a readable bordered pill everywhere else. */
|
|
44
|
+
@supports (color: color-mix(in oklch, red, white)) {
|
|
45
|
+
.overline.pill {
|
|
46
|
+
border-color: color-mix(in oklch, var(--intent, var(--border)) 35%, var(--border));
|
|
47
|
+
background: color-mix(in oklch, var(--intent, transparent) 6%, var(--surface));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Pagination — page navigation for paginated lists.
|
|
3
|
+
*
|
|
4
|
+
* Render .btn elements inside a .pagination list. The active page is marked
|
|
5
|
+
* with aria-current="page"; .btn owns the active state styling.
|
|
6
|
+
*
|
|
7
|
+
* Truncated ranges are plain text (`.muted`, `aria-hidden="true"`), not .btn
|
|
8
|
+
* — they are decorative, not actionable. They still get the same box sizing
|
|
9
|
+
* as .btn below so the row stays visually aligned.
|
|
10
|
+
*/
|
|
11
|
+
.pagination {
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-wrap: wrap;
|
|
14
|
+
align-items: center;
|
|
15
|
+
gap: var(--space-1);
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
list-style: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.pagination .btn {
|
|
22
|
+
min-inline-size: var(--control-size);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.pagination > li > [aria-hidden="true"] {
|
|
26
|
+
display: inline-flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
justify-content: center;
|
|
29
|
+
min-inline-size: var(--control-size);
|
|
30
|
+
}
|