import { Meta } from '@storybook/addon-docs/blocks'

<Meta title="Docs/Choosing a component" />

# Choosing a component

Find what you need; take the row. When nothing fits, build it in your app —
and if what you built knows nothing about your product's objects, propose
it for the package. A component that nearly fits is **forked, not fought**:
fork freely, owe nothing back, mention it on the package's ticket.

## An action

| You need | Reach for |
|---|---|
| A labeled action — a verb, clicked once | **Button** — `primary` at most once per surface |
| An icon-only action | **IconButton** — it requires an `aria-label` |
| An action in a popover list | **MenuItem**, inside a **Menu** |
| A destructive action | **Button** `destructive`, guarded by a **ConfirmDialog** |

## A choice

| You need | Reach for | Not |
|---|---|---|
| One value for a form field | **Select** | a Menu — Select's trigger shows the value |
| Several values, typed then removable | **ChipInput** | checkboxes in a Menu |
| Yes or no | **Checkbox** | a toggle we don't have |
| Yes or no, with words beside it that toggle it too | **Checkbox** `label` | words written beside it by hand — they name nothing and toggle nothing |
| Switching between views of one thing | **Tabs** | a row of Buttons |
| View options behind a `…` | **Menu**, `selected` on the current row | Select |
| Rows of checkboxes that stay open | **Checkbox** `row`, in a list in a **DialogShell** | a Menu — a Checkbox inside a `menuitem` is invalid HTML; a row with `role="option"` drawn by hand |

## Typing

| You need | Reach for |
|---|---|
| One line | **TextInput** |
| One line in a dense row, beside small selects | **TextInput** `size="small"` — 24px, the small Select's height |
| Several lines | **Textarea** |
| Typing that filters a list | **SearchInput** |
| A title edited in place | **EditableText** |
| Label and required-mark around any control | **Field** |
| The fields and the button that sends them | **Form** — Enter sends; `busy` switches everything inside off while it waits |
| A button that opens the file picker | **FilePicker**, opened by your own **Button** or **IconButton** |
| A hint or a failure under **one** control | **Field**'s `helper` / `error` — wired to it, and announced |
| A hint or an outcome under a **group** of controls | **FieldLine** — the same line on its own, with a `warning` tone Field has not got |

## People

| You need | Reach for |
|---|---|
| One face | **Avatar** |
| Several faces, overlapping | **AvatarGroup** |
| Who is in it, at a glance, opening the list | **MembersPill** |
| Who is in it, with Join, Leave and adding people | **MembersDialog** |
| Face and name in a row | **Person** |
| The face that opens a menu | **PersonTrigger** |
| Who you are, where you are, sign out | **IdentityMenu** — the account menu, ready-made |

## Floating surfaces

| You need | Reach for |
|---|---|
| A list of verbs from a trigger | **Menu** — Escape, outside-click and the arrow keys come with it |
| A panel of *content* from a trigger — a field, a toolbar, a small form | **Popover** — the menu's surface without a menu's keyboard |
| More of a thing on hover | **PreviewCard** — unlike a tooltip, you can point at it |
| A hint on hover or on keyboard focus | **Tooltip** / **WithTooltip** — one `TooltipProvider` at the app root shares the delay |
| A strip of controls that act on one thing | **Toolbar** — one Tab stop for the row, arrow keys along it |
| Reactions to choose from | **ReactionPicker** — the row; **Reaction** is the pill it produces |
| The reactions under something people react to, and adding one | **ReactionRow** — the pills, who reacted, and the picker; **AddReactionButton** alone while nobody has reacted |
| One window to find something and act on it, opened by a shortcut | **CommandPalette** — rows, forms and written answers, one level at a time |
| A list that opens as you type in an editor — `/` for commands, `@` for people | **SuggestionMenu** — the editor keeps the caret and hands it the arrow keys; `suggestionPopup` from `@estiva-app/ui/editor` wires it to a Tiptap plugin |
| Bold, italic and the like over selected text in an editor | **SelectionToolbar**, from `@estiva-app/ui/editor` — it follows the selection by itself |
| A composer's `@`, `!@`, `[` and `/` — mention a person, reference something, format or insert | **ComposerTriggers** — `PersonMention`, `UrgentPersonMention`, `CaptionedReference`, `ReferenceTrigger` and `SlashCommands` from `@estiva-app/ui/editor`; the app passes its people, its items and its own `/` rows |
| A document's text, written where it is read, in any app | **DocumentEditor**, from `@estiva-app/ui/editor` — `/`, `[`, `@`, links on words, files, saving when you leave, someone else's save and held typing; the app supplies its codec, its lists, its upload and its views |
| An editor that saves a block document and must keep its block ids | **BlockNodes** — `BlockId`, `UnknownBlock`, `ReferenceNode` and `AttachmentNode` from `@estiva-app/ui/editor`, beside StarterKit and TableKit |
| A page's title or the line under it, edited where it stands, as in a document | **InlineText**, from `@estiva-app/ui/editor` — no box; Enter saves and moves on |
| A comment, a reply or a line written and sent, in any app | **CommentBox**, from `@estiva-app/ui/editor` — triggers, keys, drafts, files, editing and a refused send; the app supplies its people, its `[` sections, its `/` rows and a send |
| Comments on words, a passage or whole blocks of a document, drawn where they are | **CommentHighlights**, from `@estiva-app/ui/editor` — a run of blocks and the words quoted; says which was clicked and which moved or are gone |
| Move, turn, duplicate or delete one block of a document being edited | **EditorBlockHandle**, from `@estiva-app/ui/editor`, with your rows after its own |
| Add or delete a table's rows and columns in a document being edited | **EditorTableControls**, from `@estiva-app/ui/editor`, inside the EditorBlockHandle |
| Offer a link or a comment on one block of a document being read | **BlockHandle** — your rows only, and no Tiptap loaded |
| Anything with a title, body and footer | **DialogShell** |
| "Are you sure?" | **ConfirmDialog** |
| A picture full screen, from a thumbnail | **Lightbox** — an **AttachmentCard** opens one by itself |

## Structure and wayfinding

| You need | Reach for |
|---|---|
| Label–value rows (a details rail) | **Property** — `row` and `stacked` |
| The bar across the top of a column: its title, and the buttons that act on the whole column | **ContainerHeader** — inside the package's columns; in an app, the header comes with **Panel** or **ListColumn** |
| A box that can hold more than fits — a list that grows with its data counts, even when today's data fits | **ScrollArea** — its bar is drawn over the content and takes no width |
| Text that can run long above things the reader needs, cut behind a fade | **ShowMore** — measures; what fits has no button |
| A status, a count or a category, in a small pill | **Chip** — six colour types; the colour is the message, the label makes it legible |
| Something new on a row or a card, no count | **UnreadDot** — the 6px dot in a 24px slot; in a sidebar row, **NavItem** `unread` draws it |
| One thing — a conversation, a project, an object — as a box you can pick | **Card** — the fill by what it sits on; `href` for a link, `hover="fill"` in a feed |
| A section heading, chevron, hover actions, a count beside the title | **SectionHeader** |
| A group of rows that opens and closes, and stays how you left it | **CollapsibleSection** — `storageKey` remembers |
| The uppercase micro-label | **SectionLabel** |
| A hairline | **Divider** |
| Where am I, and the way back up | **Breadcrumb** |
| A link — in text, on a title, beside a note, or a whole box | **Link** — `text`, `quiet`, `underlined`, `plain`; `external` for a new tab |
| A document or an image attached to something, posted or waiting to be sent | **AttachmentCard** — the file decides the shape; `pending` in a composer |
| A picture pasted into an editor, attached rather than pasted | **PastedImages** — from `@estiva-app/ui/editor`; the app hands it its upload |
| Markdown pasted as plain text, landing as the headings, lists and tables it spells | **PastedMarkdown** — from `@estiva-app/ui/editor`, in an editor that saves a block document; the app hands it the protocol's reader |
| A link in a document drawn where it sits: chip in a sentence, row alone on its line, card in the row's place | **LinkPlaces** — from `@estiva-app/ui/editor`, beside `ReferenceNode`; the app's view draws what `place` says. **DocumentEditor** has it |
| A card a chip in a document asks for, drawn after its line (an editor not yet on the line rule) | **ReferenceCards** — from `@estiva-app/ui/editor`, beside `ReferenceNode`; the app draws its card into each slot |
| A URL in a document that reads as the chip of what it points at | **LinkChips** — from `@estiva-app/ui/editor`, beside `ReferenceNode`; the app says what each URL names |
| Open a link in a document, or show a lone one as its row or card, while writing | **ReferenceMenu** — from `@estiva-app/ui/editor`, beside `LinkPlaces`; a click on the link, or putting one alone on a line, opens it |
| A code block in an editor, coloured by its language as you type | **CodeBlockColours** — from `@estiva-app/ui/editor`, in place of the starter kit's code block |
| A link to something an app looked up, in a sentence | **LinkChip** — hover shows its card; loading and "not available" drawn for you. **LinkChips** (editor) turns a URL in a document into one |
| A link alone on its line | **LinkRow** — one 36px line for every kind; **LinkUnavailable** when it cannot be read |
| A link's card: what a row cannot hold, with the pickers the reader may use | **LinkCard** — `onChange` on a picker only for a reader who may change it; **LinkCardLoading** at its height |
| The one card under a piece of text, with the ✕ that removes it | **CardUnder** — `revealOnHover` once it is sent |
| A link's card on hover, read only | **LinkPreview** — LinkChip and LinkRow already wrap themselves in it |
| A part of something longer, shared live | **PartCard** — the app draws the blocks |
| A status and an owner changed in place, a conversation count with its unread dot, a ring | **LinkParts** — `LinkPickers`, `CommentCount`, `StatusMark`, `ProgressRing` |
| A person or a thing named inside a sentence | **InlineChip** — one line high, level with the words; `href` makes it a link |
| What kind of thing a name stands for — a topic, a project, an issue, a file, a message | **KindIcon** — before the name in a row, or inside an **InlineChip**; `thingKindOf` turns an event kind into one |
| Formatted text: headings, lists, a quote, code, a table, links | **RichText** — pass the parsed tree; `small` inside a card |
| The key that does this too | **Kbd** — or the `shortcut` prop on **MenuItem**, **Tooltip** and **SearchInput** |

## Feedback

| You need | Reach for |
|---|---|
| Data is on its way | **Skeleton** — shaped like what will arrive |
| How much of something is done | **ProgressBar** — `default` to be read, with the words beside it; `quiet` for a glance beside a count |
| Nothing to show | **EmptyState** — says what would fill it; `page` when the whole page is empty (icon, centred), `section` when one part of it is (the line alone, left) |
| It happened, briefly | **Toast**, via `useToast` inside a `ToastProvider` |
| It happened, and must not be missed | **Toast** with `durationMs: 0` and an action — it floats and stays until dismissed (D21) |
| The whole surface has something to say | **Banner** — the strip under the top bar, full width; `onDismiss` if the reader closes it rather than the app |
| A part that breaks without taking the page with it | **ErrorBoundary** — around each column, panel or conversation, and once around the app; `label` says what it holds |

## The frame

Two frames, two pairs: the **solid** TopBar goes with the **Sidebar**;
the **floating** TopBar goes with the **Rail** and the content card.

| You need | Reach for |
|---|---|
| The structured frame: solid bar, sidebar, content | **AppShell** `solid` |
| The floating frame: bar over the content, rail, rounded card | **AppShell** `floating` |
| The 52px bar alone | **TopBar** — `solid` in flow, or `floating` over the content |
| A search field in the bar that opens your launcher, with Ctrl+K | the TopBar's `onSearch` — the bar draws the field |
| A 240px navigation column | **Sidebar**, filled with **NavItem** rows |
| Groups of rows in that column, rows under rows, from one nested list | **NavTree**, inside the **Sidebar** |
| A 64px icon strip | **Rail**, filled with **RailItem** tiles |
| The menu button and the logo | the TopBar's `menu` and `logo` slots — collapsing stays yours |
| Where pictures come from, and how to change page without a reload, said once | **AppProvider**, around the whole app |
| What shows while nobody is signed in: the logo, one line, at most one button | **EntryShell** — in place of the whole app; `busy` while entry is decided |
| The list beside the thing that is open | **ListColumn** — 290px, its name in a **ContainerHeader**, the list under it scrolling |
| A panel of a page that is not a list — details, a thread, what is open — with a body that must never be cut off | **Panel** — a header, a body that scrolls whenever it is taller, and a `footer` that stays put |

## Deliberately not in the package

- Anything that knows your **product's objects** — its documents, threads,
  files, tickets. Build it in your app, out of these parts, and keep its
  stories in your app's own Storybook.
- Page layouts beyond the list column (**ListColumn**) and a panel
  (**Panel**) — split views, side rails — not here yet.
