Skip to content

Integrated styling and application CSS (0.65 API)

Status: Implemented for the bounded 0.65 issue slices. The application-CSS surface and the four follow-up presentation contracts are implemented and covered by the 0.65 release evidence. The Required/Progressive boundary is recorded in the refined scope. See RFC-0092.

Authoring model

app.styles(
    name: str,
    source: str | Path,
    *,
    scope: str | None = None,
    layer: Literal["application", "overrides"] = "application",
    global_: bool = False,
    media: tuple[str, ...] = (),
    allowed_roots: Sequence[str | Path] | None = None,
    allowed_roots: Sequence[str | Path] | None = None,
)

This is the implemented Stage 0 signature. source must resolve to a local, package-owned asset. scope emits a stable root hook such as data-hedron-style-scope="app"; global_ is an explicit opt-in and is rejected when the source violates the global-CSS policy. media is a finite, manifest-recorded list rather than an arbitrary response-time condition. allowed_roots explicitly authorizes an installed package or workspace root when the source is outside the current working directory; it defaults to the current project root. allowed_roots explicitly authorizes an installed package or workspace root when the source is outside the current working directory; it defaults to the current project root.

The registration API must accept only local, package-owned assets and produce a stylesheet manifest with source path, fingerprint, layer, scope, CSP disposition, and provenance. A stylesheet is not implicitly loaded because a file happens to exist.

The supported authoring ladder is semantic props → theme/recipes → registered application CSS → explicit scoped/global CSS → ejected CSS. Ordinary CSS remains ordinary CSS; Hedron adds ownership, ordering, diagnostics, and stable hooks around it.

The precedence contract is generated reset/tokens/base/components, then registered application CSS, then explicit utility and override layers. Existing semantic behavior, interaction ownership, route state, and accessibility semantics are not style override points. An application stylesheet may change presentation only within the public hook and token contracts.

Public hooks

Rendered markup may expose manifest-backed attributes such as:

<div data-hedron-component="data-view"
     data-hedron-part="header"
     data-hedron-state="loading">
</div>

Component names, parts, slots, and state values are public only when present in the versioned hook manifest. Generated class names and DOM shapes not listed in that manifest are private and may change in a patch release. Typed selector helpers are Progressive until their generated metadata and compatibility rules are frozen.

The first Required public part/state inventory is deliberately finite:

  • AppShell.nav.link: default, hover, current, disabled;
  • ProcessFlow.step: current, complete, blocked, skipped;
  • Card: heading, supporting copy, metadata;
  • FormField: control, focus, invalid, disabled;
  • SplitView: separator and responsive collapse.

Additional component parts, slots, and state names require a later manifest decision; private descendant selectors and user-supplied selector values are rejected by the contract.

Tokens and cascade

Application tokens use a namespace owned by the registering package or application. They compose with the existing ThemeSpec/ThemePatch graph, carry provenance, and cannot overwrite a core token without an explicit compatibility error. The layer order is:

@layer reset, tokens, base, components, application, utilities, overrides;

The application layer is explicit and inspectable. Global CSS requires an explicit opt-in and cannot bypass CSP, source maps, unsafe-at-rule checks, or the public-hook policy.

Required issue slices are bounded to six named motion recipes (instant, standard, emphasized, reveal, elevate, crossfade), semantic data-view/table chrome tokens, and native-first control families for checkbox/radio, select, range, file, date/time, and number inputs. These slices must provide the states and fallbacks listed in the acceptance contract; they do not imply a product-wide restyling of every component.

Diagnostics and ejection

Static commands:

hedron style explain <surface> [--property <name>]
hedron --app <module:attr> style inspect
hedron style check --custom-css <path>
hedron --app <module:attr> style eject-css --output <path>
hedron --app <module:attr> style diff --ejected-path <path>
hedron --app <module:attr> style update --check --manifest <path>

Diagnostics identify the winning declaration, layer, selector/hook, token, source asset, and fallback. Output is deterministic and redacted. Ejected blocks retain source-map and manifest provenance; generated blocks are never silently overwritten by update.

Implemented issue slices #712–#715

  • AmbientLayer and AmbientCanvas provide ordered, inert document layers. AmbientBackdrop accepts layers= as a compatibility entry point.
  • AppShellChrome is passed as AppShell(chrome=...) and emits finite geometry-policy markers for presets, sticky behavior, offsets, gaps, insets, spacing, and density.
  • presentation_token_manifest() reports declared, consumed, overridden, and unconsumed built-in presentation tokens. Bundled CSS consumes the emitted typography, layout, geometry, motion, data, and control variables with compatibility fallbacks.
  • ResponsiveCondition supports viewport-max, container-max, viewport-range, and container-range (for example md-to-lg), with deterministic ordering and contradiction diagnostics.

Required behavior contracts

  • focus-visible, invalid, disabled, busy, and reduced-motion behavior remains accessible on every touched surface;
  • native controls retain usable browser fallback when appearance customization is unsupported;
  • data views expose semantic header/body/empty/loading/error chrome rather than visual-only states;
  • print, forced-colors/high-contrast, reduced-transparency, RTL where applicable, responsive overflow, and no-JS paths are explicit on every touched surface;
  • CSS cannot change route, effect, authorization, interaction state ownership, or semantic markup;
  • package and adapter support is declared per surface, with no universal compatibility claim.