Skip to content

Lists

List/ListRow is the rows-of-selectable-things primitive behind every picker in Silo — branch switcher, worktrees, workspace folders, the Extensions page. It stretches to fill its parent, truncates long content instead of overflowing, and ships its keyboard behavior built in.

servicetitan-contactcentermain
limit-console-logs-to-kibana
/Users/dweaver/Projects/ai/xerro-agent/projects/xerro-edit

(Third row shows truncate="start" on a long path; the last row is an AddRow.)

tsx
import { List, ListRow, Badge } from "@silo-code/sdk";

<List aria-label="Workspace folders">
  <ListRow
    selected={folder.primary}
    leading={<FolderIcon />}
    trailing={<Badge tone="accent">primary</Badge>}
    onSelect={() => choose(folder)}
  >
    {folder.path}
  </ListRow>
</List>;

List

PropTypeNotes
aria-labelstringrequired — it's a listbox
onActivate((index: number) => void)?Enter / double-click

ListRow

PropTypeNotes
selectedboolean?the selected row gets the active fill
leadingReactNode?icon slot (dimmed, fixed)
trailingReactNode?badge(s) and/or IconButton size="sm"(s) — several are fine side by side
truncate"end" | "start"default "end". Use "start" for paths, where the filename end matters most
onSelect / onActivate(() => void)?click / Enter-or-double-click

Layout behavior — guaranteed, don't fight it

  • The list and its rows are full-width: they fill the parent and never push past its edge, however long the content. Row text truncates with an ellipsis; trailing content (badges, icon buttons) never shrinks or gets pushed offscreen.
  • truncate="start" ellipsizes the front (…agent/projects/xerro-edit) — the right choice for file paths.
  • When a row's content is genuinely likely to truncate, wrap it in Tooltip with disabled={!isTruncated} so a hover reveals the full value — see the pattern in Tooltip's docs.

Keyboard — built in, one tab stop

The whole list is a single tab stop. Once focused: ↑/↓ move a focus ring row to row, Space/Enter selects the focused row, and focus survives the re-render a selection triggers — a user can Space → arrow → Space indefinitely without the list dropping focus. Don't attach your own key handlers to rows.

AddRow

The ghost "+ Add Folder…" action that sits flush under a list — visually a row, semantically a button. No fill at rest, bg-hover on hover, pressed feedback like every other button.

tsx
<List aria-label="Folders">…</List>
<AddRow onClick={addFolder}>Add Folder…</AddRow>
ColorToken
Row hover / selected fill--silo-list-hover-bg / --silo-list-active-bg
Row text / leading icon--silo-color-text-hi / --silo-color-text-lo
Focus ring--silo-color-accent

Filter-above-list (the picker pattern) is a composition with SearchInput — see Building modals.