chirp-ui 0.5.0

Release 0.5.0

Install

pip install chirp-ui==0.5.0
# or
uv add chirp-ui==0.5.0

With Chirp:

pip install "bengal-chirp[ui]"

What's New

Agent-grounding-depth — manifest is the full Python surface

chirpui-manifest@2 now carries every component's complete Python API: params (with defaults and required flags), named slots, provides/consumes keys, and the {#- chirp-ui: … -#} doc-block description. Extraction is AST-only via kida.lexer / kida.parser(free-threading safe; no template compile).

Three new surfaces built on this:

  • docs/COMPONENT-OPTIONS.md grows a generated ## API Reference block, regenerated by poe build-docs and gated by poe build-docs-check.
  • python -m chirp_ui find <query> [--category=…]substring-matches components by name/block/category/description over the shipped manifest.
  • make release-preflight (prereq of make build / make release / make gh-release) regenerates chirpui.css + manifest.json + COMPONENT-OPTIONS.md and fails the release with a "commit these files" message if git diff --quietreports drift.

Plans were triaged intodocs/plans/ (in-flight) and docs/plans/done/ (shipped) with docs/INDEX.mdsplit accordingly, so agents cannot cite stale plans as live direction.

CSS modularization + registry parity

chirpui.css is now an output of the Python component registry rather than a hand-authored monolith. 160 per-component partials under src/chirp_ui/templates/css/partials/ are concatenated into the shipped stylesheet by scripts/build_chirpui_css.py (pure-Python stdlib; free-threading safe). poe build-css regenerates, poe build-css-checkfails CI if the committed output is stale.

The cascade order is public API:chirpui.css declares @layer chirpui.reset, chirpui.token, chirpui.base, chirpui.component, chirpui.utility; at the top. Consumers override by placing rules in @layer app.overrides (or any later-declared layer) — no specificity tricks required. See docs/CSS-OVERRIDE-SURFACE.md.

ComponentDescriptor gains an emitsproperty, and a registry↔CSS parity test pins every registry-cited class to a real selector in the stylesheet (and vice versa), so AI agents that ground against the registry cite real classes.

CSS envelope hardening — batch 1

Six high-bleed components now use the@layer chirpui.component { @scope (.chirpui-X) to (.chirpui-X .chirpui-X) { … } } envelope convention introduced by the 045_card.css pilot: tray, drawer, modal, surface, callout, video-card, channel-card.

The upper scope boundary stops outer-component rules at the first nested instance, fixing a class of cascade bleeds — most notably:scope:hover on video-card flipping inner card borders, link:hover .name on channel-card tinting nested names, and :has()-driven empty-header autohide on callout matching across nested boundaries.

Each component gets a dedicated browser test undertests/browser/that asserts variant rendering survives and the nested-bleed boundary holds via computed-style comparison.

Base-layer containment + preflight-style defaults

Content no longer punches past cards, surfaces, callouts, or bento cells without manual wrapping.

  • .chirpui-surface / .chirpui-callout get min-width: 0 + overflow-wrap: break-word.
  • .chirpui-field__input gets max-width: 100% + min-width: 0.
  • Card/surface links wrap long URLs viaoverflow-wrap: anywhere.
  • New utilities:.chirpui-scroll-x, .chirpui-truncate, .chirpui-clamp-2, .chirpui-clamp-3.
  • Zero-specificity:where() reset bounds raw <img> / <svg> / <video> / <iframe> / <embed> / <object> / <canvas>.
  • <pre> and <table>dropped inside a card/surface/callout auto-scroll horizontally.
  • prefers-reduced-motion: reduce is honored globally via *, ::before, ::after.
  • :root { accent-color: var(--chirpui-accent) }— native checkboxes, radios, range, progress all match the brand.
  • Prose paragraphs usetext-wrap: pretty; code blocks and prose <pre> get overscroll-behavior: containso scroll doesn't chain to the page.

Composite contract tests + provide/consume introspection

Newtests/test_composite_contracts.py parametrizes 18 composites and asserts each renders without ChirpUIValidationWarning, catching invalid-variant / unknown-icon bugs at chirp-ui CI time.

chirp_ui.inspect gains list_provides(), list_consumes(), and audit_provide_consume() (plus --provides, --consumes, --audit-context CLI subcommands) — a regex parser over the existing {# @provides … #} / {# @consumes … #}annotations so apps can audit dead provides, orphan consumers, and annotation drift.

Dev-mode fail-fast diagnostics

set_strict("auto") now reads the CHIRP_UI_DEV environment variable (truthy: 1/true/yes/on) at call time — dev hosts opt in once and every ChirpUIValidationWarning (invalid variant, unknown icon, bad size, unparseable color) escalates to ValueError.

Newchirp_ui.alpine module exposes ALPINE_REQUIRED_COMPONENTS (manifest of the 8 chirp-ui Alpine factory names) and a pure check_alpine_runtime(html) helper so frameworks can detect layouts that import interactive macros (theme toggle, command palette, collapsible sidebar, dropdown, dialog, copy) but forget to load chirpui-alpine.js.

Changed

  • kida-templates 0.6.0 → 0.7.0 — Kida 0.7.0 flipsstrict_undefined to True by default. Rather than opt out, 10 dict-iterating macros (timeline, dock, segmented_control, route_tabs, nav_tree, tree_view, bar_chart, breadcrumbs, description_list, config_row, plus five forms.html macros) were hardened to use .get("key") guards and | default("") inline rendering. New regression suite tests/test_strict_undefined.py renders each affected macro with minimal [{}]input. No public API changes.
  • Remove vestigialfrom __future__ import annotations imports (9 files); add DesignSystemReport / DesignSystemStats TypedDicts for design_system_report()return type.

Fixed

  • Shell action variant mapping — ChirpShellAction / ShellMenuItem variants (default, secondary) now map to btn variants via new shell_action_btn_variant filter; chevron-down registered in the icon set; overflow trigger uses ghost+ named chevron icon.