Skip to main content
@smthrs/ui is the shared component library for every Smithers UI surface: custom workflow UIs under .smithers/ui/, the Monitor, Studio, and any app embedding a Gateway page. For a map of every kind of UI documentation (chat components, agentic components, adapters, run-aware widgets, hooks, and authoring guides), start at UI Docs by Type. It ships shadcn component anatomy (data-slot attributes, CVA variant props, asChild via Radix Slot) with Radix behavior for dialogs, tabs, tooltips, and selects, styled exclusively through the workflow UI theme tokens. Every component is correct in light and dark with zero dark-mode code: the OS prefers-color-scheme is respected, and an explicit data-theme="dark|light" on <html> (which the Gateway shell sets from a ?theme= query param) always wins. Import from the smthrs/ui subpath, which resolves through the smthrs install you already have. Importing the scoped @smthrs/ui name directly also works, but requires declaring it as a direct dependency under pnpm-style isolated layouts.

How the three UI packages layer

When you build a workflow UI, reach for the packages in this order:
  1. smthrs/gateway-ui for the run-shaped widgets: RunList, RunTree, RunEventLog, ApprovalPanel, LaunchButton, SimpleWorkflowDashboard, and the WorkflowUiShell page scaffold. Each connects to the Gateway by itself.
  2. smthrs/ui (this page) for everything around those widgets: buttons, cards, inputs, dialogs, tabs, tables, status pills, empty states, KPI stats, and the chat surface. These are pure visual components with no Gateway wiring.
  3. smthrs/gateway-react hooks for bespoke pieces neither library covers: read the same live data the gateway-ui widgets use and render it with the primitives here.
Hand-written markup and hand-written CSS are the last resort, not the first move. A UI assembled from these packages follows the design principles automatically.

Styling model

The stylesheet ships as a JS string (smithersUiCss), never a .css import, because the Gateway’s UI bundler drops CSS artifacts. Render <SmithersUiStyles /> once at the root; every component also self-injects the sheet in the browser as a fallback, so a consumer that forgets it still renders styled. All classes are namespaced sui-*, so nothing collides with the styleguide page vocabulary or your own CSS, and every rule is document-global so Radix portal content (dialogs, tooltips, selects) stays styled. Colors resolve only through var(--token, #lightFallback) expressions over the theme tokens, with tints derived via color-mix. Inside a Gateway-served /workflows/<key> page the shell injects the token block for you. In a standalone host (no Gateway shell), pass withTheme so the token block ships with the sheet:

Components

All components accept className and style, forward refs, and carry data-slot attributes for testing and targeted overrides.

Primitives

House compositions

Chat surface

The shared Multi-style conversation components. They are transport-neutral: feed them Gateway events, SSE text, or stored messages without bringing runtime hooks into the visual layer.

Prompt and attachments

The composer surface: a controlled PromptInput form with submit/stop streaming states and an attachments context that drives the Attachment compound.

Plans, tasks, and queues

Approvals and checkpoints

Sources, citations, and suggestions

Agents and context

Coding artifacts

The review surface: test rollups, commits, diffs-in-brief, stack traces, and the side-panel artifact container.

Sandbox previews

Workflow canvas

See Agentic UI components for the full import surface of every family in one place.

Diff viewer

DiffHunks renders one file’s unified diff, grouped into @@ … @@ hunks with dual old/new line-number gutters, sign glyphs, and per-file line pagination. It is dependency-free (pure React over the ported diff domain) and keeps no store: thread the reveal state yourself with revealed / onReveal. The diff domain that feeds it is exported alongside the component, so callers can build a DiffFile from a raw patch and reason about it without a runtime:

Utilities

Adapters

Heavy third-party editor widgets live behind explicit @smthrs/ui/adapters/* subpaths, so importing the base library never pulls their runtime. Import them from the matching smthrs/ui/adapters/* subpath instead of the root ui barrel. The editor is generic and store-free: multiplayer sync, draft reconciliation, and persistence stay a caller concern, wired through onChange and the imperative setMarkdown (which is echo-suppressed, so an external update never loops back out as a local edit). Ship its Crepe theme CSS with MarkdownEditorStyles alongside SmithersUiStyles, or rely on the browser self-injection fallback every editor performs.

A complete workflow UI

Gateway data via gateway-react hooks and gateway-ui widgets, everything else from this library:
.smithers/ui/triage.tsx
Save it as .smithers/ui/triage.tsx, declare <UI entry="../ui/triage.tsx" /> in the workflow, and open it with bunx smthrs ui RUN_ID. See Custom Workflow UIs for the full wiring guide and Workflow UI Design Principles for the visual language these components implement.