@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:smithers-orchestrator/gateway-uifor the run-shaped widgets:RunList,RunTree,RunEventLog,ApprovalPanel,LaunchButton,SimpleWorkflowDashboard, and theWorkflowUiShellpage scaffold. Each connects to the Gateway by itself.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.smithers-orchestrator/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.Utilities
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 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.