Suggestion
Prompt-starter chips on a horizontal scroll row — staggered entrance, a neutral pill that tints on hover, and the suggestion string handed straight to onClick.
<Suggestions> {starters.map((starter) => ( <Suggestion key={starter} suggestion={starter} onClick={setDraft} /> ))}</Suggestions>Usage
import { Suggestion, Suggestions } from "@reva/ui";Suggestions is the prompt-starter row — chips never wrap, the row scrolls horizontally on the house ScrollArea (the strongest ScrollArea case: native horizontal scrollbars are platform-inconsistent and undiscoverable on mobile). ScrollArea's type default (hover) applies, so the scrollbar appears on pointer-over; pass type="always" when discoverability matters — recommended for touch-first layouts, where there is no hover to discover the overflow with.
Chips stagger in ~50ms apart (the row orchestrates; chips subscribe via variants); on hover the pill tints up a step — a colour shift and a pointer cursor, no transform. Reduced motion branches values only: the row's initial collapses so chips mount directly at their visible values — the markup never forks. A chip rendered outside Suggestions gets no variant labels propagated to it, so it renders static and fully visible — graceful standalone degradation by construction.
onClick is called with the suggestion string, not the event — wire it straight to "set the composer draft" on the Prompt Input. children override the visible label while suggestion stays the click payload.
Each chip is the house Button (outline / sm) forced to a true pill with rounded-full — per the squircle rules, pills are always true rounds, never a large fixed radius.
Composition
Use the following composition to build a Suggestions row:
Suggestions (horizontal ScrollArea row — the stagger orchestrator)
└── Suggestion (× n) (one chip per prompt starter — Button outline/sm pill)Examples
Selected readout
The string payload means a state setter wires in directly — here it feeds a readout instead of a composer. initial={false} skips the entrance stagger for rows that shouldn't animate.
Nothing selected yet.
const [selected, setSelected] = useState<string | null>(null);<Suggestions initial={false}> {starters.map((starter) => ( <Suggestion key={starter} suggestion={starter} onClick={setSelected} /> ))}</Suggestions>Always-visible scrollbar
On touch there is no hover to summon the scrollbar, so a row that must read as scrollable should keep the bar visible.
<Suggestions type="always"> {starters.map((starter) => ( <Suggestion key={starter} suggestion={starter} /> ))}</Suggestions>Accessibility
- Chips are real buttons (
type="button") via the house Button — ordinary tab stops, and tabbing to an off-screen chip scrolls it into view natively. - The row carries a small padding bleed so the 3px focus ring isn't clipped by the scroll viewport, while chips still align flush with surrounding content.
- Reduced motion changes values only — the stagger collapses (chips mount visible); the markup is identical either way.
Props
| Component | Prop | Type | Default | Description |
|---|---|---|---|---|
Suggestions | type | "auto" | "always" | "scroll" | "hover" | "hover" | ScrollArea scrollbar visibility — use "always" for touch-first layouts. |
Suggestions | initial / animate | Motion variant labels | "hidden" / "visible" | Override the row's variant labels — initial={false} skips the entrance. |
Suggestions | transition | Transition | ~50ms stagger | Override the stagger orchestration (the visible variant's transition). |
Suggestion | suggestion | string | — | The prompt-starter string — the chip label and the click payload. Required. |
Suggestion | onClick | (suggestion: string) => void | — | Called with the suggestion string, not the event. |
Suggestion | children | ReactNode | the suggestion string | Override the visible label; suggestion stays the payload. |
Suggestion | variant / size | Button variants | "outline" / "sm" | Pass through to the underlying Button. |
Suggestion | variants / whileHover | Motion props | chip enter / none | Override the entrance variants, or add a Motion hover gesture (none by default). |
Attachment Chip
A file attachment chip — a status-aware label with an optional image thumbnail and a hover preview (image, PDF, or file summary). Shared by the chat composer and sent-message rows.
Reasoning
The collapsible thinking trace — auto-opens while reasoning tokens stream, auto-collapses once they settle, and hands control to the user on first toggle.