You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
.inverted is removed: it mixed a contrasting surface with theme inversion while remapping only part of the palette. Use a data-theme island for a complete light/dark subtree, or paint a local band in application CSS.
.white-space-normal is renamed .text-wrap, the counterpart of .text-nowrap.
.dialog-close, .drawer-close, and .alert-dismiss are replaced by the shared .close (components/close.css); a modular build imports it next to its host.
A removable badge needs <button class="close">: a bare .badge > button is no longer styled, and an empty one no longer paints an X.
--alert-dismiss-size and --badge-dismiss-icon-size are replaced by --close-size / --close-icon-size.
The dialog corner applies to a .close that is a direct child of the dialog, of its form or header, or of a form inside that header.
getSurfaceAutoClose is removed from surface.js: it had no caller, and the code that opens a surface passes its own autoClose.
.column-span-1…12 and .column-start-1…12 are replaced by the --column-span / --column-start hooks on each .column-layout child.
The bare actual-css entrypoint resolves to the complete compiled framework, like actual-css/full, style, unpkg, and jsdelivr; import actual-css/css for the core alone.
package.json#main is removed.
dist/actual.css and dist/actual.min.css are no longer built or published; compose the core from actual-css/css.
dist/actual.js (the compiled loader alone) is no longer built or published; bundle your own entry from actual-css/js and actual-css/js/*.
.input, .textarea, .select, and an open custom select draw a --focus-ring-width inset outline in --focus instead of a focus border plus outer halo.
.join no longer moves a field's focus ring onto the group: each segment keeps its own indicator.
.btn, .close, .check, .radio, .switch, .choice-card, .file, and .color draw a solid --focus-ring-width line in --focus at --focus-outline-offset instead of a translucent halo.
.range thumb focus ring is solid --focus instead of --focus-ring.
--focus-ring and --focus-ring-shadow are removed; every focus indicator reads --focus.
--btn-focus-color and --btn-focus-ring-color are removed: a button's focus color no longer follows its intent.
.check, .radio, and .switch keep their resting border on focus instead of switching it to --focus.
The default --focus is hsl(268 30% 55%) in both schemes instead of var(--neutral): a primary-hued mid-tone that holds 3:1 against --surface and --surface-solid.
--focus-ring-width is 2px instead of 3px, and 3px instead of 4px under prefers-contrast: more.
bootstrap-v6 sets --focus: #3d8bfd and --focus-ring-width: 3px instead of its own ring recipe.
Added
.bleed is a shared surface contract: src/css/components/bleed.css reads the relayed --surface-pad, so a direct child of a .drawer or of an accordion panel escapes its inset like a card child already did.
--accordion-pad hook: the summary row and the panel no longer hard-code their inset, and the panel relays it so .accordion.separated items accept a .bleed child.
--accordion-marker-size hook.
.data-list.stacked: the value sits under its term instead of beside it.
--bleed-pad is a public read-only hook: padding: var(--bleed-pad) pads a .bleed band that is not a header, footer, or figure.
.join supports a control nested one wrapper level deep (e.g. a combobox element): the wrapper carries the group corners and primary-edge z-index, the inner control inherits the radius, and no widget is named.
.nav-link works on a <button>: UA button chrome is neutralized with <a>-identical metrics.
material demo theme: Material 3 baseline palette, filled underline fields and addons whose focus thickens the bottom line, pill buttons, and a joined outline action drawn as one more filled segment.
.choice-card.chip: compact pill form for filter chips and selectable tags, with a leading dot that turns into the check without moving the label.
--choice-chip-dot is a read-only hook on the chip's ::before: the check-slot centre, so a theme can grow the dot's circle() clip into a selected fill.
The material theme grows the chip dot into a tonal fill.
The gradient theme demos the outer-halo field focus; bootstrap-v6 and edge have no field focus override.
demo/templates/contrast-contexts.html: the page, data-theme islands, a card island, a named theme and an application-painted band with every intent variant, a form, a combobox, a date picker and focus lines measured live, plus a .join gallery with no focus adaptation.
Fixed
dialog.js only backdrop-dismisses when the press started on the backdrop: a text selection released over the backdrop no longer closes (or shakes) the dialog.
dialog.js restores the horizontal scroll position on open, not just the vertical one.
tab.js, focus-group.js, menu.js, and the flyout trigger ignore IME-composed and ctrl/alt/meta-modified keys; escape.js ignores composition too.
status.js restores its bar when the host dialog was removed from the DOM (htmx/Turbo swap): the next status() heals instead of no-opping forever.
tooltip.js resynchronizes shorthand data-tooltip text on every show, so a "Copy" → "Copied!" update displays without rewiring.
The text of a visible shorthand tip updates on the next show, never mid-flight.
flyout.js sets aria-haspopup="menu" only for a true role="menu" panel: <menu> carries the implicit list role.
dialog.js respects closedby="none" on cancel when HTMLDialogElement.closedBy is unavailable, while explicit close requests still work.
dialog.js restores generated ARIA attributes, title IDs, and rewritten closedby values on disconnect without overwriting author changes.
A last .bleed child of an accordion panel had square corners over the rounded .separated item or the group's last item.
applyEnhancement("validation", …) did not wire an already-connected form: validation.js now registers through registerEnhancement.
--app-nav-side-size was invisible to check:css-api (header read Public hook:).
A custom data-theme on <html> kept the default palette's --*-soft-fg calibration instead of resetting it, so the same theme resolved a different soft ink on <html data-theme> than on a nested island.
.nav-link hover/current and .app-nav hover fill with a tint of their own ink and follow --ui-fg, so they read on a bar with its own --ui-bg.
.flyout owns color: var(--text), like modal and drawer.
Preset themes: every --focus is a mid-tone that holds 3:1 on --surface and --surface-solid, and a --soft-fg-mix keeps every soft ink at 4.5:1 (report:theme-contrast lists no failing pair).
report:theme-contrast measures .badge.soft explicitly, so a preset that fills badges by default (bootstrap-v6) is no longer reported against a solid pair.
ocean theme: light --danger darkened (solid text 4.1:1 → 5.2:1), --soft-fg-mix: 50% (soft inks from 2.0–4.3:1 to ≥ 4.8:1), and a mid-tone --focus that holds 3:1 on both surfaces.
.join-addon honours --control-border-block-end-color / -width like text controls, so a theme's underline or accent edge reaches the addon segment.
gradient theme: the focus halo follows validation (--form-invalid-border), and it and material restyle the open customizable select with their field focus instead of the core :open outline.
--dialog-focus-bleed and --drawer-focus-bleed reserve max(--focus-ring-width, 2 × --border-width) past the offset, so a 3px component line (bootstrap-v6) is no longer clipped by 1px in a scrollable modal or drawer body.
A focused field in .join stacks above an adjacent field (z-index: 4 rule now follows the primary-edge rule), so the neighbour no longer covers its shared edge.
A field wrapped one level deep in .join fills its stretched wrapper (block-size: 100%) instead of stopping short of a taller sibling.
Focus indicators on a --surface-solid band and on a card nested in it hold 3:1 (a primary button's ring measured 1.1:1, a neutral one in a nested card 1.0:1).
Documentation and tooling
Combobox: the bridge recipe targets @lekoala/combobox 0.5.0, replaces its halo with the field inset outline, reads --form-invalid-border, and inherits .join corners.
tests/browser/field-focus.test.js asserts the field outline stays inside the border box (default and prefers-contrast) and that --focus holds 3:1 on --surface and --surface-solid in both schemes.
bun run report:theme-contrast also reports each preset's --focus against --surface and --surface-solid.
Theming: "Make a dark (or light) section" replaces the .inverted recipe — a data-theme island for a whole context, application CSS for a painted band.
Button: a dark button (formerly .btn.inverted) is a custom intent, --intent: var(--surface-solid) / --intent-fg: var(--surface).
demo/templates/surfaces.html is removed; contrast-contexts.html covers surface boundaries.
tests/browser/inverted.test.js becomes surface-context.test.js, on an application-painted band.
Pushing a version tag publishes the GitHub release: .npmrc keeps npm version on the bare tag format, bun run release:notes extracts (and validates) the dated changelog section, and the CI release job attaches dist/.
Theming: a "Replace the palette with my own brand" entry names the tinted neutrals and soft-ink tokens a partial override leaves behind, and points at the minimal recolor set.
Tokens: the minimal recolor theme includes --shadow-color.
Tokens: a "Where a token is declared" section separates global, component-scoped, and relay properties, and shows the var(--card-pad, <default>) form for reading a component hook from outside.
Button: --ui-bg is the lever for an opaque fill under an intent-colored border, which no shared variant expresses; the rule must load after Actual CSS.
Accordion: the marker is a masked box, so a decorated marker needs a real element — the opt-out recipe paints the chevron and keeps the hover and forced-colors behavior.
llms.txt lists the four data-enhance tokens and what the vocabulary does not have (compound intents, breakpoint prefixes, spacing scale, is-*, standalone modifiers).
parseHookSections throws on a near-miss section label (Public hook:) instead of silently dropping the hooks under it.
components.json: an entry no longer lists another component's class it only styles (bleed → card), and plumbingHooks carries the "Framework plumbing:" section.
Progressive enhancement guide: built-in data-* behaviors expose no refresh(); insert the element with its attribute set.
utilities/extra.css header no longer calls extra utilities non-API.
skills/actual-css/: a copyable starter agent skill for building with Actual CSS, shipped in the package and pointed to from the README and llms.txt.
Install docs lead with modular source imports; the full bundle is the zero-config and CDN option.
Modular import guide: "Start from the full entry" copies actual.full.css / full.js into the app and prunes them, and names the three shared CSS modules (close, bleed, spinner).
Tailwind v4 guide: explicit layer order plus the --font-sans / --font-mono / --font-weight-* / --radius-* token collisions.
Choice cards: the CSS hooks list --choice-card-border, --choice-card-bg, and --choice-chip-dot.
tests/browser/choice-chip.test.js asserts the chip label never moves on check, the native inputs stay the controls, Tab focus draws the outer ring, and forced colors keep checked distinct.
Theming: a data-theme island paints nothing; give it a surface, and put it on a wrapper rather than a <fieldset>, whose legend straddles the border.
demo/scripts/theme-picker.js: every demo page uses one <theme-picker> fed by a single theme list, replacing 30 hand-copied selects and admini-theme.js.
check:templates fails when theme-picker.js drifts from src/css/themes/index.css or a page hand-copies a theme list.