Skip to content
Component installs need the registry setup
VegaStack Design

Suggestion Card

An agent offers one person a next step, in a card only they see, with buttons that name the action.

Status
stable
Since
0.44.0
Accessibility pattern
named region; ticks are labelled checkboxes

Last updated

Only you can see this

Assistant · 3 decisions from this chat

Expires tomorrow

Install

Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Suggestion Card before installation. Retain the digest printed by this command.

pnpm exec vegastack-design verify suggestion-card

Install with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.

pnpm dlx shadcn@4.21.0 add @vegastack/suggestion-card

Run the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.

The same command installs the registry items it composes: @vegastack/checkbox, @vegastack/truncated-text.

Usage

import { SuggestionCard } from "@/components/ui/suggestion-card";

<SuggestionCard
  privateLabel="Only you can see this"
  avatar={<PersonAvatar person={agent} size="sm" />}
  title="Assistant · 3 decisions from this chat"
  items={items}
  onItemCheckedChange={toggle}
  actions={
    <>
      <Button size="sm" variant="secondary" onClick={accept}>
        Create 2 tasks
      </Button>
      <Button size="sm" variant="ghost" onClick={dismiss}>
        Dismiss
      </Button>
    </>
  }
  footnote="Expires tomorrow"
/>;

The card has no action or wording of its own: the host passes the buttons and every line. For an agent that must wait for a decision before it acts, use ApprovalCard. A suggestion is an offer, and ignoring it is fine.

Only you can see this

Assistant · 3 decisions from this chat

Expires tomorrow

Examples

Accepting

state="busy" holds the items still while the host works. The spinner goes on the host's main button, and the host turns off its other buttons, so Dismiss can't race the accept.

Only you can see this

Assistant · 2 decisions from this chat

Outcomes

accepted replaces the card with outcome, a plain line, with actions after it for Undo. Use it too for something an agent did by itself. expired folds to the title, outcome and actions. failed keeps the whole card, so Retry has its items. A dismissed card is simply not rendered.

Asha created 2 tasks from Assistant's suggestion

Assistant created 3 tasks from this chat

Assistant · 2 decisions from this chat

This suggestion expired.

Assistant · 2 decisions from this chat

Couldn't create the tasks.

In a list

variant="row" is the compact form for a list: the title and buttons side by side, stacked in a container under 32rem. privateLabel, items and the footnote don't show.

Assistant · Create 2 tasks from "4000 K downlight decision"

API Reference

PropTypeDefaultDescription
title*React.ReactNode—What is offered, and the card's name: "Assistant · 3 decisions from this chat".
actionsReact.ReactNode—The buttons, which name the action: a secondary "Create 2 tasks", then ghost "Review" and "Dismiss". Never primary, and never "Yes" or "No thanks".
avatarReact.ReactNode—The agent's avatar, before the title.
footnoteReact.ReactNode—The quiet line at the foot: "Expires tomorrow".
itemsreadonly SuggestionCardItem[][]What it would act on.
menuReact.ReactNode—The ⋯ menu, at the card's top end.
onItemCheckedChange((id: string, checked: boolean) => void)—An item was ticked or unticked.
outcomeReact.ReactNode—What became of it: "Asha created 2 tasks from Assistant's suggestion".
privateLabelReact.ReactNode—Who it is for, above the title: "Only you can see this".
stateSuggestionCardState"open"busy — accepting: the items hold still. The spinner goes on the host's main button, and the host holds or drops the others, so Dismiss can't race the accept. accepted — the card gives way to outcome, a plain line, with actions after it ("Undo"); it also fits something an agent did by itself. expired — the title, outcome and actions ("Ask again"). failed — the whole card with outcome over actions ("Retry"). After accepted, ref is what's left to take focus: the button that had it is gone.
variant"card" | "row""card"card — in a conversation, full width. row — compact, for a list: the title and buttons side by side, stacked in a container under 32rem; privateLabel, items and the footnote don't show.

Data attributes and CSS variables on SuggestionCard

AttributeValues
data-slot"suggestion-card" | "suggestion-card-actions" | "suggestion-card-avatar" | "suggestion-card-footnote" | "suggestion-card-header" | "suggestion-card-heading" | "suggestion-card-item" | "suggestion-card-items" | "suggestion-card-menu" | "suggestion-card-outcome" | "suggestion-card-private" | "suggestion-card-title"
data-statemirrors a prop or state value
data-variantmirrors a prop or state value
PropTypeDefaultDescription
id*string—A stable key, and what onItemCheckedChange reports.
label*React.ReactNode—What it is: "Order 3000 K samples". Cut with an ellipsis on one line.
checkedboolean—Ticked. Leave it out for an item that can't be unticked: no checkbox.
metaReact.ReactNode—A muted note kept whole at the row's end: "Ravi, Wed".

Accessibility

  • An open card is a region named by its title. A row is a group, and an accepted line is neither, so a long list or history doesn't flood the landmarks.
  • Each item's label names its checkbox. A long label is cut on screen, not for a screen reader, and shows in full on hover.
  • A card that appears announces nothing. Announce a failure or an acceptance through the conversation's own useAnnouncer region, and after accepted move focus to the card with ref, since the button that had it is gone.
KeyAction
TabMove through ticks and buttons
SpaceTick or untick an item
ContractStates tested
Behaviouropen, busy, accepted, expired, failed, ticks, no-ticks
Accessibilitynamed-region, group-row, no-landmark-when-accepted, labelled-checkboxes, aria-busy, browser-accessibility-test
Visualcard, busy, outcomes, row

Do / Don't

Do
Name the action on the button, 'Create 2 tasks', with a quiet 'Dismiss' after it.
Don't
Write 'Yes, do it' or 'No thanks', or make the main button primary.

On this page