Feedback
Two components for "there's nothing to show" and "here's what this means." Neither is an alert box.
EmptyState
The big-icon + title + dim-description block a modal shows when a list is empty or everything is fine ("All workflows passing"). It renders flat in the modal body — no card, no shadow of its own.
import { EmptyState } from "@silo-code/sdk";
<EmptyState
tone="ok"
icon={<CheckIcon />}
title="All workflows passing"
description="No failures or active runs on this repo."
/>
<EmptyState
icon={<SearchIcon />}
title="No matching branches"
description="Try a different filter."
/>| Prop | Type | Default | Notes |
|---|---|---|---|
tone | "ok" | "neutral" | "neutral" | colors the circled icon; ok = green ring for positive-empty |
icon | ReactNode? | rendered inside the ring | |
title | string | — | base/600/text-hi |
description | string? | sm/text-lo | |
action | ReactNode? | e.g. a Button ("Clear filter") |
Use the neutral tone for "nothing matched"; ok for "empty because everything is good." A failure state is not an EmptyState tone — show the error content itself.
Callout
A quiet set-off box for explanatory copy — a hairline border around body text, no fill, no tone. The canonical case: the Worktrees modal's closing paragraph explaining what opening a worktree does.
import { Callout } from "@silo-code/sdk";
<Callout>
Opening a worktree adds it as another folder in this workspace — its files,
terminals, and Git panel appear alongside your current ones. Closing a view
leaves the worktree untouched on disk.
</Callout>;No props beyond children — that's the point. A Callout is not a warning, error, or info-alert box (there is deliberately no tone): status belongs to Badge tones and EmptyState. If you're tempted to make a Callout yellow, you're building the wrong thing.
| Color | Token |
|---|---|
| Border | --silo-color-border-strong |
| Text | --silo-color-text (sm, body role) |
Tooltip
A hover/focus label for anything whose meaning isn't already on the page — most often an IconButton, whose aria-label gives screen readers a name but leaves sighted users with nothing. It's the one component here that isn't modal-scoped: Tooltip is app-wide (status bar, panels, toolbars, and modal content), so its full prop reference lives with the rest of ctx-level API docs at Tooltip rather than only here — this section covers the pattern you'll actually reach for inside a modal.
import { Tooltip, IconButton } from "@silo-code/sdk";
<Tooltip content="Refresh">
<IconButton aria-label="Refresh" onClick={refresh}>
<RefreshIcon />
</IconButton>
</Tooltip>;The other common case inside modal content: a ListRow's truncated text — see Tooltip's disabled prop for the show-only-when-truncated pattern.