@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:smthrs/gateway-uifor the run-shaped widgets:RunList,RunTree,RunEventLog,ApprovalPanel,LaunchButton,SimpleWorkflowDashboard, and theWorkflowUiShellpage scaffold. Each connects to the Gateway by itself.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.smthrs/gateway-reacthooks for bespoke pieces neither library covers: read the same live data the gateway-ui widgets use and render it with the primitives here.
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 acceptclassName 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 controlledPromptInput 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 viagateway-react hooks and
gateway-ui widgets, everything else from this
library:
.smithers/ui/triage.tsx
.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.