Skip to main content
@smithers-orchestrator/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. 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 smithers-orchestrator/ui subpath, which resolves through the smithers-orchestrator install you already have. Importing the scoped @smithers-orchestrator/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. smithers-orchestrator/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. smithers-orchestrator/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. smithers-orchestrator/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.

Utilities

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 smithers-orchestrator ui RUN_ID. See Custom Workflow UIs for the full wiring guide and Workflow UI Design Principles for the visual language these components implement.