Skip to content

Releases: aqkprogrammer/dowel-ui

0.14.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 14 Oct 12:16
v0.14.0
0851ee6

Added

  • shader-background (experimental): a full-bleed WebGL scene behind
    content. One engine draws fourteen procedural presets: dunes, hills,
    storm-sea, meadow, petals, glass-wave, liquid-metal, silk,
    mesh-gradient, topography, particle-ocean, nebula, warp and
    helix. colors re-dresses any scene with theme tokens or CSS colours, and
    attach="viewport" pins it behind a whole page without clipping sticky
    headers. It stops drawing off-screen and in hidden tabs, shows one still frame
    under reduced motion, and falls back to a CSS gradient in the same palette
    without WebGL or after a lost context.

  • aurora-background, border-beam and cosmic-background.

  • Docs: /docs/backgrounds shows every background in the library live,
    with category filters and, for each one, a prompt for a coding agent that is
    generated from the same catalogue as the card.

  • Docs: manual install tabs on component and block pages, next to the CLI
    command.

  • Controls on every component page. A Controls toggle beside the live
    example sets its props in place and shows the tag as set; the Playground link
    carries those props with it.

  • Playground links hold the whole configuration: component, example, theme,
    mode, radius and every changed prop. Values read from a link are checked
    against the control that would have set them — an unknown option is dropped
    and a number is clamped to its range.

  • Registry: a control on each prop (select, boolean, number, text or
    colour), derived from the prop's type with its default, and refined by a new
    optional controls field in meta.ts for what a type cannot say (a number's
    range). The MCP server's get_component shows number ranges.

  • Registry: capabilities.tier — css, motion, canvas or webgl, the
    heaviest technique an item uses counting what it installs with it. Optional in
    the schema, so registries built before it still parse.

  • carousel: scroll-snap carousel with previous/next, dots, keyboard
    steps in reading direction, several items per view and a vertical layout.
    Rotation is opt-in and pauses on hover, focus, off-screen and in hidden tabs.

  • comparison-slider: two versions of one thing with a draggable,
    keyboard-operable divider.

  • color-picker: saturation square, hue and alpha, hex/rgb/oklch,
    swatches, eyedropper and a live WCAG contrast reading.

  • resizable: panels with window-splitter handles, limits and collapsible
    panels.

  • password-strength: a strength meter and rule checklist for a password
    field.

  • Hooks in the registry: use-reduced-motion and use-in-view install
    into the project's hooks folder (dowel add use-in-view), and are exported
    from @dowel-ui/react and @dowel-ui/react/hooks/*.

  • pattern-background, interactive-grid, light-beams and
    flow-field: a CSS pattern backdrop (dots, grid, lines, stripes, checker,
    grain), a pointer-lit canvas grid with ripples, CSS rays of light, and
    particles on a moving current. All four are on /docs/backgrounds, in a new
    "Patterns & grids" filter.

  • Docs: background pages link to the gallery ("14 looks in Backgrounds"),
    deep-linked to the look, and component pages say how a component draws when
    it is more than CSS ("Draws on a canvas", "Renders with WebGL").

  • Scroll effects: scroll-reveal (seven effects, staggered children, and
    content that is never hidden unless it will be revealed), parallax,
    stacking-cards and horizontal-scroll (pinned, driven by the page's own
    scroll, a plain scroller without JavaScript or under reduced motion).

  • Cursor effects: image-trail and cursor-spotlight, scoped to their
    box, leaving the system cursor alone, and off for touch and reduced motion.

  • Text effects: gradient-text, highlight-text, letter-swap and
    proximity-text — each keeps the text as real, readable text.

  • Buttons: effect-button gains a glitch effect; Button gains
    press="depth", raised on an edge it sinks into; confetti-button bursts
    confetti from itself, and burstConfetti() from anywhere.

  • Layout: glow-card gains variant="spotlight", and bento-grid lays out
    tiles of mixed sizes.

  • Navigation: navbar (static, sticky or hide-on-scroll — never hidden
    while it holds focus — with a mobile menu and a skip link),
    navigation-menu (links and mega menus) and bottom-nav (a phone tab bar
    with spoken badges).

  • AI: voice-input records, shows level and time, transcribes where the
    browser can, and explains a blocked or missing microphone;
    audio-visualizer draws a stream or a level as bars, a wave or an orb;
    workflow-graph lays out a pipeline in layers, each step stating its
    status; model-comparison compares models in a table that marks the best
    of each row in words.

  • Blocks: changelog, contact, careers, integrations, api-keys
    (each new key shown once, revoking confirmed), site-header (desktop menus
    and the mobile list from one list of links), and two heroes over the new
    backgrounds, hero-light-beams and hero-flow-field. Search finds them by
    everyday words — "release notes", "jobs", "mega menu", "api keys".

  • 3D: cube turns to show one face at a time — a carousel to assistive
    technology, by buttons, arrow keys or drag; image-ring stands images on a
    slowly turning ring you can drag; device-mockup draws a phone, tablet,
    laptop or browser around a screenshot or live UI, with an optional tilt.

  • WebGL: globe draws a dotted globe with places and the routes between
    them in raw WebGL, listing them for screen readers and falling back to SVG;
    model-viewer shows a glTF/GLB model people can turn, behind a poster.
    three is an optional peer used only by model-viewer, which is not in
    the main entry: import it from @dowel-ui/react/model-viewer.

  • Visual regression tests. packages/visual-tests screenshots every
    Storybook story and compares it with the same story on the base branch, in a
    new CI workflow. No baseline images are committed: the job builds Storybook
    for both commits and captures the baseline from the base build each time. A
    pull request that changes how a story looks fails unless it carries the
    visual-change label. See docs/testing/visual-regression.md. It runs
    alongside packages/browser-tests, which keeps committed baselines for a
    curated set of stories.

  • A live agent demo, at /agent-demo. A model operates a small deals page
    through the tools the page registers with agent-surface, and the visitor
    can take the page back by touching it, hand it back with a note, approve or
    decline the one action that cannot be undone, and undo the rest. The model
    runs through one narrow endpoint that is off until ANTHROPIC_API_KEY is
    set; without it the page plays a scripted run through the same surface. See
    RELEASING.md for the configuration and what bounds the cost.

Changed

  • Registry items can name dev dependencies. An item whose npm dependency
    ships no type declarations lists them in devDependencies, and dowel add
    installs them with -D, so the project still type-checks — the install
    check caught model-viewer failing without @types/three. The field is
    optional: older registries parse, and an older CLI ignores it (and leaves
    the types to be installed by hand). dowel doctor, the MCP server and the
    docs' manual install steps list them too.
  • The install check runs in CI. pnpm install-check installs every
    registry item into a new Next.js app with this checkout's CLI and builds it,
    on pull requests that touch the library and nightly against the newest
    Next.js.
  • Releases publish from a tag. Pushing vX.Y.Z runs a workflow that
    refuses to continue until the live registry serves that version, publishes
    to npm with trusted publishing, and opens the GitHub release from this
    file. See RELEASING.md.
  • audit:installed-imports fails when two items ship different files under
    one name, the cause of the carousel bug fixed in 0.12.0.
  • blast-radius says a single kind of change plainly: "2 emails will be
    created." where it said "2 emails will change: 2 created."

Fixed

Three things the demo showed within minutes of being used by hand, none of
which a unit test could see.

  • agent-surface: the click that takes control is no longer lost. Ticking
    a box or typing in a field while the agent held the page took control and
    threw the tick or the character away. Control changed in the event's capture
    phase, React rendered before the control's own onChange was worked out,
    and a controlled input was put back to its old value. The agent is still
    refused from the instant of the click, and the change now reaches React in
    the bubble phase, with the person's handler. jsdom cannot show this, so it
    is checked in a browser (agent-surface.browser.spec.ts, run by a job in the
    Browser workflow).

  • agent-surface, agent-approvals: a question is withdrawn when the
    person takes over.
    An approval stayed on screen after a take-over, though
    approving it could only be refused. The call now ends at once, told that the
    person holds the page, and agent-approvals moves on to the next request.
    The same happens when the caller aborts.

  • agent-replay no longer takes the page from the agent. Stepping through
    a replay inside a surface counted as taking over. Like the ledger, it is
    marked as the agent's own interface.

  • Props tables were missing props a component removes from its element with
    Omit and then declares itself (BorderBeam's color, for one): 120 across
    the library, now listed.

  • matrix-orb could run its springs backwards for one frame: the first
    frame's clock and the next frame's timestamp can disagree, and the negative
    step w...

Read more

0.13.1

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 07 Oct 09:25

Fixes for the accessibility problems the real-browser suite found in 0.13.0.
@dowel-ui/react and @dowel-ui/themes only; the CLI, the MCP server, the
registry builder and create-dowel-app are unchanged at 0.13.0. Components
installed as source get these through dowel update.

Fixed

  • Status and primary text on their own tints reach 4.5:1 in light mode.
    text-destructive on bg-destructive/10 (and the same for success, warning
    and info) measured 4.14–4.32:1, and primary text on the soft button's 12%
    tint 3.97–4.48:1 in ten of the thirteen presets. The status colours are
    darker in light mode (red-500 0.577→0.55, green-500 0.53→0.515,
    amber-500 0.55→0.535, blue-500 0.545→0.525), as is the light-mode primary
    of the default theme and of amber, blue, candy, emerald, green,
    indigo, ocean, orange and red (by 0.005–0.035, with hover and active
    moved by the same step). Dark mode is unchanged. Every such pair now measures
    4.52:1 or better in every preset.
  • The soft button stays readable while hovered and pressed. Its label now
    steps to primary-hover as the tint deepens, and the pressed tint is 20%
    rather than 24%; primary text on the old hover and pressed tints fell to
    3.3–4.4:1. The onboarding block's current-step marker uses a 12% tint, like
    the soft button, instead of 15%.
  • audit:contrast checks text on tints. It now measures each status colour
    on its own 10% tint and primary text on the soft button's tints, over both
    the page and the card, and composites translucent colours the way browsers
    paint them (on gamma-encoded channels). It previously blended in linear
    light, which reads a 10% tint as darker than it renders and would have
    passed these pairs by ~0.3:1. pnpm audit:contrast --verbose lists them.
  • The theme studio checks text on tints too. A colour derived there could
    pass every label check and still fail as text on its own tint, as the shipped
    presets did; the studio now lists primary on the soft button's tints, light
    and dark, alongside the solid states.
  • ai-suggest-mode: removed text is full-strength, marked by its strike-through
    and tint. Muted text on the darker destructive tint measured 4.4:1 — found by
    the browser suite after the palette change above.
  • Select inside FormControl had no accessible name. FormControl
    passes the field's id, description and invalid state to its child, and
    Select's root renders no element, so they were dropped and the label
    pointed at nothing. Select now passes them on to its trigger.
  • Conversation's transcript could not be scrolled by keyboard when the
    messages held nothing focusable. It is now a focusable, named region (label,
    default "Conversation"), as Table's scroll wrapper already is.
  • ai-loader: the elapsed-time counter is full-strength muted text instead of opacity-60 on muted text (2.4:1).
  • pull-to-refresh: the demo's balance decimals and idle time windows use text-muted-foreground instead of a faded foreground (2.2:1).
  • browser-tabs: the tab strip follows the tone, so an inverted window's inactive tab titles read at 4.5:1 or more instead of 2.1:1.
  • island: secondary text in the demo views is full-strength, not opacity-70, which was 3.34:1 on the primary tone.
  • code-block: the light-mode highlighted-line band is a 4% tint of the page, so syntax colours on it stay at 4.5:1 or more (text-info was 4.08:1).
  • log-viewer: the Fields toggle is a 24px-tall target instead of 16px; only rows that have one grow, by 2px.
  • image-accordion: a collapsed panel, which is its own trigger, is never narrower than 24px (it could be 16px).
  • reviews-carousel: each pagination dot is a 24 × 24 target instead of 16 × 24; the dot itself is unchanged.
  • command-center block: a resolved incident shows an outline severity badge and muted title instead of fading the row, which took the warning badge to 2.8:1.
  • onboarding block: a blocked step is no longer faded, so its warning badge has the solid fill instead of a lighter one (3.95:1).
  • selection-list: item descriptions were the foreground at 45% (2.9:1); they use text-muted-foreground (5.3:1 light, 7.4:1 dark), and full-strength text on the inverted fill.
  • slide-to-confirm: the track label, the control's only visible instruction, was text-foreground/45 (2.9:1); it is text-muted-foreground (5.3:1 light, 7.4:1 dark), and the power shimmer only ever brightens it.
  • confirm-typed: the action was faded to opacity-55 (2.2–2.5:1) until the text matched; it stays reachable but is now aria-disabled and drawn in the outline style, with a full-contrast label, until it takes its real variant on a match.
  • animated-checklist: the "Add new task" button was faded to opacity-34 (2.1:1) and done tasks to opacity-42 (2.7:1); both use text-muted-foreground (5.3:1), and a done task is shown by its tick and strike-through.
  • calendar: days outside the month, which are selectable, were muted at 50% opacity (2.0:1); they are plain text-muted-foreground (5.3:1). The root is now relative, so the month navigation sits on the calendar rather than at the edges of the page.
  • Stories: the agent-data-table selection column has a header name, the
    skeleton loading stories give their label a role to belong to, and the tabs
    stories render the panels their triggers point at.

0.13.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 06 Oct 15:52

The CLI and the MCP server now work after the install as well as during it,
and coding agents are told which component is right, not only which exist.

  • Security. The CLI no longer trusts its registry with the filesystem or
    its licence key: paths are confined, keys go only to the registry they were
    issued for, and registry dependencies must be npm packages.
  • The component genome. Every registry item carries its props, whether it
    needs a client boundary, whether it animates, and its quality checks; 188
    carry guidance on when to use them and what they are confused with.
  • dowel doctor, diff, audit and plan, and the MCP server's
    audit_code. plan --model asks Claude, with your own credentials.
  • Private registries with per-registry keys, and governance metadata
    (owner, since, deprecated).
  • In the repository: real-browser accessibility over every story, visual
    regression, a fresh-app install of every item in CI, and AgentBench, a
    harness for measuring whether agent support helps.

Added

  • AgentBench (packages/agentbench, private): a harness that runs the same
    prompt in two copies of a project — with Dowel's agent files and MCP server,
    and without — and scores both diffs with tsc, dowel audit, invented and
    uninstalled imports, recall of expected components, and the jsx-a11y rules.
    Ten tasks, a Claude Code adapter, and noop/reference adapters that cost
    nothing. No run has been published; /agentbench on the site documents the
    method and shows published runs only.
  • Private registries can require a key. A registry that answers 401 gets
    one retry with the key stored for it, and no other; a public registry never
    receives a key it did not ask for. Keys are stored per registry, so a Pro
    licence and a company key coexist. login --registry <url> verifies against
    the registry's index when it has no licence endpoint; logout --registry
    removes one key; whoami lists them. The MCP server reads DOWEL_TOKEN and
    DOWEL_TOKEN_REGISTRY for the same.
  • Governance metadata: an item can declare owner, since, and
    deprecated (version, reason, replacement). Deprecated items still install;
    add and update name the replacement, list and doctor mark them, the
    MCP server and agent docs warn off them, and the planners skip them. Custom
    registries can also declare guidance and composesWith, and the build
    rejects any of these naming an item that does not exist. Upstream guidance
    that names an item the extending registry cannot serve, such as a Pro block,
    is dropped from the inherited copy.
  • dowel plan "<screen>" chooses the blocks and components for a screen you
    describe. --model asks Claude to choose, with your own Anthropic
    credentials and the optional peer @anthropic-ai/sdk; whatever it names
    that the registry does not have is dropped and reported. Without --model
    it uses the built-in planner, which needs nothing.
  • MCP audit_code checks code an agent wrote against the same rules as
    dowel audit. get_component now says when to use a component, what it is
    confused with, whether it needs a client boundary, and every prop its type
    declares; search_components matches on what a component is for.
  • The agent files list each component's guidance under it, and the planners
    score it above a description match.
  • create-dowel-app writes the agent files when it scaffolds.
  • dowel doctor checks a project's setup and prints a checklist: the
    project shape, the import alias against tsconfig.json, the tokens in the
    stylesheet, installed files present, npm packages and component dependencies
    installed, a licence for any Pro item, updates available, and stale agent
    docs. It is a checklist, not a score, and it writes nothing.
  • dowel diff [names…] shows how installed files differ from the
    registry's current ones, as a unified diff.
  • dowel audit [paths…] finds Tailwind palette colours, literal colours in
    classes and inline styles, arbitrary sizes off the scale, physical direction
    utilities, and native elements where the Dowel component is installed. It
    skips the files Dowel wrote. --fix rewrites the physical utilities, the
    only findings with one exact fix, after asking. --json is for CI.
  • The component genome. Every registry item now carries capabilities
    (whether it needs a client boundary, whether it animates), props read from
    its type, and the quality checks from /quality. Items may also declare
    guidance (when to use it, when not, what it is confused with) and
    composesWith. All optional: older registries parse, and older CLIs ignore
    the new fields.
  • The registry now publishes the JSON Schemas its $schema fields pointed at:
    r/schema/registry-item.json and r/schema/registry-index.json.
  • The MCP server has contract tests for every tool, and a README.

Continuous integration

  • Every Storybook story is checked by axe in a real browser, light and dark,
    with the color-contrast and target-size rules the jsdom tests cannot
    run (packages/browser-tests, ADR 18). It found 140 violations across 82
    stories, recorded as 83 entries in known-violations.json, each with a
    reason — 70 of them "to fix". The suite fails on anything new and on any
    entry that no longer occurs, so the list can only shrink. The largest group
    is status text on its own 10% tint (4.1–4.5:1), a pair the palette audit
    never checked.
  • Visual regression for 42 curated stories — forms, open overlays, data,
    feedback, AI and five blocks — in light and dark, LTR and RTL, compared
    pixel-for-pixel inside the pinned Playwright container (188 images). It
    found the calendar's month navigation anchored to the wrong ancestor.
  • Storybook has a Direction toolbar global that sets dir and wraps the
    story in DirectionProvider, so RTL previews mirror the primitives too.
  • Coverage thresholds are enforced in CI (measured: 97.3% statements,
    93.4% branches, against floors of 85% and 80%).
  • Every free item is installed into a fresh app on every pull request
    (scripts/smoke/install-all.mjs): scaffold, init, add all of them,
    tsc --noEmit, next build — the release check that used to be manual.

Security

  • Registry file paths are confined to their directory. A path such as
    ui/../../.bashrc used to be written outside the project. The registry
    schema now refuses absolute paths, .., . and empty segments,
    backslashes, colons and NUL, and the CLI checks again where the path meets
    the disk.
  • remove only deletes what the CLI could have written. It used to delete
    any path components.json listed. It now refuses, deleting nothing, when an
    entry names a file outside the directories components are installed into.
    Alias directories outside the project, as in a monorepo, still work.
  • The licence key goes only to the registry it was issued for, over HTTPS.
    The registry an install reads comes from components.json, so a cloned
    repository could name its own server, mark an item as licensed, and collect
    the key. login now records which registry it verified the key against, and
    the CLI refuses to send the key anywhere else. Keys stored before this change
    belong to the default registry. DOWEL_TOKEN belongs to the default registry
    unless the new DOWEL_TOKEN_REGISTRY names another.
  • Registry dependencies must be npm package names, optionally with a
    version range. A git+https: URL, a tarball or a local path is refused
    instead of being handed to the package manager.
  • Item names are validated wherever they arrive from, including the
    command line, before they become a URL or a file path.

Fixed

  • remove theme --force deleted the project's whole stylesheet, because
    init records it under theme. The stylesheet is now never deleted.
  • update failed with ENOENT restoring a file whose directory had been
    deleted.
  • Registry and licence requests time out after 30 seconds instead of waiting
    indefinitely.
  • The MCP server's install_command said a Pro item was "not found"; it now
    resolves it from the index and says it needs a licence. Unknown names are
    all reported together, with suggestions, and a name like ../package is
    refused rather than read from outside the registry.
  • audit:rtl skipped a physical utility whenever a class such as bg-muted
    sat within a dozen characters before it. No component had such a bug hiding;
    the check is now exact.
  • The CLI and scaffolder state Node 20.12 as their floor, which their prompts
    library requires, and CI runs the built binaries on Node 20 and 22.

0.12.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 05 Oct 13:36

Twenty-four animated components from Animate UI's patterns, 244 in all (up
from 220). Also fixes sheet and drawer dimming their own panel, and
swipe-carousel breaking the other carousels when installed after them.

Added

Twenty-four animated components whose patterns come from Animate UI. All are
original implementations: Animate UI's licence (MIT with the Commons Clause)
does not allow redistribution, so none of its code was used. See
THIRD_PARTY_NOTICES.md. Animate UI items Dowel already covered, such as tabs,
tooltip, accordion and the copy, icon and theme-toggler buttons, were not
added again. All 24 are beta, and all of them stop or settle under reduced
motion.

  • Overlays: alert-dialog (springs up out of a blur, and the destructive
    tone shakes its icon once), hover-card (grows from its trigger with an
    overshoot, and can stagger its contents) and preview-link-card (a link
    whose preview image wipes in from a shimmer; nothing is fetched).
  • Form controls: toggle (squishes when pressed, and its fill pours out
    from the centre), toggle-group (a sliding highlight in single mode,
    per-item springs in multiple mode), flip-button, ripple-button,
    liquid-button (rolling liquid fill with an inverting label) and
    share-button (opens into a staggered row of targets, including copy-link
    and the native share sheet).
  • Data and navigation: file-tree (the full ARIA tree pattern, with
    folders that tilt open, a drawn guide rail and a gliding selection),
    code-tabs (syncKey switches every instance on the page together and
    remembers the choice), pin-list, management-bar (a floating bulk-actions
    toolbar with rolling counts) and radial-nav.
  • Display and feedback: flip-card (leans toward the pointer, lifts as it
    turns, and a sheen sweeps across), radial-intro (avatars spiral out into
    an orbiting ring) and notification-list (a receding deck that springs open
    into a list, with swipe-to-dismiss and an always-available dismiss button).
  • Backgrounds: stars-background, gravity-stars-background,
    fireworks-background and hole-background draw through the
    dither-canvas engine, so they inherit its DPR cap, pause when off-screen
    or in a hidden tab, and take their colours from the theme.
    bubble-background, gradient-background (linear, aurora and mesh) and
    hexagon-background are CSS-first.

Changed

  • Generate and the MCP server find the new components from the words
    people use for them — "file explorer", "link preview", "are you sure",
    "bulk actions", "fireworks", "honeycomb" and others now reach them.
  • The components page features fireworks-background, file-tree and
    flip-card.
  • button, badge, label, avatar, input, separator and
    data-table
    now mark their root with data-slot, like every other
    component. They were the exceptions, so tooling that finds a component's
    parts in rendered markup — the docs site's "Parts" view on block pages —
    could not see them. A data-slot passed by the caller still wins, so
    wrappers such as copy-button keep their own.

Fixed

  • Installing swipe-carousel no longer breaks reviews-carousel and
    invite-carousel.
    All three ship a carousel-controls.tsx, but
    swipe-carousel's was a shorter copy without the rotation control. Files
    install flat, so adding swipe-carousel after either of the others replaced
    the file they import from, and the project stopped type-checking. All three
    now ship the same file, and a registry test fails if two items ever ship
    different files to the same path. If it happened to you, run
    dowel update swipe-carousel.
  • sheet and drawer no longer dim themselves. Each put its overlay on
    --z-overlay (300) and its panel on --z-drawer (200), so the overlay
    painted over the open panel — and over sidebar's mobile panel, which is a
    sheet. The overlay now shares the panel's drawer layer and comes first in
    the portal, so the panel sits above it; a dialog opened from inside a panel
    still dims it from the layer above. If you installed either, run
    dowel update sheet drawer, or change z-[var(--z-overlay)] to
    z-[var(--z-drawer)] on the overlay yourself.

0.11.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 26 Sep 17:39

Seven components from the "later" list in docs/plans/agent-operable-ui.md,
WebMCP's exposedTo, and fixes that make every registry item install and
build. The plan is docs/plans/next-components.md. All seven are beta.

Added

  • provenance-text shows who wrote each part of a paragraph: the person,
    an agent or a quoted source, with each author's share. Provenance is hidden
    until someone turns it on; when shown, agent and source text differ by
    underline shape as well as colour, and screen readers hear who wrote each
    marked part. provenanceFromEdit keeps attribution current word by word.
  • nl-filter: type what you want to see ("failed on main took over 5"),
    press Enter, and get filter chips you can edit or remove. A plain parser
    ships for field:value, field>3, quoted values and option names; pass
    your own, such as a model call, and a newer submission aborts the older
    one. Text it cannot read stays in the field as "Not understood: …".
  • memory-inspector shows what an assistant remembers about the person,
    where each memory came from and when it was last used, with search, edit
    in place, pin and forget. A forgotten memory disappears at once, and
    onForget is only called when the undo window closes.
  • expression-editor, a formula field with highlighting, autocomplete
    for variables and functions, the error shown where it is, and a live
    result. It parses and evaluates the expression itself, from an allowlist,
    without eval.
  • quantity-input, a number with a unit (kg/lb, GB/TB, s/min, °C/°F).
    Changing the unit converts the amount, min and max are quantities so they
    hold in any unit, "5 lb" typed or pasted sets both parts, and numbers are
    read and written the locale's way.
  • permission-prompt asks for a capability when it is needed ("Claude
    wants to read your calendar"): why, what it allows and doesn't, and the
    risk in words, with allow once, for this session, always, or not at all.
    usePermissionPrompt gives an app or agent tool a promise to await, and
    remembers session and stored grants.
  • chart-sonifier lets you hear a chart. Each series plays as pitch over
    time, and a keyboard slider steps through the points, playing each note and
    reading the value, beside a one-sentence summary of the series. Nothing
    plays until someone asks, and Pause, Escape and Mute stop it at once.
  • agent-surface: exposedTo and debugging, from the WebMCP draft of
    2026-09-26. exposedTo lists origins, beyond the page's own, that may see
    the tools within the page's frames, on the surface or per tool. The browser
    refuses a whole tool over one bad origin, so the page drops those first
    and says which in development.

Fixed

  • expression-editor builds in apps that target ES2017, as a new Next.js
    app does. It used the regular expression flag s, which TypeScript refuses
    below ES2018. packages/ui now also type-checks at ES2017. Found by
    installing every registry item into a fresh app, which all 220 components
    and 47 blocks now pass.

  • Components installed with the CLI now build. In this repo
    @/components/x resolves to a folder's index.ts, but an installed project
    has no index: the CLI rewrites the import to @/components/ui/x, the main
    file. 22 main files exported less than their index, so a project that
    installed one of them failed to build:

    • Every dither chart and uptime-matrix imported createSprings,
      ditherFill and more from dither-canvas, which dither-canvas.tsx did
      not export.
    • agent-form and agent-approvals imported the JsonSchema type from
      agent-surface.
    • toast(), parseCron, FloatingLabelInput, findSensitive and other
      documented exports could not be imported from their component's file.

    Each main file now re-exports what its index does, and the new
    audit:installed-imports fails CI when one doesn't. Found by installing
    0.10.0 into a fresh Next.js app.

  • stream-announcer: NVDA with Chrome no longer re-reads the previous two
    sentences with every announcement after the third. The live region used to
    drop its oldest sentence while adding the newest, and Chrome then reported
    every sentence in it as new. It now fills up to three and then starts over.
    Found by the first real NVDA run.

0.10.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 26 Sep 17:29

Agent-operable UI: agents can operate your UI and hand it back

Eleven components that let an agent work on the page itself, and let the
person oversee it and take the page back. The plan is in
docs/plans/agent-operable-ui.md and the decisions are in ADR 0015.

Control

  • agent-surface (experimental) is a region whose actions are registered
    as tools with useAgentTool. Each tool runs the same handler a person's
    click runs, and its input is validated in the page. Your own assistant calls
    tools through apiRef; with webmcp, browser agents can call them too,
    through document.modelContext (Chrome and Edge origin trials). Control is
    state: shared, agent or person.
    • While the person holds control, every call is refused, reads included.
    • Irreversible actions need approval; without it they are refused.
    • Operating a control while the agent drives takes over, except inside
      [data-agent-ui].
    • Other libraries already expose component actions over WebMCP. This one is
      built around who has control.
  • control-baton (experimental) shows who has control and lets the person
    take over, then hand back with a note. The note is added to the start of the
    agent's next tool result. It works inside a surface, or on its own with
    holder. We don't know of another component library that ships a reusable
    take-over / hand-back control; the pattern comes from agent products such as
    ChatGPT agent and Browserbase's live view.

Oversight

  • agent-approvals (experimental) is the approval step, built on
    ai-approval-request. The person can correct the agent's arguments before
    approving, approve once or for the session, or deny with a reason the agent
    is told. Mounting it inside a surface is all the wiring there is, and
    requests still waiting when it unmounts are refused.

  • agent-ledger (experimental) lists what the agent did, built on
    ai-action-ledger. It can undo a call whose tool registered an undo with the
    new onUndo, and the agent is told what the person took back.

  • blast-radius (beta) shows what an action will change before it runs:
    how many things, how, which can't be undone, and a sample by name. For
    example: "43 deals will change: at least 3 deleted. At least 2 cannot be
    undone." A tool's new preview dry run fills it in inside agent-approvals
    while the person decides.

  • agent-replay (experimental) steps through a finished run, by button,
    slider or playback. It shows each call, exactly what the agent was told,
    and every take-over and hand-back.

  • ai-suggest-mode (beta) is track changes for an agent's edits to text.
    Each change is shown in place with its reason and accepted or rejected on
    its own. It works from edits or from a whole rewrite. The agent is told what
    was rejected, so it doesn't suggest it again.

Privacy

  • prompt-redactor (beta) checks a prompt before it's sent. Email
    addresses, card numbers, IBANs, API keys and phone numbers are named, masked,
    and sent as placeholders such as [EMAIL_1]. They're put back locally in
    the reply. Card numbers and IBANs are only matched when their checksums
    pass, and you can add your own detectors.

Tools for existing components

  • agent-form (experimental) gives fill, read and submit tools to any
    form. Fields, labels, options and errors are read from the form itself.
    Values are set through the events typing fires, and submitting goes through
    the form's own handler. Passwords, one-time codes and card numbers are never
    read or filled. Submitting waits for approval unless you say it can be
    undone. With declarative, the form also describes itself to browser agents
    through WebMCP's form attributes, and their submits pass the same checks.
  • agent-data-table (experimental) provides useDataTableAgentTools,
    which gives a TanStack table read, sort, search, filter, select and page
    tools, each only when the table has that feature. They call the same API as
    the table's own controls.

Accessibility

  • stream-announcer (beta) is an opt-in way for a screen reader user to
    hear a streaming response as it arrives. It reads whole sentences only,
    pacing them so pause, skip and repeat can still act on the queue. Markdown is
    read as prose, and a code block is summarised as its language and line count.
    ai-conversation's state-only announcements stay the default.
  • Screen reader tests. packages/screen-reader-tests drives real
    VoiceOver and NVDA through Guidepup, in a new CI workflow. A harness project
    checks the scenarios themselves without a screen reader, and JAWS has a
    manual protocol in docs/testing/screen-readers.md. stream-announcer stays
    beta until those runs pass.

Changes to existing components

  • agent-surface also gains preview, told, a controlLog of changes of
    control, and api.notify, which tells the agent something with its next
    result.
  • ai-approval-request and ai-prompt-input now carry data-agent-ui, so
    approving a call or typing to the agent inside a surface never counts as
    taking over.
  • ai-action-ledger no longer keeps a reverted action in its selection, where
    it was still counted by "Undo 2 selected".

Known issue, fixed in the registry

Until 2026-09-27, some components added with the CLI did not build in the project they were added to: every dither chart, uptime-matrix, agent-form and agent-approvals, among others. Each imported something its sibling's main file did not export. The registry the CLI reads is fixed, so re-run npx @dowel-ui/cli add <name> --overwrite for anything added before then. 0.11.0 adds a check so it cannot happen again.

0.7.0

Choose a tag to compare

@aqkprogrammer aqkprogrammer released this 05 Sep 17:49

The release that puts something up for sale, and fixes the bug that finding out how to sell it uncovered.

Nothing that was free has stopped being free. The registry build now names every block that shipped without a licence and fails the release if any of them changes access.

The Pro catalogue

Four new blocks, all access: "pro". Whole application surfaces rather than page sections:

  • crm — a pipeline with its deals. Sales cycle is declared lower-is-better, so a slowing pipeline is not painted green.
  • command-center — service health worst-first, incidents by severity, capacity meters, a filterable log stream and a ⌘K palette. The overall status is one sentence, and deliberately not a live region.
  • ai-workspace — conversations, transcript, and the model's context beside it: window usage, attachments, a structured result filling in.
  • admin-dashboard — the shell an admin area shares, with children for your own pages, and an overview that puts what needs attention first.

Withheld means the index lists them in full and only the gated route serves their bodies. The docs render their previews from the same stories the tests run; packages/ui no longer ships src/blocks in its tarball.

Sidebar fix

The mobile sheet was mounted whenever the rail was open and hidden with CSS. A modal dialog that CSS hides is still modal: on every desktop, whenever the sidebar was open, the rest of the page was aria-hidden and pointer-events was off on the body. It now mounts only below the breakpoint, with its own open state.

The site

Pricing, a private-registry guide, and a front page that counts itself — components, blocks, average quality from the audits, npm and GitHub figures fetched hourly, and a version badge that no longer claims 0.1.0.

Design tokens for Figma

@dowel-ui/themes reads the same CSS the components use and writes W3C design tokens. One file per preset at /figma/<preset>.tokens.json, and the Theme Studio downloads the same for a preset built there.

Full notes in CHANGELOG.md.