The descriptive half of the design docs: which packages/design/src primitives
exist, their slots, and each one's when-to-use — extracted from the JSDoc on the shipped
components. It is DESCRIPTIVE ONLY. The normative design law — the four pillars, the
prohibitions, and the role-token values — is founder-authored in
design-system-manifest.md and is never written here. A
when-to-use references that law; it never restates or mints it.
Source: packages/design/src/Alert.tsx
When to use: A Manti-backed inline semantic message. Use danger for errors and another semantic variant for non-error outcomes; add kp-alert--inline when preserving a feature's existing text-only geometry.
Slots:
children— The message description.
Source: packages/design/src/Avatar.tsx
When to use: The Manti-backed user/actor image primitive. Always pass name: it names the image and supplies the initials fallback when src is absent or fails. Reach for it for any actor identity glyph.
Slots:
fallback— Rendered internally from the first two initials ofname.
Source: packages/design/src/Badge.tsx
When to use: A Manti-backed compact status or category chip. Keep state in text, not color alone, and use a feature class only to preserve an established Phoenix category palette.
Slots:
children— The badge label.
Source: packages/design/src/Button.tsx
When to use: The Manti-backed base action control. Use primary for the promoted action, secondary for standard actions, tertiary for low-emphasis actions and danger for destructive actions; prefer it over a hand-rolled button.
Slots:
children— The visible label and accessible name.icon— Optional leading decorative glyph, mapped to Manti's icon slot.
Source: packages/design/src/Card.tsx
When to use: The opinionated default for a NEW surface — a bordered, subtly-raised, padded box. Reach for Surface with explicit props only to preserve an existing shell's exact look during a migration (the composite-primitive selection rule is the manifest's, referenced not restated — see design-system-manifest.md).
Slots:
children— The card's content.
Agent directives (@agent — protected, do not regenerate):
- Prefer this composite over hand-rolling a bordered box; do not regenerate this selection guidance — it echoes the manifest's component-selection rule.
Source: packages/design/src/CaylakBadge.tsx
When to use: Never directly — reach for SandboxMarker, which owns the ReviewBadge/CaylakBadge choice so the two cannot stack on one item. Rendered only when the server-derived sandboxedInPlace field is true, which is structurally false while PHOENIX_CAYLAK_VISIBILITY is off.
Slots:
none— Fixed copy; no children slot.
Source: packages/design/src/atoms.tsx
When to use: The inline-code glyph — renders a <code> for an identifier, path, or short literal inside running prose. Reach for it over a styled span so the code run is semantic; for a multi-line block use a <pre>, not this inline atom.
Slots:
children— The code text.
Source: packages/design/src/Collapsible.tsx
When to use: The Manti-backed inline disclosure. Pass the trigger and panel content to reveal optional detail while retaining keyboard and ARIA behavior.
Slots:
trigger— The disclosure control supplied through thetriggerprop.children— The region shown while the disclosure is open.
Source: packages/design/src/CommandPalette.tsx
When to use: A keyboard-first search surface over a caller-owned result set — modal by default, or inline in place at presentation="inline". The caller owns copy, filtering overrides and what selecting a result does.
Slots:
trigger— Optional element that opens the palette. Rendered disabled, not removed, when the palette is disabled.footer— Optional key legend or contextual hint below the results.announcement— Optional sentence for the palette's polite live region, held until the caller replaces it. It is heard, never seen — the visible copy is the caller's own.error— Optional refusal for the search field: the invalid state and the message under it.
Source: packages/design/src/CopyLinkButton.tsx
When to use: The shared paylaş (share/copy-link) control. Reach for it on any shareable item (pano post/comment, sözlük definition) — pass the canonical path and it resolves the absolute URL, copies it, and flashes inline kopyalandı/kopyalanamadı feedback (native share sheet only on coarse-pointer surfaces). Don't hand-roll per-page link logic.
Slots:
none— Renders its own label; no children slot.
Source: packages/design/src/CountToggle.tsx
When to use: The pressable count-pill — a reaction/vote/toggle affordance that carries an aggregate count. Reach for it over a bare toggle button whenever a count rides alongside the on/off state (the reaction bar is the canonical use).
Slots:
children— The visible label; when omitted (icon-only), name the control viaaria-labelsince the icon is decorative.icon— Leading decorative glyph rendered before the label/count.
Source: packages/design/src/Dialog.tsx
When to use: The Manti-backed modal surface for confirmations, forms and focused overlay tasks. Supply title for its accessible name and use the footer render prop when actions need the provided close callback.
Slots:
trigger— Optional element that opens the dialog.children— The dialog body.footer— Optional action row, accepting Manti's dialog render props.
Source: packages/design/src/DraftRestoreBanner.tsx
When to use: The saved-draft restore prompt. Reach for it after a flow that may have stashed a draft across the auth round-trip — it OFFERS restore/discard rather than silently re-injecting (#1214). Wire onRestore/onDismiss to the caller's draft store.
Slots:
none— Fixed copy + two actions; no children slot.
Source: packages/design/src/EditedIndicator.tsx
When to use: The edited-marker glyph. Reach for it on any editable entity's meta row (post, comment, definition) to signal an edit — render it unconditionally and let it self-suppress when the item is unedited or still within the grace window.
Slots:
none— Fixed copy + tooltip; no children slot.
Source: packages/design/src/EmptyState.tsx
When to use: The inline empty-state block. Reach for it to fill a sparse region within a page (an empty feed, a zero-count list, a contribution-less profile) so the void reads as intentional. For a full-page miss use NotFoundPage, its 404 sibling, instead.
Slots:
icon— Optional decorative glyph above the title (aria-hidden).title— The required headline for the empty state.description— Optional supporting line under the title.action— Optional CTA (e.g. a Button) below the copy.
Source: packages/design/src/Form.tsx
When to use: The native form shell around Manti's field-owning Input and Textarea components. Use it for submit semantics without introducing another field state layer.
Slots:
children— The Manti fields and form actions.
Source: packages/design/src/Form.tsx
When to use: The Manti single-line field. Pass its label directly and use hint or error so Manti owns the field's accessible relationships.
Slots:
none— A leaf field control with its label and messages supplied as props.
Source: packages/design/src/atoms.tsx
When to use: The keyboard-key glyph — renders a <kbd> for a shortcut key or key combo mentioned in running text (e.g. a ⌘K hint). Reach for it over a styled span so the key reads as a key semantically, not just visually.
Slots:
children— The key label (a single key or a combo).
Source: packages/design/src/atoms.tsx
When to use: The highlight glyph — renders a <mark> to emphasize a run of text (a search-match hit, a called-out term). Reach for it over a colored span so the highlight carries the native highlight semantics.
Slots:
children— The highlighted text.
Source: packages/design/src/Markdown.tsx
When to use: Read-only display of markdown an agent produced — a chat transcript row, a tool result, any surface that shows model output. It is a renderer, not an editor: for authoring reach for the app's editor instead.
Slots:
children— The markdown source. Not sanitized upstream and not required to be: raw HTML in it renders as text, never as markup.
Source: packages/design/src/Menu.tsx
When to use: The Manti-backed dropdown command list for account and contextual actions. Describe commands through items; use groups and separators for structure instead of hand-built popup content.
Slots:
trigger— The element that opens the menu.items— Commands, separators and command groups supplied throughitems.
Source: packages/design/src/MetaRow.tsx
When to use: The muted metadata row shell — author · time · a count · an action, dot-separated. Reach for it (with MetaRow.Dot between items) for any feed row, post/definition header, or comment footer instead of hand-rolling the row.
Slots:
children— The metadata items; separate them withMetaRow.Dot.
Source: packages/design/src/NumberInput.tsx
When to use: A Manti-backed numeric field with bounds and step controls. Prefer this over a generic Input with type="number" when numeric stepping is the interaction.
Slots:
label— Optional visible field label.
Source: packages/design/src/Popover.tsx
When to use: The Manti-backed non-modal anchored surface for compact interactive content such as the notification preview. Use Dialog when the task must be modal.
Slots:
trigger— The element that anchors and opens the popover.children— The popover content.
Source: packages/design/src/ReportButton.tsx
When to use: The shared bildir (report) control. Reach for it on any reportable item (pano post/comment, sözlük definition) — pass onReport to perform the mutation and it owns the in-flight lock plus the bildirildi/zaten bildirildi feedback, locking once confirmed. Don't hand-roll per-page report logic.
Slots:
none— Renders its own label; no children slot.
Source: packages/design/src/ReviewBadge.tsx
When to use: Every "incelemede" (pending review) badge, wherever it renders — the author's own sandboxed content (post-detail, definition, profile katkıların) and the divan review queue. Never hand-roll a second one; a feature class over a raw Badge variant is how the divan chip ended up grey-on-blue (#5228).
Slots:
none— Fixed copy; no children slot.
Source: packages/design/src/SandboxMarker.tsx
When to use: Any surface showing content that can be sandboxed — the pano feed row, post detail, comment tree node, sözlük definition entry. Renders nothing when neither wire field applies, which is also what every viewer gets with PHOENIX_CAYLAK_VISIBILITY off.
Slots:
none— Chooses a fixed-copy badge; no children slot.
Source: packages/design/src/ScrollArea.tsx
When to use: A bounded Manti-backed scroll viewport that needs keyboard focus and draggable scrollbars while its surrounding header/footer stay fixed.
Slots:
children— Scrollable content.
Source: packages/design/src/Select.tsx
When to use: The Manti-backed selection field for a compact fixed option list whose choices need keyboard navigation and a styled listbox.
Slots:
items— The options supplied throughitems.
Source: packages/design/src/atoms.tsx
When to use: The loading-placeholder block — a shimmering box that reserves space for content still in flight. Reach for it to hold layout during a fetch instead of a spinner or a collapsing void; size it to the content it stands in for.
Slots:
none— Presentational; renders no children.
Source: packages/design/src/Card.tsx
When to use: The parameterized surface shell — background/border/radius/padding/ elevation driven entirely by role-token props. Reach for it (over Card) only to reproduce an existing shell's exact look during a migration; for a new surface prefer Card's opinionated default (the selection rule is the manifest's, referenced not restated — see design-system-manifest.md).
Slots:
children— The surface's content.
Source: packages/design/src/Switch.tsx
When to use: The Manti-backed binary setting control for an immediately applied on/off value. Supply a textual child as its label; use CountToggle when a count travels with the state.
Slots:
children— The switch's trailing accessible label.
Source: packages/design/src/Tabs.tsx
When to use: The Manti-backed sibling-view switcher. Declare each trigger and panel through items; use line, pill or soft appearance without hand-wiring tab roles and selection state.
Slots:
items— Tab labels and their corresponding panel content.
Source: packages/design/src/atoms.tsx
When to use: The category/kind chip — a small colored label for a post kind, topic, or status. Pass href to render it as a link chip, omit it for a static label. Reach for it over a hand-styled span for any categorical badge.
Slots:
children— The chip label.
Source: packages/design/src/Form.tsx
When to use: The Manti multi-line field for free-form content. Pass its label directly; use kp-textarea--mono only for code or preformatted input.
Slots:
none— A leaf field control with its label and messages supplied as props.
Source: packages/design/src/Toast.tsx
When to use: The Manti-backed transient-notification host. Mount it once near the application root and raise ephemeral status through useToast; stable ids replace.
Slots:
children— The subtree that can calluseToast.
Source: packages/design/src/ToggleGroup.tsx
When to use: The Manti-backed compact selection set for segmented controls, filters and small fixed option lists. Supply options through items and control selection with the string-array value contract.
Slots:
items— Toggle options supplied throughitems.
Source: packages/design/src/Tooltip.tsx
When to use: The Manti-backed hover/focus hint for short supplementary text. Never place essential information solely in a tooltip.
Slots:
children— The trigger content wrapped by Manti's inline trigger.
Source: packages/design/src/Tooltip.tsx
When to use: Compatibility-only no-op for the former application-level provider. Manti Tooltip needs no provider; new code should not add another provider.
Slots:
children— The application subtree, returned unchanged.