actual-css 0.4.1 → 0.5.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 +54 -0
- package/README.md +2 -2
- package/dist/actual.css +53 -14
- package/dist/actual.full.css +300 -91
- package/dist/actual.full.js +1 -1
- package/dist/actual.full.min.css +1 -1
- package/dist/actual.min.css +1 -1
- package/docs/design-notes/spacing-units.md +286 -0
- package/docs/navigation.json +1 -0
- package/docs/pages/components/alert.md +1 -1
- package/docs/pages/components/app-navigation.md +2 -0
- package/docs/pages/components/badge.md +17 -3
- package/docs/pages/components/button.md +9 -2
- package/docs/pages/components/card.md +13 -0
- package/docs/pages/components/data-list.md +72 -0
- package/docs/pages/components/dialog.md +2 -0
- package/docs/pages/components/drawer.md +2 -0
- package/docs/pages/components/fab.md +2 -0
- package/docs/pages/components/meter.md +56 -1
- package/docs/pages/components/progress.md +10 -0
- package/docs/pages/components/skeleton.md +2 -0
- package/docs/pages/components/steps.md +10 -2
- package/docs/pages/components/table.md +1 -0
- package/docs/pages/enhancements/flyout.md +2 -0
- package/docs/pages/enhancements/status-bar.md +10 -1
- package/docs/pages/examples/overview.md +2 -1
- package/docs/pages/forms/joined-controls.md +2 -0
- package/docs/pages/forms/overview.md +1 -1
- package/docs/pages/forms/range.md +2 -0
- package/docs/pages/forms/states-and-sizes.md +1 -1
- package/docs/pages/forms/validation.md +2 -0
- package/docs/pages/foundations/philosophy.md +11 -1
- package/docs/pages/foundations/tokens.md +7 -3
- package/docs/pages/foundations/typography.md +10 -2
- package/docs/pages/guides/introduction.md +1 -1
- package/docs/pages/layout/scroll-snap.md +2 -0
- package/docs/pages/layout/sidebar-layout.md +2 -0
- package/docs/pages/layout/topbar.md +2 -0
- package/docs/pages/utilities/accessibility.md +18 -0
- package/package.json +1 -1
- package/scripts/reserved-classes.json +4 -0
- package/src/css/components/actions.css +1 -0
- package/src/css/components/breadcrumb.css +1 -0
- package/src/css/components/data-list.css +27 -0
- package/src/css/components/drawer.css +30 -11
- package/src/css/components/flyout.css +17 -12
- package/src/css/components/index.css +1 -0
- package/src/css/components/meter.css +28 -1
- package/src/css/components/modal.css +28 -11
- package/src/css/components/navbar.css +2 -0
- package/src/css/components/pagination.css +1 -0
- package/src/css/components/progress.css +5 -0
- package/src/css/components/status-bar.css +31 -15
- package/src/css/components/steps.css +36 -9
- package/src/css/components/surface.css +5 -3
- package/src/css/components/tab.css +1 -0
- package/src/css/components/tooltip.css +5 -8
- package/src/css/core/base.css +7 -1
- package/src/css/core/intents.css +6 -0
- package/src/css/core/tokens.css +23 -9
- package/src/css/core/variants.css +17 -4
- package/src/css/forms/form-actions.css +1 -0
- package/src/css/forms/form.css +4 -4
- package/src/css/layout/cluster.css +1 -0
- package/src/css/layout/scroll-snap.css +1 -0
- package/src/css/layout/sidebar-layout.css +1 -0
- package/src/css/layout/switcher.css +1 -0
- package/src/css/layout/topbar.css +1 -0
- package/src/css/typography/prose.css +2 -3
- package/src/css/utilities/base.css +16 -0
- package/src/js/selectors.js +1 -0
- package/src/js/status.js +88 -7
- package/src/js/surface.js +2 -11
- package/src/js/transition.js +20 -0
|
@@ -6,13 +6,21 @@ Use an `<ol>` because order is part of the meaning. Add `.complete` to finished
|
|
|
6
6
|
steps and `aria-current="step"` to exactly one current step. Unmarked items are
|
|
7
7
|
future steps. The component needs no JavaScript.
|
|
8
8
|
|
|
9
|
+
The three states are distinct without any glyph: future is neutral, complete is
|
|
10
|
+
a filled marker with an accented connector, current is an outlined marker with a
|
|
11
|
+
thicker ring. The accented connector reads as "already walked", so the segment
|
|
12
|
+
leaving the current step stays neutral. A step carrying both states renders
|
|
13
|
+
entirely as current — marker, glyph, and connector.
|
|
14
|
+
|
|
15
|
+
**Related terms:** stepper, progress steps, step indicator, wizard steps, multi-step progress.
|
|
16
|
+
|
|
9
17
|
## Class reference
|
|
10
18
|
|
|
11
19
|
| Class | Kind | Description |
|
|
12
20
|
|-------------------------|-----------|--------------------------------------------|
|
|
13
21
|
| `.steps` | Component | Ordered progression with numbered markers. |
|
|
14
|
-
| `.complete` | State | A finished step.
|
|
15
|
-
| `[aria-current="step"]` | State | The current step.
|
|
22
|
+
| `.complete` | State | A finished step: filled marker. |
|
|
23
|
+
| `[aria-current="step"]` | State | The current step: outlined marker. |
|
|
16
24
|
|
|
17
25
|
```html demo
|
|
18
26
|
<ol class="steps">
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
- Use `.text-end` for numeric columns and `.text-nowrap` for non-wrapping cells.
|
|
8
8
|
- For wide tables, make the wrapper an accessible scroll region with `role="region"`, `aria-labelledby`, and `tabindex="0"`.
|
|
9
9
|
- Tables stay content-first and neutral by default.
|
|
10
|
+
- `.table` is a static, content-first table. It provides no sorting, filtering, search, selection, pagination, or row actions. For an interactive data grid ("datatable"), use a dedicated component — see the [data grid template](../../demo/templates/data-grid.html), which themes `data-grid-component` with Actual CSS tokens.
|
|
10
11
|
- `.table` does not consume shared variants or intent colors (`--ui-bg` / `--intent`): a `.soft` + intent combo on a `<tr>` has no effect. To tint rows or headers, style them with a class of your own.
|
|
11
12
|
|
|
12
13
|
## Class reference
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
> Positioned surface attached to a trigger, commonly used for action lists and small panels.
|
|
4
4
|
|
|
5
|
+
**Related terms:** popover, dropdown, dropdown menu, action menu, context menu, bottom sheet, action sheet, anchored panel.
|
|
6
|
+
|
|
5
7
|
## Class reference
|
|
6
8
|
|
|
7
9
|
| Class | Kind | Description |
|
|
@@ -11,9 +11,18 @@ replace the previous one. Keep one element in the HTML, styled with
|
|
|
11
11
|
`.status-bar` and carrying the `[data-status][role="status"]` contract that the
|
|
12
12
|
runtime targets, empty by default.
|
|
13
13
|
|
|
14
|
-
- JavaScript
|
|
14
|
+
- JavaScript writes the text content and toggles `.is-open`, the state class the CSS animates. The element is never hidden, so it stays available as a live region.
|
|
15
15
|
- Use it for transient status (`Saved.`, `Reconnected.`, `Copied.`). Critical, persistent, or actionable information belongs in `.alert`, inline messages, or dialogs.
|
|
16
16
|
- Intents: `danger`, `success`, `warning`, `neutral`. The default (no intent) is a neutral dark pill.
|
|
17
|
+
- On mobile, the runtime keeps the bar above the software keyboard by tracking `visualViewport` while a message is showing.
|
|
18
|
+
|
|
19
|
+
Clearing is deferred, not immediate: the bar closes first and only empties its
|
|
20
|
+
text and intent once the exit transition has finished, so it leaves at the size
|
|
21
|
+
and color it was shown at. A new message during that exit wins — it cancels the
|
|
22
|
+
pending cleanup instead of being wiped by it. Read the bar's content right after
|
|
23
|
+
`clear()` and you still see the outgoing message; that is the contract, not a
|
|
24
|
+
race. An empty message clears too, so `status(response.error)` on a successful
|
|
25
|
+
response closes the bar rather than opening a blank pill.
|
|
17
26
|
|
|
18
27
|
The runtime auto-wires the status bar to Actual's form validation: a form that
|
|
19
28
|
fails to submit shows its `data-validation-message` in the status bar with the
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
The examples live in the repository under `demo/` and load `actual.full.css`
|
|
6
6
|
and `actual.full.js` from `dist/`, plus the theme palettes bundle from
|
|
7
|
-
`demo/assets
|
|
7
|
+
`demo/assets/`. The bundle is committed and regenerated by
|
|
8
|
+
`bun run build:themes`, so the pages open from a fresh checkout.
|
|
8
9
|
|
|
9
10
|
## Templates
|
|
10
11
|
|
|
@@ -164,7 +164,7 @@ A full form using the control classes, field wrappers, and form actions:
|
|
|
164
164
|
- `required` is the semantic source of truth. Add `<span class="required-mark" aria-hidden="true">*</span>` inside a label only when a visual required marker is wanted; the framework does not add one automatically.
|
|
165
165
|
- `.field` is the canonical field wrapper. It works on `<label>` and `<div>`.
|
|
166
166
|
- `.field-label` is element-agnostic. Use it on `<span>` inside a wrapped label, on `<label for="…">` in a detached layout, or on `<legend>` inside a fieldset.
|
|
167
|
-
- `.field-group` styles a `<fieldset class="field-group">` as a grouped field container. Its legend gutter is tunable with `--fieldset-legend-padding-inline` (`var(--space-10)`).
|
|
167
|
+
- `.field-group` styles a `<fieldset class="field-group">` as a grouped field container. Its legend gutter is tunable with `--fieldset-legend-padding-inline` (`var(--space-10)`). It carries no sibling margin: space consecutive groups with `.stack` on the form, so the rhythm follows the layout instead of the component.
|
|
168
168
|
- Use native `<optgroup>` and `disabled` options in `.select` controls when applicable; the customizable picker preserves both as a progressive enhancement.
|
|
169
169
|
- `.choice` is the choice-label API. Use `.check` or `.radio` on the nested control. The control goes first, the label group second, so multi-line labels align the control with the first line.
|
|
170
170
|
- For a switch, use `class="switch"` and `role="switch"`.
|
|
@@ -21,7 +21,7 @@ without its label would only break the alignment. Scale them by scaling their
|
|
|
21
21
|
type instead.
|
|
22
22
|
|
|
23
23
|
```html demo
|
|
24
|
-
<form novalidate>
|
|
24
|
+
<form class="stack" novalidate>
|
|
25
25
|
<fieldset class="field-group">
|
|
26
26
|
<legend class="field-label">Text control states</legend>
|
|
27
27
|
<div class="stack" style="--grid-min: 14rem;">
|
|
@@ -10,9 +10,19 @@ Components are semantic boxes: `.btn`, `.badge`, `.alert`, `.card`, `.avatar`, e
|
|
|
10
10
|
|
|
11
11
|
`.primary`, `.secondary`, `.success`, `.warning`, `.danger` do not style elements directly. They only expose `--intent` and `--intent-fg`. Components and variants decide how to consume them.
|
|
12
12
|
|
|
13
|
+
Intent classes define the current `--intent` value; they do not form a
|
|
14
|
+
general-purpose color utility system. Use `.intent-color` when a simple element
|
|
15
|
+
should consume the current intent as its foreground color. It works with an
|
|
16
|
+
intent on the same element or inherited from an ancestor.
|
|
17
|
+
|
|
13
18
|
```html demo
|
|
14
19
|
<button class="btn primary">Primary</button>
|
|
15
20
|
<span class="badge success">Success</span>
|
|
21
|
+
<span class="success intent-color">Success text</span>
|
|
22
|
+
<span class="danger">
|
|
23
|
+
<i class="ti ti-alert-triangle intent-color" aria-hidden="true"></i>
|
|
24
|
+
Something needs attention
|
|
25
|
+
</span>
|
|
16
26
|
```
|
|
17
27
|
|
|
18
28
|
There is no `.btn-primary` or `.badge-success`. Intents are generic and reusable across any component that supports them.
|
|
@@ -35,7 +45,7 @@ Custom intents need no framework support — define `--intent` and `--intent-fg`
|
|
|
35
45
|
|
|
36
46
|
## Variants
|
|
37
47
|
|
|
38
|
-
`.solid`, `.soft`, `.outline` define the visual treatment by setting `--ui-bg`, `--ui-fg`, `--ui-border`. Components consume these tokens with sensible fallbacks. Interactive components also set a `--ui-hover-bg` recipe that their hover rule reads.
|
|
48
|
+
`.solid`, `.soft`, `.outline`, `.surface` define the visual treatment by setting `--ui-bg`, `--ui-fg`, `--ui-border`. Components consume these tokens with sensible fallbacks. Interactive components also set a `--ui-hover-bg` recipe that their hover rule reads.
|
|
39
49
|
|
|
40
50
|
`.btn` defaults to `.solid`; `.badge` and `.alert` default to `.soft`.
|
|
41
51
|
|
|
@@ -133,7 +133,7 @@ Spacing should be useful without becoming a design-token encyclopedia.
|
|
|
133
133
|
}
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
Official steps are named in tens so the scale stays extensible
|
|
136
|
+
Official steps are named in tens so the scale stays extensible. **Actual CSS will never define a `--space-*` token that is not a multiple of 10.** The intermediate names (`--space-15`, `--space-45`, …) are reserved for application-level interpolation: defining them is not writing into the framework namespace, it is using the half of the scale the framework has permanently given up.
|
|
137
137
|
|
|
138
138
|
Use `em` for spacing that should scale with the component text size, such as button gaps and inline padding. Use `rem` for global rhythm, layouts, and fixed density.
|
|
139
139
|
|
|
@@ -220,7 +220,7 @@ With `color-mix()` support the shadows derive from `--shadow-color` (a theme tok
|
|
|
220
220
|
|
|
221
221
|
### Motion
|
|
222
222
|
|
|
223
|
-
Motion
|
|
223
|
+
Motion durations keep transitions consistent and easy to disable.
|
|
224
224
|
|
|
225
225
|
```css
|
|
226
226
|
:root {
|
|
@@ -229,10 +229,13 @@ Motion tokens keep transitions consistent and easy to disable.
|
|
|
229
229
|
--duration-slow: 200ms; /* one-shot open/close */
|
|
230
230
|
--duration-spin: 0.75s; /* continuous spin (.spinner) */
|
|
231
231
|
--duration-shimmer: 1.2s; /* continuous shimmer (.skeleton, indeterminate .progress) */
|
|
232
|
-
--ease:
|
|
232
|
+
--ease-enter: cubic-bezier(0.2, 0, 0, 1);
|
|
233
|
+
--ease-exit: cubic-bezier(0.4, 0, 1, 1);
|
|
233
234
|
}
|
|
234
235
|
```
|
|
235
236
|
|
|
237
|
+
Ordinary interaction/state transitions have **no easing token**: they use the CSS default `ease` directly, and the dialog shake feedback plus the `actual-dialog` View Transition keep that default deliberately. The presence pair exists only for one-shot open/close where open and closed states own separate transition declarations (`.status-bar`/`.is-open`, `dialog.modal[open]`, `dialog.drawer[open]`): `--ease-enter` decelerates the appearance, `--ease-exit` accelerates the departure. The pair follows Material's standard rhythm; the emphasized-decelerate entrance is deliberately not offered because it only pays off at 250–400ms durations, beyond this vocabulary. Backdrops keep `ease` — a scrim only fades, it does not travel — but track their surface's duration. Toggles that share one transition list at `--duration-fast` (flyout, tooltip) also stay on `ease`: at 100ms the curve barely resolves and entry/exit cannot split on a single rule. These absences are deliberate, not gaps; a theme with a different motion character overrides `--ease-enter` / `--ease-exit`.
|
|
238
|
+
|
|
236
239
|
`reset.css` clamps raw animation and transition durations to `0.01ms`, resets their delays, and restores `html` scroll behavior under `prefers-reduced-motion: reduce`. Decorative loops effectively complete immediately without blanket-disabling animation support.
|
|
237
240
|
|
|
238
241
|
### Icons
|
|
@@ -294,6 +297,7 @@ The shared visual variants are:
|
|
|
294
297
|
- `.solid`: full background, paired foreground. This is the default for buttons.
|
|
295
298
|
- `.soft`: lightly tinted background, colored text. Good for alerts, badges, and secondary actions.
|
|
296
299
|
- `.outline`: transparent background, colored border and text.
|
|
300
|
+
- `.surface`: the page surface with the theme border, and the intent only in the text. The neutral chrome neither `.soft` (the intent-tinted treatment) nor `.outline` (no fill) can give.
|
|
297
301
|
|
|
298
302
|
Buttons also support two button-only variants:
|
|
299
303
|
|
|
@@ -77,7 +77,15 @@ There is also a non-fluid `.lead` utility in the core, for a simple readable int
|
|
|
77
77
|
|
|
78
78
|
Global links are intentionally neutral. Only `.prose` styles them as prose links, and only components style their own link-like elements (nav links, button-as-link, tabs, breadcrumbs, etc.). The reason is that underlining every `a` globally fights against button-like links, nav links, clickable cards, menu items, and tab triggers. Components that need link semantics should opt in with their own rule.
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
`--link` is the theme-level link ink. It is unset by default, so a bare `a` inherits its color and `.prose` links fall back to `--primary` — nothing changes until a theme opts in. Setting it is that opt-in, and it reaches both places at once:
|
|
81
|
+
|
|
82
|
+
```css
|
|
83
|
+
:root {
|
|
84
|
+
--link: var(--primary); /* bare links become link-colored, prose included */
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The `.prose` fallback to `--primary` breaks down for a theme whose primary is a light or fully saturated accent: it can carry a filled button, where it is the background under its own `--primary-fg`, but not inline body text, where it has to hold contrast against `--surface` on its own. `--link` is the override for exactly that case — hover included, with no rule to restate.
|
|
81
89
|
|
|
82
90
|
```css
|
|
83
91
|
[data-theme="vivid"] {
|
|
@@ -133,7 +141,7 @@ There is no `--line-height-normal`. It would be redundant with `--line-height`.
|
|
|
133
141
|
- `--prose-line-height` — body line height inside `.prose`.
|
|
134
142
|
- `--prose-heading-line-height` — heading line height inside `.prose`.
|
|
135
143
|
- `--prose-flow` — vertical rhythm between sibling blocks inside `.prose`.
|
|
136
|
-
- `--link` —
|
|
144
|
+
- `--link` — theme-level link ink, listed here because `.prose` is its main consumer. Unset, bare links inherit and prose links fall back to `--primary`.
|
|
137
145
|
|
|
138
146
|
## text-wrap
|
|
139
147
|
|
|
@@ -75,7 +75,7 @@ Actual CSS uses a small unprefixed class grammar:
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
Intents are `.primary`, `.secondary`, `.success`, `.warning`, and `.danger`, and
|
|
78
|
-
work across components. Variants such as `.solid`, `.soft`, and `.
|
|
78
|
+
work across components. Variants such as `.solid`, `.soft`, `.outline`, and `.surface` are
|
|
79
79
|
shared by buttons, badges, alerts, and cards; `.inverted` is a shared surface
|
|
80
80
|
modifier that paints any block with the inverse surface. `.ghost` and `.link`
|
|
81
81
|
are button-only. Size variants `.sm` and `.lg` scale controls consistently.
|
|
@@ -6,6 +6,8 @@ Horizontal rails that stay useful without JavaScript and snap in modern browsers
|
|
|
6
6
|
|
|
7
7
|
Use `.scroll-snap` for a niche row of items that should scroll horizontally, such as card rails, media strips, overflow tabs, or a simple touch-friendly carousel baseline. Scrolling only appears when the items are wider than the container; set `--scroll-snap-item-size` for card rails.
|
|
8
8
|
|
|
9
|
+
**Related terms:** carousel, card carousel, horizontal scroller, media rail, scrolling rail.
|
|
10
|
+
|
|
9
11
|
```html demo
|
|
10
12
|
<section class="stack" aria-labelledby="featured-title">
|
|
11
13
|
<h2 id="featured-title">Featured articles</h2>
|
|
@@ -5,6 +5,8 @@ switches intrinsically according to its own available width: the regions sit
|
|
|
5
5
|
side by side when the main minimum, preferred aside width, and gap fit; they
|
|
6
6
|
otherwise stack. No `.container-query` ancestor is required.
|
|
7
7
|
|
|
8
|
+
**Related terms:** master-detail, split view.
|
|
9
|
+
|
|
8
10
|
```html demo
|
|
9
11
|
<div class="sidebar-layout">
|
|
10
12
|
<article class="stack">
|
|
@@ -21,3 +21,5 @@ Use `.topbar` for the structural shell of an app-shell header: sticky positionin
|
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
This is for the app-shell topbar specifically — a structural need that recurs unchanged across app UIs regardless of brand. It is not for marketing or editorial site headers, which are one-off visual identity per page.
|
|
24
|
+
|
|
25
|
+
**Related terms:** sticky header, app bar, application header.
|
|
@@ -32,3 +32,21 @@ Use `.sr-only` for text that should be available to assistive technology but vis
|
|
|
32
32
|
border: 0;
|
|
33
33
|
}
|
|
34
34
|
```
|
|
35
|
+
|
|
36
|
+
## Touch targets
|
|
37
|
+
|
|
38
|
+
`.touch-target` adds 8px of invisible hit area around a small control on coarse
|
|
39
|
+
primary pointers, without growing the visual. Apply it opt-in to targets that
|
|
40
|
+
are genuinely small — icon buttons, close buttons, compact actions.
|
|
41
|
+
|
|
42
|
+
```html demo
|
|
43
|
+
<button class="btn icon-only touch-target" type="button" aria-label="Close">
|
|
44
|
+
<i class="ti ti-x" aria-hidden="true"></i>
|
|
45
|
+
</button>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Related terms:** touch target, hit area, tap target, target size.
|
|
49
|
+
|
|
50
|
+
On fine pointers the class is fully neutral. On coarse pointers it establishes
|
|
51
|
+
a relative positioning context — do not apply it to controls whose positioning
|
|
52
|
+
is structural (`fixed`, `absolute`, `sticky`).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "actual-css",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Plain CSS component framework with semantic classes, universal variants, small tokens, theme hooks, and progressive enhancements.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "bun@1.4.0",
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
"container-query",
|
|
80
80
|
"cursor-pointer",
|
|
81
81
|
"danger",
|
|
82
|
+
"data-list",
|
|
82
83
|
"dialog-close",
|
|
83
84
|
"dialog-confirmation",
|
|
84
85
|
"dialog-icon",
|
|
@@ -134,6 +135,7 @@
|
|
|
134
135
|
"inline-size-full",
|
|
135
136
|
"input",
|
|
136
137
|
"input-icon",
|
|
138
|
+
"intent-color",
|
|
137
139
|
"inverted",
|
|
138
140
|
"is-open",
|
|
139
141
|
"is-sheet",
|
|
@@ -246,6 +248,7 @@
|
|
|
246
248
|
"stretch",
|
|
247
249
|
"subtle",
|
|
248
250
|
"success",
|
|
251
|
+
"surface",
|
|
249
252
|
"surface-backdrop",
|
|
250
253
|
"switch",
|
|
251
254
|
"switcher",
|
|
@@ -269,6 +272,7 @@
|
|
|
269
272
|
"textarea",
|
|
270
273
|
"tooltip",
|
|
271
274
|
"topbar",
|
|
275
|
+
"touch-target",
|
|
272
276
|
"truncate",
|
|
273
277
|
"user-select-none",
|
|
274
278
|
"visibility-hidden",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Data list — term/value pairs for the properties of a single object.
|
|
3
|
+
*
|
|
4
|
+
* Expects alternating <dt>/<dd> children: one term, one value per property.
|
|
5
|
+
* A plain <dl> handles richer relationships (several terms or descriptions)
|
|
6
|
+
* and stays untouched by this component.
|
|
7
|
+
*
|
|
8
|
+
* Why margin resets: neutralizes .prose list margins if .data-list appears
|
|
9
|
+
* inside an authored rich-text scope; the grid owns row/column rhythm.
|
|
10
|
+
*/
|
|
11
|
+
.data-list {
|
|
12
|
+
display: grid;
|
|
13
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
14
|
+
align-items: baseline;
|
|
15
|
+
gap: var(--space-20) var(--space-40);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.data-list > dt {
|
|
19
|
+
min-inline-size: 0;
|
|
20
|
+
margin-block-start: 0;
|
|
21
|
+
font-weight: var(--font-weight-strong);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.data-list > dd {
|
|
25
|
+
min-inline-size: 0;
|
|
26
|
+
margin: 0;
|
|
27
|
+
}
|
|
@@ -13,11 +13,16 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Internal:
|
|
15
15
|
* --drawer-closed-translate (side/RTL positioning state)
|
|
16
|
+
* --drawer-motion-duration (shared by panel and ::backdrop so exit duration
|
|
17
|
+
* changes in one place; entry state redefines it longer)
|
|
16
18
|
*/
|
|
17
19
|
dialog.drawer {
|
|
18
20
|
--drawer-size: 20rem;
|
|
19
21
|
--drawer-pad: var(--space-40);
|
|
20
22
|
--drawer-closed-translate: -100%;
|
|
23
|
+
/* Exit is shorter than entry so the panel clears quickly; the scrim reads
|
|
24
|
+
the same variable through inheritance and never lags the panel. */
|
|
25
|
+
--drawer-motion-duration: var(--duration);
|
|
21
26
|
|
|
22
27
|
/* Keep the surface anchored to the viewport in the top layer. This also
|
|
23
28
|
provides the containing block for the absolutely positioned close button.
|
|
@@ -41,16 +46,20 @@ dialog.drawer {
|
|
|
41
46
|
opacity: 0;
|
|
42
47
|
transform: translateX(var(--drawer-closed-translate));
|
|
43
48
|
transition:
|
|
44
|
-
opacity var(--duration-
|
|
45
|
-
transform var(--duration-
|
|
49
|
+
opacity var(--drawer-motion-duration) var(--ease-exit),
|
|
50
|
+
transform var(--drawer-motion-duration) var(--ease-exit);
|
|
46
51
|
}
|
|
47
52
|
|
|
48
53
|
dialog.drawer[open] {
|
|
54
|
+
--drawer-motion-duration: var(--duration-slow);
|
|
49
55
|
display: grid;
|
|
50
56
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
51
57
|
gap: var(--space-40);
|
|
52
58
|
opacity: 1;
|
|
53
59
|
transform: translateX(0);
|
|
60
|
+
transition:
|
|
61
|
+
opacity var(--drawer-motion-duration) var(--ease-enter),
|
|
62
|
+
transform var(--drawer-motion-duration) var(--ease-enter);
|
|
54
63
|
}
|
|
55
64
|
|
|
56
65
|
/* Backdrop color sourced from components/surface.css so it matches .modal
|
|
@@ -58,7 +67,9 @@ dialog.drawer[open] {
|
|
|
58
67
|
dialog.drawer::backdrop {
|
|
59
68
|
background: var(--backdrop-fill);
|
|
60
69
|
opacity: 0;
|
|
61
|
-
|
|
70
|
+
/* Scrim curve stays neutral `ease`; only the panel's character curves
|
|
71
|
+
apply. Duration follows --drawer-motion-duration through inheritance. */
|
|
72
|
+
transition: opacity var(--drawer-motion-duration) ease;
|
|
62
73
|
}
|
|
63
74
|
|
|
64
75
|
dialog.drawer[data-side="end"] {
|
|
@@ -94,17 +105,25 @@ dialog.drawer nav {
|
|
|
94
105
|
@supports (transition-behavior: allow-discrete) {
|
|
95
106
|
dialog.drawer {
|
|
96
107
|
transition:
|
|
97
|
-
opacity var(--duration-
|
|
98
|
-
transform var(--duration-
|
|
99
|
-
overlay var(--duration
|
|
100
|
-
display var(--duration
|
|
108
|
+
opacity var(--drawer-motion-duration) var(--ease-exit),
|
|
109
|
+
transform var(--drawer-motion-duration) var(--ease-exit),
|
|
110
|
+
overlay var(--drawer-motion-duration) allow-discrete,
|
|
111
|
+
display var(--drawer-motion-duration) allow-discrete;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
dialog.drawer[open] {
|
|
115
|
+
transition:
|
|
116
|
+
opacity var(--drawer-motion-duration) var(--ease-enter),
|
|
117
|
+
transform var(--drawer-motion-duration) var(--ease-enter),
|
|
118
|
+
overlay var(--drawer-motion-duration) allow-discrete,
|
|
119
|
+
display var(--drawer-motion-duration) allow-discrete;
|
|
101
120
|
}
|
|
102
121
|
|
|
103
122
|
dialog.drawer::backdrop {
|
|
104
123
|
transition:
|
|
105
|
-
opacity var(--duration
|
|
106
|
-
overlay var(--duration
|
|
107
|
-
display var(--duration
|
|
124
|
+
opacity var(--drawer-motion-duration) ease,
|
|
125
|
+
overlay var(--drawer-motion-duration) allow-discrete,
|
|
126
|
+
display var(--drawer-motion-duration) allow-discrete;
|
|
108
127
|
}
|
|
109
128
|
}
|
|
110
129
|
|
|
@@ -140,7 +159,7 @@ dialog.drawer nav {
|
|
|
140
159
|
|
|
141
160
|
@media (prefers-reduced-motion: no-preference) {
|
|
142
161
|
dialog.drawer.is-static {
|
|
143
|
-
animation: actual-dialog-static var(--duration-slow)
|
|
162
|
+
animation: actual-dialog-static var(--duration-slow) ease;
|
|
144
163
|
}
|
|
145
164
|
}
|
|
146
165
|
|
|
@@ -73,11 +73,10 @@
|
|
|
73
73
|
box-shadow: var(--shadow-popout);
|
|
74
74
|
list-style: none;
|
|
75
75
|
opacity: 1;
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
translate var(--duration-fast) var(--ease);
|
|
76
|
+
/* Anchored flyouts fade in and out; scaling around the center would detach
|
|
77
|
+
the anchored edge from its trigger on wide panels. The sheet presentation
|
|
78
|
+
below adds its own translate motion. */
|
|
79
|
+
transition: opacity var(--duration-fast) ease;
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
.flyout.is-open:not(.is-sheet) {
|
|
@@ -87,7 +86,6 @@
|
|
|
87
86
|
@starting-style {
|
|
88
87
|
.flyout.is-open {
|
|
89
88
|
opacity: 0;
|
|
90
|
-
scale: 0.98;
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
91
|
|
|
@@ -109,22 +107,24 @@
|
|
|
109
107
|
max(var(--space-30), env(safe-area-inset-bottom));
|
|
110
108
|
border-end-start-radius: 0;
|
|
111
109
|
border-end-end-radius: 0;
|
|
110
|
+
/* Sheet motion is a directional slide from the viewport edge; it replaces
|
|
111
|
+
the base fade-only recipe. */
|
|
112
|
+
transition:
|
|
113
|
+
opacity var(--duration-fast) ease,
|
|
114
|
+
translate var(--duration-fast) ease;
|
|
112
115
|
}
|
|
113
116
|
|
|
114
117
|
.flyout[hidden] {
|
|
115
118
|
display: none;
|
|
116
119
|
opacity: 0;
|
|
117
|
-
scale: 0.98;
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
.flyout.is-sheet[hidden] {
|
|
121
|
-
scale: 1;
|
|
122
123
|
translate: 0 var(--space-30);
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
@starting-style {
|
|
126
127
|
.flyout.is-sheet.is-open {
|
|
127
|
-
scale: 1;
|
|
128
128
|
translate: 0 var(--space-30);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -132,9 +132,14 @@
|
|
|
132
132
|
@supports (transition-behavior: allow-discrete) {
|
|
133
133
|
.flyout {
|
|
134
134
|
transition:
|
|
135
|
-
opacity var(--duration-fast)
|
|
136
|
-
|
|
137
|
-
|
|
135
|
+
opacity var(--duration-fast) ease,
|
|
136
|
+
display var(--duration-fast) allow-discrete;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.flyout.is-sheet {
|
|
140
|
+
transition:
|
|
141
|
+
opacity var(--duration-fast) ease,
|
|
142
|
+
translate var(--duration-fast) ease,
|
|
138
143
|
display var(--duration-fast) allow-discrete;
|
|
139
144
|
}
|
|
140
145
|
}
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Meter — native
|
|
2
|
+
* Meter — native and segmented gauges for known-range values.
|
|
3
3
|
*
|
|
4
4
|
* Maps the three standard meter zones (optimum / suboptimum / even-less-good)
|
|
5
5
|
* to the shared success / warning / danger intent colors.
|
|
6
|
+
*
|
|
7
|
+
* Thickness is a dimension, not a density step: the bar always spans its
|
|
8
|
+
* container and only gets thinner or thicker, so --bar-height is the API and
|
|
9
|
+
* .sm/.lg are deliberately not supported.
|
|
10
|
+
*
|
|
11
|
+
* Public hooks:
|
|
12
|
+
* --meter-value
|
|
13
|
+
* --bar-height
|
|
6
14
|
*/
|
|
7
15
|
|
|
8
16
|
.meter {
|
|
@@ -17,6 +25,25 @@
|
|
|
17
25
|
background: var(--surface-subtle);
|
|
18
26
|
}
|
|
19
27
|
|
|
28
|
+
/* A non-native meter is a weighted flex container. The element type keeps the
|
|
29
|
+
native <meter> API and the composed segmented API distinct without another
|
|
30
|
+
public variant class. */
|
|
31
|
+
.meter:not(meter) {
|
|
32
|
+
--intent: initial;
|
|
33
|
+
|
|
34
|
+
display: flex;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.meter:not(meter) > * {
|
|
38
|
+
flex: var(--meter-value, 1) 1 0;
|
|
39
|
+
min-inline-size: 0;
|
|
40
|
+
background: var(--intent);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.meter:not(meter) > * + * {
|
|
44
|
+
border-inline-start: var(--border-width) solid var(--surface);
|
|
45
|
+
}
|
|
46
|
+
|
|
20
47
|
.meter::-webkit-meter-bar {
|
|
21
48
|
-webkit-appearance: none;
|
|
22
49
|
block-size: var(--bar-height);
|