actual-css 0.3.1 → 0.4.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 +109 -3
- package/README.md +35 -30
- package/dist/actual.css +66 -4958
- package/dist/actual.full.css +7548 -0
- package/dist/actual.full.js +1 -0
- package/dist/actual.full.min.css +1 -0
- package/dist/actual.js +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/app-ui.md +33 -0
- package/docs/design-notes/cascade-layer.md +34 -13
- package/docs/design-notes/column-layout.md +677 -0
- package/docs/design-notes/enhancement-contract.md +25 -0
- package/docs/design-notes/forced-colors.md +3 -0
- package/docs/design-notes/grid.md +785 -0
- package/docs/design-notes/naming.md +15 -0
- package/docs/design-notes/references.md +1 -1
- package/docs/design-notes/widget-primitives.md +1 -0
- package/docs/navigation.json +12 -2
- package/docs/pages/components/alert.md +21 -14
- package/docs/pages/components/app-navigation.md +34 -0
- package/docs/pages/components/aura.md +1 -1
- package/docs/pages/components/avatar.md +16 -6
- package/docs/pages/components/badge.md +9 -7
- package/docs/pages/components/button.md +46 -16
- package/docs/pages/components/card.md +17 -9
- package/docs/pages/components/chat.md +8 -8
- package/docs/pages/components/dialog.md +7 -7
- package/docs/pages/components/drawer.md +3 -3
- package/docs/pages/components/fab.md +9 -7
- package/docs/pages/components/indicator.md +52 -0
- package/docs/pages/components/list.md +62 -0
- package/docs/pages/components/navbar.md +15 -8
- package/docs/pages/components/pagination.md +4 -3
- package/docs/pages/components/rating.md +68 -0
- package/docs/pages/components/skeleton.md +4 -4
- package/docs/pages/components/spinner.md +5 -5
- package/docs/pages/components/steps.md +57 -0
- package/docs/pages/components/table.md +30 -5
- package/docs/pages/enhancements/flyout.md +15 -15
- package/docs/pages/enhancements/overview.md +1 -1
- package/docs/pages/enhancements/scrollspy.md +6 -6
- package/docs/pages/enhancements/status-bar.md +5 -1
- package/docs/pages/enhancements/tabs.md +7 -8
- package/docs/pages/enhancements/tooltip.md +1 -1
- package/docs/pages/examples/overview.md +47 -22
- package/docs/pages/forms/choice-cards.md +11 -6
- package/docs/pages/forms/controls.md +1 -1
- package/docs/pages/forms/detached-actions.md +1 -1
- package/docs/pages/forms/floating-field.md +10 -5
- package/docs/pages/forms/form-actions.md +1 -1
- package/docs/pages/forms/input-policy.md +1 -1
- package/docs/pages/forms/joined-controls.md +4 -4
- package/docs/pages/forms/labels.md +6 -6
- package/docs/pages/forms/otp.md +33 -1
- package/docs/pages/forms/overview.md +19 -19
- package/docs/pages/forms/password.md +1 -1
- package/docs/pages/forms/range.md +1 -1
- package/docs/pages/forms/states-and-sizes.md +44 -48
- package/docs/pages/forms/sticky-actions.md +3 -3
- package/docs/pages/forms/switch.md +110 -2
- package/docs/pages/forms/validation.md +9 -9
- package/docs/pages/foundations/philosophy.md +1 -1
- package/docs/pages/foundations/theming.md +17 -2
- package/docs/pages/foundations/tokens.md +22 -10
- package/docs/pages/foundations/typography.md +50 -20
- package/docs/pages/guides/bootstrap.md +11 -11
- package/docs/pages/guides/integrating-actual-css.md +192 -0
- package/docs/pages/guides/introduction.md +23 -26
- package/docs/pages/guides/modular-import.md +173 -0
- package/docs/pages/guides/progressive-enhancement.md +81 -78
- package/docs/pages/guides/tailwind.md +6 -8
- package/docs/pages/layout/app-layout.md +57 -0
- package/docs/pages/layout/app-shell.md +28 -7
- package/docs/pages/layout/center.md +12 -1
- package/docs/pages/layout/choosing.md +54 -0
- package/docs/pages/layout/column-layout.md +206 -0
- package/docs/pages/layout/frame.md +6 -1
- package/docs/pages/layout/grid.md +133 -102
- package/docs/pages/layout/media.md +1 -1
- package/docs/pages/layout/overview.md +15 -2
- package/docs/pages/layout/scroll-snap.md +2 -2
- package/docs/pages/layout/scroll-target.md +45 -0
- package/docs/pages/layout/sidebar-layout.md +38 -18
- package/docs/pages/layout/stack.md +70 -1
- package/docs/pages/layout/switcher.md +10 -26
- package/docs/pages/layout/topbar.md +2 -2
- package/docs/pages/patterns/actions.md +1 -1
- package/docs/pages/patterns/code-block.md +1 -1
- package/docs/pages/patterns/exclusive-accordion.md +1 -1
- package/docs/pages/patterns/hierarchical-nav.md +1 -1
- package/docs/pages/patterns/icon-input.md +1 -1
- package/docs/pages/patterns/icon-slot.md +61 -0
- package/docs/pages/patterns/intent-nesting.md +1 -1
- package/docs/pages/patterns/navigation-list.md +1 -1
- package/docs/pages/patterns/overview.md +1 -1
- package/docs/pages/patterns/structured-lists.md +38 -40
- package/docs/pages/utilities/accessibility.md +3 -3
- package/docs/pages/utilities/flex.md +15 -15
- package/docs/pages/utilities/links.md +4 -4
- package/docs/pages/utilities/list.md +8 -8
- package/docs/pages/utilities/overflow.md +8 -8
- package/docs/pages/utilities/overview.md +1 -1
- package/docs/pages/utilities/shape.md +3 -3
- package/docs/pages/utilities/sizing-wrapping.md +23 -16
- package/docs/pages/utilities/spacing.md +20 -20
- package/docs/pages/utilities/text.md +10 -10
- package/llms.txt +46 -4
- package/package.json +43 -13
- package/scripts/reserved-classes.json +278 -0
- package/src/cli/actual-css.js +133 -0
- package/src/css/actual.css +1 -31
- package/src/css/actual.full.css +11 -2
- package/src/css/components/alert.css +17 -4
- package/src/css/components/app-nav.css +76 -0
- package/src/css/components/avatar.css +4 -0
- package/src/css/components/badge.css +19 -19
- package/src/css/components/breadcrumb.css +1 -1
- package/src/css/components/button.css +20 -32
- package/src/css/components/card.css +34 -9
- package/src/css/{optional → components}/chat.css +0 -6
- package/src/css/components/drawer.css +24 -5
- package/src/css/{optional → components}/fab.css +1 -7
- package/src/css/components/flyout.css +5 -0
- package/src/css/components/index.css +37 -27
- package/src/css/components/indicator.css +47 -0
- package/src/css/components/join.css +8 -1
- package/src/css/components/key.css +2 -0
- package/src/css/components/list.css +83 -0
- package/src/css/components/menu.css +11 -8
- package/src/css/components/meter.css +4 -1
- package/src/css/components/modal.css +5 -17
- package/src/css/components/navbar.css +6 -15
- package/src/css/components/pagination.css +11 -0
- package/src/css/components/rating.css +101 -0
- package/src/css/components/spinner.css +5 -0
- package/src/css/components/status-bar.css +5 -0
- package/src/css/components/steps.css +122 -0
- package/src/css/components/surface.css +5 -0
- package/src/css/components/tab.css +20 -22
- package/src/css/components/table.css +6 -0
- package/src/css/components/tooltip.css +3 -7
- package/src/css/{focus.css → core/focus.css} +0 -8
- package/src/css/core/index.css +9 -0
- package/src/css/core/print.css +18 -0
- package/src/css/{theme.css → core/theme.css} +19 -19
- package/src/css/{tokens.css → core/tokens.css} +16 -4
- package/src/css/{variants.css → core/variants.css} +3 -2
- package/src/css/{optional → effects}/aura.css +1 -10
- package/src/css/effects/index.css +2 -0
- package/src/css/forms/base.css +8 -0
- package/src/css/forms/choice-card.css +7 -15
- package/src/css/forms/choice.css +49 -37
- package/src/css/forms/control.css +4 -1
- package/src/css/forms/custom-select.css +2 -0
- package/src/css/{optional → forms}/floating-field.css +25 -7
- package/src/css/forms/index.css +10 -13
- package/src/css/forms/native.css +15 -2
- package/src/css/{optional → forms}/otp.css +25 -16
- package/src/css/forms/range.css +14 -4
- package/src/css/forms/switch.css +31 -29
- package/src/css/layout/app-layout.css +102 -0
- package/src/css/layout/app-shell.css +6 -0
- package/src/css/layout/center.css +14 -0
- package/src/css/layout/cluster.css +21 -0
- package/src/css/layout/column-layout.css +144 -0
- package/src/css/layout/container-query.css +15 -0
- package/src/css/layout/frame.css +19 -0
- package/src/css/layout/grid.css +155 -0
- package/src/css/layout/index.css +44 -0
- package/src/css/layout/measure.css +9 -0
- package/src/css/layout/media.css +10 -0
- package/src/css/layout/scroll-target.css +15 -0
- package/src/css/layout/scroller.css +41 -0
- package/src/css/layout/sidebar-layout.css +52 -0
- package/src/css/layout/stack.css +21 -0
- package/src/css/layout/switcher.css +23 -0
- package/src/css/{optional/layout-extra.css → layout/topbar.css} +0 -20
- package/src/css/typography/index.css +5 -0
- package/src/css/typography/lead.css +7 -0
- package/src/css/{components → typography}/overline.css +2 -2
- package/src/css/{prose.css → typography/prose.css} +57 -38
- package/src/css/{utilities.css → utilities/base.css} +2 -0
- package/src/css/utilities/index.css +3 -0
- package/src/js/escape.js +36 -0
- package/src/js/flyout.js +22 -12
- package/src/js/full.js +26 -0
- package/src/js/index.js +5 -21
- package/src/js/surface.js +1 -31
- package/src/js/tooltip.js +48 -19
- package/src/js/validation.js +1 -1
- package/src/tooling/css-bundle.js +308 -0
- package/dist/actual-themes.min.css +0 -1
- package/dist/optional.css +0 -1048
- package/dist/optional.min.css +0 -1
- package/docs/pages/guides/optional-components.md +0 -33
- package/docs/pages/layout/list.md +0 -41
- package/src/css/grid.css +0 -109
- package/src/css/layout.css +0 -123
- package/src/css/optional/index.css +0 -10
- package/src/css/optional/scroller.css +0 -63
- package/src/css/print.css +0 -47
- package/src/css/themes/corporate.css +0 -60
- package/src/css/themes/cyberpunk.css +0 -60
- package/src/css/themes/dim.css +0 -33
- package/src/css/themes/edge.css +0 -117
- package/src/css/themes/forest.css +0 -65
- package/src/css/themes/gradient.css +0 -97
- package/src/css/themes/index.css +0 -47
- package/src/css/themes/indigo.css +0 -33
- package/src/css/themes/lavender.css +0 -66
- package/src/css/themes/mono.css +0 -60
- package/src/css/themes/neon.css +0 -66
- package/src/css/themes/ocean.css +0 -60
- package/src/css/themes/petrol.css +0 -64
- package/src/css/themes/spruce.css +0 -64
- package/src/css/themes/square.css +0 -65
- package/src/css/themes/sunset.css +0 -66
- /package/src/css/{base.css → core/base.css} +0 -0
- /package/src/css/{intents.css → core/intents.css} +0 -0
- /package/src/css/{reset.css → core/reset.css} +0 -0
- /package/src/css/{optional → layout}/scroll-snap.css +0 -0
- /package/src/css/{optional/typography-fluid.css → typography/fluid.css} +0 -0
- /package/src/css/{optional/utilities-extra.css → utilities/extra.css} +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Scroller — optional scrollbar treatment for overflow regions.
|
|
3
|
+
*
|
|
4
|
+
* Apply to any scroll container (.overflow-auto, sidebars, long tables). Only
|
|
5
|
+
* the standard properties are used: the engine keeps drawing the scrollbar,
|
|
6
|
+
* this hands it the theme's density and colour. No ::-webkit-scrollbar chrome —
|
|
7
|
+
* rebuilding a thumb by hand means re-implementing the hover, the corner and
|
|
8
|
+
* the light/dark adaptation that color-scheme already gives for free, and the
|
|
9
|
+
* two never match anyway.
|
|
10
|
+
*
|
|
11
|
+
* Above the capability floor: scrollbar-color lands in Chromium 121 and
|
|
12
|
+
* Safari 18.2, the floor is Chromium 99 / Safari 15.4. Older engines ignore
|
|
13
|
+
* both declarations and draw their native scrollbar — the intended fallback,
|
|
14
|
+
* not a broken state.
|
|
15
|
+
*
|
|
16
|
+
* Styles the scrollbar only; it does not create the overflow. Pair it with
|
|
17
|
+
* .overflow-auto or a component that already scrolls.
|
|
18
|
+
*
|
|
19
|
+
* Public hooks:
|
|
20
|
+
* --scroller-track
|
|
21
|
+
* --scroller-thumb
|
|
22
|
+
*/
|
|
23
|
+
.scroller {
|
|
24
|
+
--scroller-track: transparent;
|
|
25
|
+
--scroller-thumb: var(--border);
|
|
26
|
+
|
|
27
|
+
scrollbar-color: var(--scroller-thumb) var(--scroller-track);
|
|
28
|
+
scrollbar-width: thin;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* Opt-in gutter: reserves space so the layout does not shift when
|
|
32
|
+
the scrollbar appears. Use alongside a known-overflow container. */
|
|
33
|
+
.scroller.stable-gutter {
|
|
34
|
+
scrollbar-gutter: stable;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@supports (color: color-mix(in oklch, red, white)) {
|
|
38
|
+
.scroller {
|
|
39
|
+
--scroller-thumb: color-mix(in oklch, var(--text-muted), transparent 55%);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Main content + secondary region.
|
|
3
|
+
*
|
|
4
|
+
* The children wrap according to the space allocated to this layout, without
|
|
5
|
+
* an ancestor opt-in or viewport threshold. The large growth ratio lets the
|
|
6
|
+
* main region reclaim the full row when the aside wraps instead of remaining
|
|
7
|
+
* at its minimum viable width.
|
|
8
|
+
*
|
|
9
|
+
* Public hooks:
|
|
10
|
+
* --sidebar-content-min
|
|
11
|
+
* --sidebar-layout-size
|
|
12
|
+
*
|
|
13
|
+
* Child contract: the main region is first and the aside second by default
|
|
14
|
+
* (aside on the inline end). .reverse expects the aside first in the DOM, so
|
|
15
|
+
* visual, reading and keyboard order all agree — the role rules swap so the
|
|
16
|
+
* aside still takes its preferred width and the main still reclaims the row.
|
|
17
|
+
*/
|
|
18
|
+
.sidebar-layout {
|
|
19
|
+
display: flex;
|
|
20
|
+
flex-wrap: wrap;
|
|
21
|
+
gap: var(--gap);
|
|
22
|
+
align-items: flex-start;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Main region — flexible, reclaims the full row when the aside wraps. */
|
|
26
|
+
.sidebar-layout > :first-child {
|
|
27
|
+
flex-basis: 0;
|
|
28
|
+
flex-grow: 999;
|
|
29
|
+
min-inline-size: min(100%, var(--sidebar-content-min, 30rem));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Aside region — preferred width, never forces content min-width. */
|
|
33
|
+
.sidebar-layout > :last-child {
|
|
34
|
+
flex-basis: var(--sidebar-layout-size, 18rem);
|
|
35
|
+
flex-grow: 1;
|
|
36
|
+
min-inline-size: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* .reverse: the aside is first in the DOM and the main last, so each role
|
|
40
|
+
rule above would hit the wrong element. Swap the sizing per child; the
|
|
41
|
+
higher-specificity reverse rules outrank the positional defaults. */
|
|
42
|
+
.sidebar-layout.reverse > :last-child {
|
|
43
|
+
flex-basis: 0;
|
|
44
|
+
flex-grow: 999;
|
|
45
|
+
min-inline-size: min(100%, var(--sidebar-content-min, 30rem));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.sidebar-layout.reverse > :first-child {
|
|
49
|
+
flex-basis: var(--sidebar-layout-size, 18rem);
|
|
50
|
+
flex-grow: 1;
|
|
51
|
+
min-inline-size: 0;
|
|
52
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/* Vertical flow. .stack owns the block axis only: block margins reset, inline
|
|
2
|
+
margins stay free (self-centering children via margin-inline: auto keep
|
|
3
|
+
working).
|
|
4
|
+
Child contract: direct children become flex items; margins reset, spacing
|
|
5
|
+
comes from --gap.
|
|
6
|
+
|
|
7
|
+
--gap is inherited, so a container that composes other primitives sets its
|
|
8
|
+
own rhythm on the `gap` property, not on the token: setting --gap on a
|
|
9
|
+
region re-spaces every nested stack, cluster and grid at any depth. Setting
|
|
10
|
+
the token stays correct on the element that consumes it, and .sm/.lg set it
|
|
11
|
+
deliberately so a density context reaches nested layouts. See
|
|
12
|
+
docs/pages/layout/stack.md. */
|
|
13
|
+
.stack {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-direction: column;
|
|
16
|
+
gap: var(--gap);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.stack > * {
|
|
20
|
+
margin-block: 0;
|
|
21
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Peer regions that switch as a group.
|
|
3
|
+
*
|
|
4
|
+
* All children sit side by side when they all fit; otherwise every child
|
|
5
|
+
* stacks. Unlike .grid, this recipe cannot create a partial row such as two
|
|
6
|
+
* items plus one orphan.
|
|
7
|
+
*
|
|
8
|
+
* Public hooks:
|
|
9
|
+
* --switcher-threshold
|
|
10
|
+
*
|
|
11
|
+
* Child contract: every direct child is a peer; the flex-basis applies to all.
|
|
12
|
+
*/
|
|
13
|
+
.switcher {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-wrap: wrap;
|
|
16
|
+
gap: var(--gap);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.switcher > * {
|
|
20
|
+
flex-basis: calc((var(--switcher-threshold, 40rem) - 100%) * 999);
|
|
21
|
+
flex-grow: 1;
|
|
22
|
+
min-inline-size: 0;
|
|
23
|
+
}
|
|
@@ -1,23 +1,3 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Additional layout primitives not included in the core bundle.
|
|
3
|
-
*
|
|
4
|
-
* Import this file explicitly when a project needs these patterns.
|
|
5
|
-
*
|
|
6
|
-
* Public hooks:
|
|
7
|
-
* --switcher-threshold
|
|
8
|
-
*/
|
|
9
|
-
.switcher {
|
|
10
|
-
display: flex;
|
|
11
|
-
flex-wrap: wrap;
|
|
12
|
-
gap: var(--gap);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
.switcher > * {
|
|
16
|
-
flex-basis: calc((var(--switcher-threshold, 40rem) - 100%) * 999);
|
|
17
|
-
flex-grow: 1;
|
|
18
|
-
min-inline-size: 0;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
1
|
/*
|
|
22
2
|
* Sticky, frosted top bar shell for app/dashboard shells (persistent
|
|
23
3
|
* sidebar + topbar layouts). Owns positioning, stacking, and the frosted
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/* Lead paragraph: a slightly larger, more relaxed reading-introduction text.
|
|
2
|
+
Non-fluid and always available — use .text-lead from the optional fluid
|
|
3
|
+
module for marketing/display surfaces. */
|
|
4
|
+
.lead {
|
|
5
|
+
font-size: 1.125em;
|
|
6
|
+
line-height: var(--line-height-relaxed);
|
|
7
|
+
}
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
keeps a readable bordered pill everywhere else. */
|
|
43
43
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
44
44
|
.overline.pill {
|
|
45
|
-
border-color: color-mix(in
|
|
46
|
-
background: color-mix(in
|
|
45
|
+
border-color: color-mix(in oklab, var(--intent, var(--border)) 35%, var(--border));
|
|
46
|
+
background: color-mix(in oklab, var(--intent, transparent) 6%, var(--surface));
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* --prose-h2
|
|
15
15
|
* --prose-h3
|
|
16
16
|
* --prose-h4
|
|
17
|
+
* --link
|
|
17
18
|
*/
|
|
18
19
|
|
|
19
20
|
.prose {
|
|
@@ -29,19 +30,27 @@
|
|
|
29
30
|
--prose-h4: 1.125rem;
|
|
30
31
|
|
|
31
32
|
max-inline-size: var(--prose-measure);
|
|
32
|
-
color: var(--text);
|
|
33
33
|
font-size: var(--prose-size);
|
|
34
34
|
line-height: var(--prose-line-height);
|
|
35
35
|
overflow-wrap: break-word;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
/* Vertical rhythm belongs to the direct block that participates in the
|
|
39
|
+
document, so it must not be injected into the internals of a nested
|
|
40
|
+
component (e.g. a .table-wrap around a .table would trap the margin). */
|
|
41
|
+
.prose > * {
|
|
42
|
+
margin-block-end: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.prose > * + * {
|
|
46
|
+
margin-block-start: var(--prose-flow);
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
/* Heading hierarchy remains low-specificity and contextual: a surface may
|
|
50
|
+
remap --heading without prose repainting it with the root text color. */
|
|
42
51
|
.prose :where(h1, h2, h3, h4, h5, h6) {
|
|
43
52
|
margin-block: 1.5em 0;
|
|
44
|
-
color: var(--text);
|
|
53
|
+
color: var(--heading, var(--text));
|
|
45
54
|
font-weight: var(--font-weight-strong);
|
|
46
55
|
line-height: var(--prose-heading-line-height);
|
|
47
56
|
}
|
|
@@ -54,48 +63,71 @@
|
|
|
54
63
|
margin-block-start: 0;
|
|
55
64
|
}
|
|
56
65
|
|
|
57
|
-
.prose
|
|
66
|
+
/* Element recipes are wrapped in :where() so every .prose rule is 0-1-0.
|
|
67
|
+
An explicit component/util class can therefore override prose defaults
|
|
68
|
+
regardless of the underlying element — a .btn or .alert link must not be
|
|
69
|
+
reshaped just because it lives inside authored content. */
|
|
70
|
+
.prose :where(h1) {
|
|
58
71
|
font-size: var(--prose-h1);
|
|
59
72
|
}
|
|
60
73
|
|
|
61
|
-
.prose h2 {
|
|
74
|
+
.prose :where(h2) {
|
|
62
75
|
font-size: var(--prose-h2);
|
|
63
76
|
}
|
|
64
77
|
|
|
65
|
-
.prose h3 {
|
|
78
|
+
.prose :where(h3) {
|
|
66
79
|
font-size: var(--prose-h3);
|
|
67
80
|
}
|
|
68
81
|
|
|
69
|
-
.prose h4 {
|
|
82
|
+
.prose :where(h4) {
|
|
70
83
|
font-size: var(--prose-h4);
|
|
71
84
|
}
|
|
72
85
|
|
|
73
|
-
.
|
|
74
|
-
|
|
86
|
+
/* Link ink defaults to --primary. --link is an optional escape hatch: a
|
|
87
|
+
theme whose primary is too light or too vivid to read as inline text sets
|
|
88
|
+
it without having to restate the rule. */
|
|
89
|
+
.prose :where(a) {
|
|
90
|
+
color: var(--link, var(--primary));
|
|
75
91
|
text-decoration-line: underline;
|
|
76
92
|
text-decoration-thickness: 0.08em;
|
|
77
93
|
text-underline-offset: 0.18em;
|
|
78
94
|
}
|
|
79
95
|
|
|
80
|
-
.prose a:hover {
|
|
96
|
+
.prose :where(a:hover) {
|
|
81
97
|
text-decoration-thickness: 0.12em;
|
|
82
98
|
}
|
|
83
99
|
|
|
84
100
|
@supports (color: color-mix(in oklch, red, white)) {
|
|
85
|
-
.prose a:hover {
|
|
86
|
-
color: color-mix(in
|
|
101
|
+
.prose :where(a:hover) {
|
|
102
|
+
color: color-mix(in oklab, var(--link, var(--primary)), var(--text) 15%);
|
|
87
103
|
}
|
|
88
104
|
}
|
|
89
105
|
|
|
106
|
+
/* Rich-text descendants are intentional here. Components and application UI
|
|
107
|
+
belong outside the prose boundary. */
|
|
90
108
|
.prose :where(ul, ol) {
|
|
91
109
|
padding-inline-start: 1.5em;
|
|
92
110
|
}
|
|
93
111
|
|
|
94
|
-
.prose li + li {
|
|
112
|
+
.prose :where(li + li) {
|
|
95
113
|
margin-block-start: 0.35em;
|
|
96
114
|
}
|
|
97
115
|
|
|
98
|
-
|
|
116
|
+
/* Description lists keep document flow: a valid <dl> may pair several <dt>
|
|
117
|
+
with one <dd> or the reverse, so no grid layout is imposed here. */
|
|
118
|
+
.prose :where(dt) {
|
|
119
|
+
font-weight: var(--font-weight-strong);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.prose :where(dd) {
|
|
123
|
+
margin-inline-start: 1.5em;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.prose :where(dd + dt) {
|
|
127
|
+
margin-block-start: 0.75em;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.prose :where(code) {
|
|
99
131
|
padding: 0.15em 0.3em;
|
|
100
132
|
border-radius: var(--radius-sm);
|
|
101
133
|
background: var(--surface-subtle);
|
|
@@ -104,7 +136,8 @@
|
|
|
104
136
|
}
|
|
105
137
|
|
|
106
138
|
/* Visual twin of .key (components/key.css) — keep the two recipes in sync. */
|
|
107
|
-
|
|
139
|
+
/* @sync key-recipe */
|
|
140
|
+
.prose :where(kbd) {
|
|
108
141
|
display: inline-flex;
|
|
109
142
|
align-items: center;
|
|
110
143
|
justify-content: center;
|
|
@@ -123,8 +156,9 @@
|
|
|
123
156
|
white-space: nowrap;
|
|
124
157
|
vertical-align: 0.08em;
|
|
125
158
|
}
|
|
159
|
+
/* @sync key-recipe */
|
|
126
160
|
|
|
127
|
-
.prose pre {
|
|
161
|
+
.prose :where(pre) {
|
|
128
162
|
overflow-x: auto;
|
|
129
163
|
padding: 1em;
|
|
130
164
|
border: var(--border-width) solid var(--border);
|
|
@@ -132,53 +166,38 @@
|
|
|
132
166
|
background: var(--surface-subtle);
|
|
133
167
|
}
|
|
134
168
|
|
|
135
|
-
.prose pre code {
|
|
169
|
+
.prose :where(pre) :where(code) {
|
|
136
170
|
padding: 0;
|
|
137
171
|
background: transparent;
|
|
138
172
|
}
|
|
139
173
|
|
|
140
|
-
.prose blockquote {
|
|
174
|
+
.prose :where(blockquote) {
|
|
141
175
|
padding-inline-start: 1em;
|
|
142
176
|
border-inline-start: var(--border-width) solid var(--border);
|
|
143
177
|
color: var(--text-muted);
|
|
144
178
|
}
|
|
145
179
|
|
|
146
|
-
.prose figure {
|
|
180
|
+
.prose :where(figure) {
|
|
147
181
|
margin-inline: 0;
|
|
148
182
|
}
|
|
149
183
|
|
|
150
|
-
.prose figcaption {
|
|
184
|
+
.prose :where(figcaption) {
|
|
151
185
|
margin-block-start: 0.5em;
|
|
152
186
|
color: var(--text-muted);
|
|
153
187
|
font-size: 0.875em;
|
|
154
188
|
}
|
|
155
189
|
|
|
156
|
-
.prose table {
|
|
190
|
+
.prose :where(table) {
|
|
157
191
|
inline-size: 100%;
|
|
158
192
|
border-collapse: collapse;
|
|
159
193
|
}
|
|
160
194
|
|
|
161
|
-
.prose th,
|
|
162
|
-
.prose td {
|
|
195
|
+
.prose :where(th, td) {
|
|
163
196
|
padding: 0.5em;
|
|
164
197
|
border-block-end: var(--border-width) solid var(--border);
|
|
165
198
|
text-align: start;
|
|
166
199
|
}
|
|
167
200
|
|
|
168
|
-
/* Lead paragraph: a slightly larger, more relaxed reading-introduction text.
|
|
169
|
-
Non-fluid and always available — use .text-lead from the optional fluid
|
|
170
|
-
module for marketing/display surfaces. */
|
|
171
|
-
.lead {
|
|
172
|
-
font-size: 1.125em;
|
|
173
|
-
line-height: var(--line-height-relaxed);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
/* Readable content measure. Composes with .center for centering or with
|
|
177
|
-
margin-inline: auto for a one-off centered block. */
|
|
178
|
-
.measure {
|
|
179
|
-
max-inline-size: var(--prose-measure, 70ch);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
201
|
.prose.sm {
|
|
183
202
|
--prose-size: 0.9375rem;
|
|
184
203
|
--prose-h1: 1.75rem;
|
package/src/js/escape.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Per-document LIFO dismissal for transient UI that closes on Escape.
|
|
3
|
+
* Consumers register only while visible, so the topmost dismissable UI owns
|
|
4
|
+
* one key press and pinned or hidden UI never consumes it.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const dismissableStacks = new WeakMap();
|
|
8
|
+
|
|
9
|
+
export function registerEscapeDismissal(element, dismiss) {
|
|
10
|
+
const doc = element.ownerDocument;
|
|
11
|
+
let stack = dismissableStacks.get(doc);
|
|
12
|
+
if (!stack) {
|
|
13
|
+
stack = [];
|
|
14
|
+
dismissableStacks.set(doc, stack);
|
|
15
|
+
doc.addEventListener("keydown", onDocumentEscape);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const entry = { element, dismiss };
|
|
19
|
+
stack.push(entry);
|
|
20
|
+
|
|
21
|
+
return () => {
|
|
22
|
+
const index = stack.indexOf(entry);
|
|
23
|
+
if (index >= 0) stack.splice(index, 1);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function onDocumentEscape(event) {
|
|
28
|
+
if (event.key !== "Escape" || event.ctrlKey || event.altKey || event.shiftKey) return;
|
|
29
|
+
|
|
30
|
+
const stack = dismissableStacks.get(event.currentTarget);
|
|
31
|
+
const entry = stack.at(-1);
|
|
32
|
+
if (!entry) return;
|
|
33
|
+
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
entry.dismiss({ restoreFocus: true });
|
|
36
|
+
}
|
package/src/js/flyout.js
CHANGED
|
@@ -144,10 +144,29 @@ function connectTrigger(trigger) {
|
|
|
144
144
|
trigger.addEventListener("keydown", onTriggerKeydown, { signal: controller.signal });
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
function
|
|
148
|
-
|
|
147
|
+
function releasePanelReference(trigger, state) {
|
|
148
|
+
state.releaseMenu?.();
|
|
149
|
+
state.releaseMenu = null;
|
|
150
|
+
|
|
151
|
+
const panel = state.panel;
|
|
152
|
+
state.panel = null;
|
|
153
|
+
if (!panel) return;
|
|
154
|
+
|
|
155
|
+
const panelEntry = panelRefs.get(panel);
|
|
156
|
+
if (!panelEntry) return;
|
|
157
|
+
|
|
158
|
+
panelEntry.triggers.delete(trigger);
|
|
159
|
+
if (panelEntry.triggers.size === 0) {
|
|
160
|
+
panelEntry.release();
|
|
161
|
+
panelRefs.delete(panel);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
149
164
|
|
|
165
|
+
function resolvePanel(trigger, state) {
|
|
150
166
|
const panel = panelFor(trigger);
|
|
167
|
+
if (state.panel === panel && panel?.isConnected) return panel;
|
|
168
|
+
|
|
169
|
+
releasePanelReference(trigger, state);
|
|
151
170
|
if (!panel) return null;
|
|
152
171
|
|
|
153
172
|
let panelEntry = panelRefs.get(panel);
|
|
@@ -174,21 +193,12 @@ function resolvePanel(trigger, state) {
|
|
|
174
193
|
function disconnectTrigger(trigger) {
|
|
175
194
|
const state = triggerMap.get(trigger);
|
|
176
195
|
if (!state) return;
|
|
177
|
-
state.releaseMenu?.();
|
|
178
196
|
state.controller.abort();
|
|
179
197
|
if (state.panel?.isConnected && isSurfaceOpen(state.panel)) {
|
|
180
198
|
closeSurface(state.panel, { restoreFocus: false });
|
|
181
199
|
}
|
|
200
|
+
releasePanelReference(trigger, state);
|
|
182
201
|
triggerMap.delete(trigger);
|
|
183
|
-
|
|
184
|
-
const panelEntry = state.panel ? panelRefs.get(state.panel) : undefined;
|
|
185
|
-
if (panelEntry) {
|
|
186
|
-
panelEntry.triggers.delete(trigger);
|
|
187
|
-
if (panelEntry.triggers.size === 0) {
|
|
188
|
-
panelEntry.release();
|
|
189
|
-
panelRefs.delete(state.panel);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
202
|
}
|
|
193
203
|
|
|
194
204
|
registerEnhancement("flyout", (trigger) => {
|
package/src/js/full.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Actual CSS - JavaScript runtime, full bundle entry.
|
|
3
|
+
*
|
|
4
|
+
* Each module self-registers via observer: importing this bundle enables
|
|
5
|
+
* common behaviors. No DOMContentLoaded ceremony, no init calls.
|
|
6
|
+
* Injected content wires automatically; removal cleans up automatically.
|
|
7
|
+
*
|
|
8
|
+
* A plain `<script src="actual.full.js"></script>` (no bundler, no import) still
|
|
9
|
+
* gets the full runtime, including declarative triggers like status's
|
|
10
|
+
* `command="--status"` and the `actual:status` event — no global needed to
|
|
11
|
+
* drive them from other inline scripts either.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import "./flyout.js";
|
|
15
|
+
import "./context-menu.js";
|
|
16
|
+
import "./dialog.js";
|
|
17
|
+
import "./dismiss.js";
|
|
18
|
+
import "./tab.js";
|
|
19
|
+
import "./tooltip.js";
|
|
20
|
+
import "./scrollspy.js";
|
|
21
|
+
import "./filter.js";
|
|
22
|
+
import "./mask.js";
|
|
23
|
+
import "./password.js";
|
|
24
|
+
import "./validation.js";
|
|
25
|
+
import "./status.js";
|
|
26
|
+
import "./index.js";
|
package/src/js/index.js
CHANGED
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Actual CSS - JavaScript runtime.
|
|
2
|
+
* Actual CSS - JavaScript runtime, core entry.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* A plain `<script src="actual.js"></script>` (no bundler, no import) still
|
|
9
|
-
* gets the full runtime, including declarative triggers like status's
|
|
10
|
-
* `command="--status"` and the `actual:status` event — no global needed to
|
|
11
|
-
* drive them from other inline scripts either.
|
|
4
|
+
* This entry only starts the enhancement manifest loader. Built-in behaviors
|
|
5
|
+
* (dialogs, menus, tabs, validation, ...) ship in the full bundle entry
|
|
6
|
+
* (src/js/full.js). Use this module for pages that only need progressive
|
|
7
|
+
* enhancement via enhancement manifests.
|
|
12
8
|
*/
|
|
13
9
|
|
|
14
|
-
import "./flyout.js";
|
|
15
|
-
import "./context-menu.js";
|
|
16
|
-
import "./dialog.js";
|
|
17
|
-
import "./dismiss.js";
|
|
18
|
-
import "./tab.js";
|
|
19
|
-
import "./tooltip.js";
|
|
20
|
-
import "./scrollspy.js";
|
|
21
|
-
import "./filter.js";
|
|
22
|
-
import "./mask.js";
|
|
23
|
-
import "./password.js";
|
|
24
|
-
import "./validation.js";
|
|
25
|
-
import "./status.js";
|
|
26
10
|
import { watchEnhancementManifests } from "./enhancement-loader.js";
|
|
27
11
|
|
|
28
12
|
watchEnhancementManifests();
|
package/src/js/surface.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import enhance from "./enhance.js";
|
|
2
|
+
import { registerEscapeDismissal } from "./escape.js";
|
|
2
3
|
import { EVENTS } from "./events.js";
|
|
3
4
|
import { autoUpdate, reposition, repositionAt } from "./floating.js";
|
|
4
5
|
|
|
@@ -418,37 +419,6 @@ function ensureDocumentClick(menu) {
|
|
|
418
419
|
doc.addEventListener("click", onDocumentClick);
|
|
419
420
|
}
|
|
420
421
|
|
|
421
|
-
const dismissableStacks = new WeakMap();
|
|
422
|
-
|
|
423
|
-
export function registerEscapeDismissal(element, dismiss) {
|
|
424
|
-
const doc = element.ownerDocument;
|
|
425
|
-
let stack = dismissableStacks.get(doc);
|
|
426
|
-
if (!stack) {
|
|
427
|
-
stack = [];
|
|
428
|
-
dismissableStacks.set(doc, stack);
|
|
429
|
-
doc.addEventListener("keydown", onDocumentEscape);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
const entry = { element, dismiss };
|
|
433
|
-
stack.push(entry);
|
|
434
|
-
|
|
435
|
-
return () => {
|
|
436
|
-
const index = stack.indexOf(entry);
|
|
437
|
-
if (index >= 0) stack.splice(index, 1);
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
function onDocumentEscape(event) {
|
|
442
|
-
if (event.key !== "Escape" || event.ctrlKey || event.altKey || event.shiftKey) return;
|
|
443
|
-
|
|
444
|
-
const stack = dismissableStacks.get(event.currentTarget);
|
|
445
|
-
const entry = stack.at(-1);
|
|
446
|
-
if (!entry) return;
|
|
447
|
-
|
|
448
|
-
event.preventDefault();
|
|
449
|
-
entry.dismiss({ restoreFocus: true });
|
|
450
|
-
}
|
|
451
|
-
|
|
452
422
|
export function getSurfaceAutoClose(menu) {
|
|
453
423
|
return surfaceMap.get(menu)?.autoClose ?? "outside";
|
|
454
424
|
}
|