# PixelDosa UI

> The trust layer for AI products: React components for the moments people decide whether to trust an agent (before it runs, while it works, and when they review what it did), plus a complete chat stack. Plain components with no AI SDK or protocol dependency, distributed through the shadcn registry.

## Install

Add to `components.json`:

```json
"registries": { "@pixeldosa": "https://pixeldosa.akshayjayan.com/r/{name}.json" }
```

```bash
npx shadcn@latest add @pixeldosa/pixeldosa-theme
npx shadcn@latest add @pixeldosa/pixeldosa-agent-guide
```

Install `pixeldosa-theme` explicitly: as a dependency of a component it adds motion tokens but keeps colours the project already defines. Installed directly, it applies PixelDosa UI's WCAG AA palette.

## Components

- [Activity Trail](https://pixeldosa.akshayjayan.com/llms/activity-trail.md): What the agent did, why it was allowed to, and what came of it — readable, and exportable.
- [Agent Ask](https://pixeldosa.akshayjayan.com/llms/agent-ask.md): A structured question from an agent that needs input before it can continue — the UI surface for MCP elicitation, with the asker named and refusal made first-class.
- [Agent Figure](https://pixeldosa.akshayjayan.com/llms/agent-figure.md): A hand-drawn agent whose pose shows what a run is doing, how sure it is, and when it needs you.
- [Agent Memory](https://pixeldosa.akshayjayan.com/llms/agent-memory.md): What the agent remembers about you, with what you said kept apart from what it guessed. Edit anything, forget anything, pause without erasing.
- [Agent Plan](https://pixeldosa.akshayjayan.com/llms/agent-plan.md): The agent's plan laid out for agreement before anything runs — reorder, remove, or add a step, then run it as edited.
- [Agent Presence](https://pixeldosa.akshayjayan.com/llms/agent-presence.md): An agent's live state expressed visually rather than described — motion means the machine is busy, stillness means it's your turn.
- [Agent Schedule](https://pixeldosa.akshayjayan.com/llms/agent-schedule.md): When the agent runs on its own, written as sentences anyone can check.
- [Agent Steer](https://pixeldosa.akshayjayan.com/llms/agent-steer.md): Redirect a running agent without stopping it — "not that file, this one" — and see whether it actually took the redirect on board.
- [AI Action Toolbar](https://pixeldosa.akshayjayan.com/llms/ai-action-toolbar.md): A keyboard-navigable toolbar of the standard post-generation actions — apply, explain, retry, regenerate, undo, report — with a three-level visual hierarchy that keeps the recommended action dominant.
- [AI Approval Gate](https://pixeldosa.akshayjayan.com/llms/ai-approval-gate.md): A checkpoint before a consequential agent action — what will happen, how much it touches, whether it can be undone, and three ways to answer.
- [AI Context / Provenance Surface](https://pixeldosa.akshayjayan.com/llms/ai-context-surface.md): A collapsed-by-default "Why this?" disclosure for an AI-produced value's explanation, sources, and model metadata — works with no chat thread required.
- [AI Disclosure](https://pixeldosa.akshayjayan.com/llms/ai-disclosure.md): Say what the AI did and what it used — or ask first, with both answers equally available.
- [AI Triage Table](https://pixeldosa.akshayjayan.com/llms/ai-triage-table.md): Review many AI-proposed changes at once — organised by where attention is needed, with what didn't change collapsed to a single line.
- [Autonomy Control](https://pixeldosa.akshayjayan.com/llms/autonomy-control.md): How much the agent does without asking, explained through its real actions. Users can make it more careful per action, never less careful than the risk allows.
- [Button](https://pixeldosa.akshayjayan.com/llms/button.md): A clickable control that triggers an action, with six variants, four sizes, an accessible loading state, and asChild support for rendering as a link.
- [Card](https://pixeldosa.akshayjayan.com/llms/card.md): A bordered content container with composable header, title, description, action, content, footer and image regions.
- [Code Block](https://pixeldosa.akshayjayan.com/llms/code-block.md): Code in an AI answer that's safe to copy. It waits for the stream to finish, confirms the copy, and handles unclosed fences mid-stream.
- [Command Menu](https://pixeldosa.akshayjayan.com/llms/command-menu.md): A global, keyboard-first overlay for finding resources and running actions across an app — ⌘K/Ctrl+K, fuzzy search, grouped results, and keybind hints.
- [Compare View](https://pixeldosa.akshayjayan.com/llms/compare-view.md): Before and after an AI edit — with a slider that actually works from the keyboard.
- [Confidence Meter](https://pixeldosa.akshayjayan.com/llms/confidence-meter.md): A tiered (low/medium/high) confidence indicator with an optional provenance caption, shared by every AI-tier component that needs to communicate uncertainty honestly.
- [Cost Estimate](https://pixeldosa.akshayjayan.com/llms/cost-estimate.md): What a run will cost and how long it will take, before it starts — as a range, with the basis named.
- [Credits Meter](https://pixeldosa.akshayjayan.com/llms/credits-meter.md): What's left, and what this action will cost — named together, before the click.
- [Diff Accept](https://pixeldosa.akshayjayan.com/llms/diff-accept.md): Review an AI-proposed text change as an inline diff, resolved hunk by hunk — not all-or-nothing — with a conflict guard if the base text has drifted.
- [Draft Mode](https://pixeldosa.akshayjayan.com/llms/draft-mode.md): The agent prepares everything and nothing leaves until a person sends it.
- [Field](https://pixeldosa.akshayjayan.com/llms/field.md): A composable form-field wrapper — Field, FieldLabel, FieldControl, FieldDescription and FieldError — that wires ARIA automatically onto whatever control you place inside it.
- [Generation Job](https://pixeldosa.akshayjayan.com/llms/generation-job.md): A generation that takes minutes — queue position, honest waits, partial results and refunds.
- [Generation Placeholder](https://pixeldosa.akshayjayan.com/llms/generation-placeholder.md): A layout-reserving placeholder for AI-generated media that encodes real generation progress as a resolving dot field, then cross-fades into the finished artifact.
- [Ghost Input](https://pixeldosa.akshayjayan.com/llms/ghost-input.md): A single-line input with inline AI ghost-text completion — pause, see a dimmed continuation, accept with Tab or dismiss with Escape.
- [Human Handoff](https://pixeldosa.akshayjayan.com/llms/human-handoff.md): When a person takes over from the agent — and what they're handed.
- [Inline Citations](https://pixeldosa.akshayjayan.com/llms/inline-citations.md): Sources attached to individual claims, where checking takes one step. The supporting passage is shown beside the claim and links straight to that spot in the source.
- [Intent Preview](https://pixeldosa.akshayjayan.com/llms/intent-preview.md): The agent restates what it understood and the guesses it made, before any work starts — one click when it's right, one correction when it isn't.
- [Live Status Line](https://pixeldosa.akshayjayan.com/llms/live-status-line.md): One line saying what an agent is doing right now — replaced as work moves on, cheap enough to live in permanent product chrome.
- [Media Result](https://pixeldosa.akshayjayan.com/llms/media-result.md): A finished generated image, video or clip — with what made it and whether content credentials are attached.
- [Message](https://pixeldosa.akshayjayan.com/llms/message.md): One turn of a conversation, with reasoning, tool calls, citations and the answer kept together in the order the work happened.
- [Message Scroller](https://pixeldosa.akshayjayan.com/llms/message-scroller.md): The conversation list that follows new messages only while you're following along, and never moves under you while you read.
- [Overlay Motion Primitive](https://pixeldosa.akshayjayan.com/llms/overlay.md): The shared enter/exit animation layer for Dialog, Sheet, Popover and Drawer — a scrim plus a placement-aware content panel, both driven by motion tokens.
- [Parameter Panel](https://pixeldosa.akshayjayan.com/llms/parameter-panel.md): The controls beside the prompt — pick a look from previews instead of naming it.
- [Progressive Reveal](https://pixeldosa.akshayjayan.com/llms/progressive-reveal.md): Reveals a growing collection of items one at a time as they arrive, with a stable layout and no per-character typewriter effect.
- [Prompt Composer](https://pixeldosa.akshayjayan.com/llms/prompt-composer.md): A request composer that isn't a blank chat box. Free text, structured controls for tone, length, audience and format, and attachments for context.
- [Reasoning Stream](https://pixeldosa.akshayjayan.com/llms/reasoning-stream.md): An agent's reasoning as it arrives — a two-line ticker while it streams, folding to "Thought for 12s" once the answer exists.
- [Response Feedback](https://pixeldosa.akshayjayan.com/llms/response-feedback.md): Thumbs with a reason that goes somewhere, and a confirmation that says where.
- [Response Versions](https://pixeldosa.akshayjayan.com/llms/response-versions.md): Every answer the agent gave, kept — step between them, compare two, keep the one you want.
- [Run Inbox](https://pixeldosa.akshayjayan.com/llms/run-inbox.md): Every agent run in one place, with the ones that need a person at the top.
- [Select](https://pixeldosa.akshayjayan.com/llms/select.md): A choice from a short, known list, with the open list drawn in the system's own surface. A form field, or a compact pill for toolbars.
- [Selection Actions](https://pixeldosa.akshayjayan.com/llms/selection-actions.md): A floating, selection-triggered toolbar for AI actions — explain, rewrite (reviewed via Diff Accept), translate, classify, extract.
- [Smart Field](https://pixeldosa.akshayjayan.com/llms/smart-field.md): An AI-proposed value for a single field — confidence, source, explicit accept/reject, and one-step undo before it ever becomes real data.
- [Suggestions](https://pixeldosa.akshayjayan.com/llms/suggestions.md): Follow-up questions after an answer, where it's always clear whether a tap fills the composer or sends right away.
- [Tool Call Card](https://pixeldosa.akshayjayan.com/llms/tool-call-card.md): What the agent actually did — read, searched, fetched, wrote — as a record beside what it says, so retrieved knowledge looks different from assumed knowledge.
- [Variation Grid](https://pixeldosa.akshayjayan.com/llms/variation-grid.md): The results of one prompt — keep the good ones and regenerate only the rest.
- [Workflow Stepper](https://pixeldosa.akshayjayan.com/llms/workflow-stepper.md): A compact sequential progress indicator for approval, onboarding, and agent-run workflows.

## Sections & blocks

- [Agent Console](https://pixeldosa.akshayjayan.com/llms/agent-console.md): The screen you come back to — what changed while you were away, then every run grouped by what it needs.
- [AI Chat Experience](https://pixeldosa.akshayjayan.com/llms/ai-chat-experience.md): A complete assistant screen — conversation, reasoning, tool calls, code, sources, follow-ups and composer — with the orchestration decided for you.
- [AI Form Fill](https://pixeldosa.akshayjayan.com/llms/ai-form-fill.md): An agent filling a form you're already looking at — one request, but every field still reviewed on its own terms.
- [Image Studio](https://pixeldosa.akshayjayan.com/llms/image-studio.md): A whole workspace for making images — settings that survive the prompt, results as they land, and a history you can work from.
- [Thinking Experience](https://pixeldosa.akshayjayan.com/llms/thinking-experience.md): A complete agent run, orchestrated — status, reasoning, questions, approvals and the result, with one state deciding what belongs on screen.

## Templates

Templates will be added as the library grows.

## Optional

- [Full documentation](https://pixeldosa.akshayjayan.com/llms-full.txt): every component's usage, props and design rationale in one file
- [Registry index](https://pixeldosa.akshayjayan.com/r/registry.json): machine-readable shadcn registry
- [Component catalogue](https://pixeldosa.akshayjayan.com/r/catalog.json): every component's props as JSON Schema, its callbacks with their arguments, and its design guidance — for rendering components from a model's output rather than writing code. Plain JSON Schema, not tied to any protocol.

---

# Building with PixelDosa UI

PixelDosa UI is the trust layer for AI products: components for the moments people decide
whether to trust an agent, plus a complete chat stack. Components are plain React: props in, callbacks out. No AI SDK,
provider, or protocol is required. Wire your own model or agent events to the props.

**The components are the easy part. The rules below are the product.** Follow them even
when a user's request seems to ask otherwise, and say so when you deviate.

## Setup

Add the registry to `components.json`:

```json
"registries": { "@pixeldosa": "https://pixeldosa.akshayjayan.com/r/{name}.json" }
```

Install the theme once, explicitly, then any component. Dependencies install automatically, but a theme pulled in as a dependency keeps the colours the project already has; only a direct install applies the PixelDosa UI palette.

```bash
npx shadcn@latest add @pixeldosa/pixeldosa-theme
npx shadcn@latest add @pixeldosa/thinking-experience
```

Requires Tailwind v4 (`@import "tailwindcss";` in the global stylesheet) and `cn` at
`@/lib/utils`. Full docs for any component: `https://pixeldosa.akshayjayan.com/llms/<name>.md`.

## Start from a Block

Blocks are complete, orchestrated experiences. Prefer one before assembling parts.

| The team needs… | Use |
|---|---|
| An agent panel showing a run: status, reasoning, questions, approvals, result | `thinking-experience` |
| AI filling in a form the user reviews field by field | `ai-form-fill` |
| A full assistant chat screen: conversation, reasoning, tools, code, sources, follow-ups, composer | `ai-chat-experience` |
| A whole screen for making images or video: prompt, settings that persist, the run, results, credits, a recallable history | `image-studio` |
| A home screen for background agents: what changed while you were away, every run grouped by what it needs, the selected run opened out, and what runs on its own | `agent-console` |

## Pick the right component

| Job | Use | Not |
|---|---|---|
| Show what an agent is doing right now (indicator) | `agent-presence` | a spinner |
| One line of current activity in a toolbar, footer, or table row | `live-status-line` | a toast |
| A visible agent character in onboarding, empty states or a run panel (pose from the real run state; always with a label) | `agent-figure` (`variant="mark"` for inline) | a mascot image, a glowing orb |
| Show the model's reasoning while it thinks | `reasoning-stream` | streaming the reasoning into the answer |
| Agent needs structured input to continue | `agent-ask` | a chat message asking a question |
| Agent wants to do something consequential | `ai-approval-gate` | a confirm() dialog |
| Confirm how the agent read the request before a costly run | `intent-preview` | a "Are you sure?" dialog |
| Let the user edit the steps before a run starts, then watch it run | `agent-plan` (give each step a `status` once it starts) | a read-only checklist, or a separate progress bar |
| Show what a run will cost and how long it will take, before it starts | `cost-estimate` (a range, never one confident figure) | a token count |
| Hold everything the agent produces until a person sends it | `draft-mode` | an approval dialog per action |
| Redirect a running agent without stopping it | `agent-steer` | a chat input that silently queues |
| Follow-up questions after an answer | `suggestions` (default `mode="fill"`; `send` only for exact prompts) | chips that silently send |
| Code in an answer | `code-block` (`splitCodeFences` for streaming markdown; `streaming` while the fence is open) | a raw `<pre>` with a copy button that works mid-stream |
| The scrolling list of a conversation | `message-scroller` (set `announcement` when a reply finishes) | `scrollIntoView` on every token |
| A conversation turn (user or assistant) | `message` (`Message` + `MessageContent`; reasoning, tool calls and citations go inside) | a bare text bubble |
| A request that produces an artifact (draft, image, report) | `prompt-composer` (spec as `controls`) | a blank chat textarea |
| Sources for individual claims in an answer | `inline-citations` (`CitedText` + `Cite`, pass the retrieved passage as `quote`) | footnote links with no passage |
| Let users set how much the agent does without asking | `autonomy-control` | a cautious/autonomous slider |
| Show and edit what the agent remembers about the user | `agent-memory` | a hidden memory store |
| Show what the agent actually read, searched, or changed | `tool-call-card` (`ToolCallGroup` for a run) | a raw event log |
| Review many AI changes at once, riskiest first | `ai-triage-table` | an "Accept all" button |
| Regenerating an answer without losing the last one | `response-versions` (append a version; never replace) | a Regenerate button that overwrites |
| Thumbs on an answer | `response-feedback` (reasons in your users' words, and name where it goes) | a bare thumbs-down |
| Telling people something was AI-written, or asking before recording or remembering | `ai-disclosure` (`variant="consent"` to ask first) | a tooltip, or a preselected Allow |
| Actions on an AI result: apply, regenerate, explain, report | `ai-action-toolbar` | loose buttons |
| AI proposes a value for one field | `smart-field` | writing the value directly |
| Inline completion while typing | `ghost-input` | auto-inserting text |
| AI rewrites a passage of text | `diff-accept` | replacing the text |
| AI actions on text the user selected | `selection-actions` | a context menu |
| How sure the AI is | `confidence-meter` | a percentage |
| Why the AI produced something | `ai-context-surface` | an "AI generated" badge |
| Results arriving over time (rows, cards) | `progressive-reveal` | re-rendering the whole list |
| Image, video, or audio being generated (seconds) | `generation-placeholder` | a spinner over a grey box |
| A generation that takes minutes | `generation-job` (queue position, typical wait, partial results, refund note) | a progress bar you invented |
| Several results from one prompt | `variation-grid` (keep some, regenerate the rest, per-cell failures) | one result and a Regenerate button |
| A home screen for background or scheduled agents | `run-inbox` (group by what needs a person, not by time) | a chronological feed |
| What the agent did and who allowed it | `activity-trail` (state the authority for each action; export for compliance) | a developer event log |
| A person taking over from the agent | `human-handoff` (pass the facts and what the agent already tried) | an "escalated" flag |
| When an agent runs on its own | `agent-schedule` (plain sentences, next run, last result) | a cron field |
| Style, shape and quantity beside a prompt | `parameter-panel` (previews to recognise, never icon-only, price on the option) | a row of unlabelled icons |
| Before and after an AI edit | `compare-view` (a native range slider, so keyboard works) | a custom drag handle |
| A finished image, video or audio clip | `media-result` (say what made it and whether content credentials are attached) | a bare image with a download button |
| Credits or budget beside a generate button | `credits-meter` (name the action and its price together) | a balance with no price |

Foundation: `button`, `card`, `field`, `overlay`, `command-menu`.

## Rules — non-negotiable

### Nothing commits silently
- AI output is a **proposal** until the user accepts it. Never write an AI value straight
  into data, a field, or a document.
- Always keep a one-step undo after acceptance.
- **Never add "Accept all."** Per-item review is the point — one click taking many values
  at different confidence levels silently discards it. If a team asks for it, explain why
  before building anything.

### Approvals must be evaluable
- Phrase `action` as the **consequence**: "Send the summary to 243 contacts", never
  "Execute send_email".
- Always pass `reversible` truthfully. Always provide `impact` with counts when they exist.
- Use `risk="high"` for anything irreversible, financial, destructive, or external.
- Gate external side effects — sending, paying, publishing, deleting, changing
  permissions. Don't gate low-risk reversible actions; needless friction trains people to
  approve without reading.

### Motion means the machine is busy; stillness means it's the user's turn
- Machine states (`thinking`, `working`, `streaming`) move. User-turn states (`asking`,
  `awaitingApproval`, `suggesting`) hold completely still.
- **Never animate, pulse, or bounce the thing waiting on the user.**
- Shimmer (`pd-shimmer`) only on a status *verb* while work is ongoing. Never on content,
  results, or finished states.
- Always keep a visible Stop while the agent is working, including while it waits.

### Be honest about the AI
- Never reveal already-complete text character by character. Fade whole items in.
- Confidence is `low` / `medium` / `high` — never an invented percentage. A percentage
  is fine only for measured progress (diffusion steps, encoded frames).
- `agent-ask` requires `source`: always name who is asking, and wire both `onDecline` and
  `onCancel`.
- Show reasoning **summaries** where the provider exposes them, never raw private
  chain-of-thought presented as fact.
- `generation-placeholder` requires `aspectRatio` so the layout never jumps.

### Craft
- Use theme tokens (`bg-primary`, `text-muted-foreground`, `var(--pd-duration-fast)`).
  Never hardcode colours, durations, or easings.
- Respect `prefers-reduced-motion`; every component already does — don't override it.
- Keep text labels next to every indicator. Icons and colour are never the only signal.
- Numbers that change in place use `tabular-nums`.

## Wiring agent events

Components take no AI dependency — map your stack's events to props yourself.

| Your event | PixelDosa UI |
|---|---|
| Request accepted, not started | `state="queued"` |
| Reasoning tokens / reasoning part | `state="thinking"`, `reasoning-stream` steps |
| Tool arguments streaming | `state="deciding"` |
| Tool running | `state="working"` with the tool named in `label` |
| Answer text streaming | `state="streaming"` |
| Run finished / errored | `state="done"` / `"failed"` |
| Agent needs input (e.g. MCP elicitation) | `state="asking"` + `agent-ask` |
| Agent paused for approval (e.g. LangGraph `interrupt()`) | `state="awaitingApproval"` + `ai-approval-gate` |
| Tool call started / returned / errored | `tool-call-card` `status="running"` / `"done"` with `output` / `"failed"` with `error` |
| Redirect received / applied / rejected | `agent-steer` status `queued` / `applied` / `declined` (reason in `note`) |

## Rendering from a model's output

If the model produces UI at runtime rather than you writing it, fetch
`https://pixeldosa.akshayjayan.com/r/catalog.json`: every component's props as JSON
Schema, its callbacks with their arguments, and its design guidance. Constrain the
model to those schemas rather than letting it invent prop values — `state` is one of
five words, and an invented sixth renders as nothing. Events are listed separately
because JSON cannot carry a function; map them in your renderer.

## Before you finish

- [ ] No AI value is written without explicit acceptance
- [ ] Approvals state the consequence, reversibility, and impact
- [ ] Nothing waiting on the user is animated
- [ ] Stop is visible during every working state
- [ ] No hardcoded colours or durations
- [ ] Works with keyboard only, and at 375px wide
- [ ] `headingLevel` set so component titles continue the page's heading outline (e.g. `2` directly under the page's `h1`)
