Elements

09 / 37 · Messages

Follow-up suggestions

Prompt pills that stagger in after a reply and invite the next turn.

Installation

npx shadcn@latest add "@assistant-ui/elements-suggestions"

Usage

import { Suggestions } from "@/components/elements/suggestions";

<Suggestions
  suggestions={["Explain more", "Show an example"]}
  selectedSuggestion={null}
  cycle={0}
  onSuggestion={setSelected}
/>

Props

suggestions*readonly string[]Follow-up prompt pills rendered in order.
selectedSuggestion*string | nullThe pill currently pressed, or null when none is selected.
cycle*numberIdentity key that remounts the row so the stagger entrance can replay.
variant"pills" | "list"pills wraps suggestions into a centered row; list stacks them as full-width rows.
onSuggestion*(suggestion: string) => voidCalled when a suggestion pill is pressed.
classNamestringExtra classes merged onto the root.

Source

suggestions.tsx
"use client";

import { cn } from "@/lib/utils";
import { paper } from "./surfaces";

export interface SuggestionsProps {
  suggestions: readonly string[];
  selectedSuggestion: string | null;
  cycle: number;
  onSuggestion: (suggestion: string) => void;
  variant?: "pills" | "list";
  className?: string;
}

export function Suggestions({
  suggestions,
  selectedSuggestion,
  cycle,
  onSuggestion,
  variant = "pills",
  className,
}: SuggestionsProps) {
  const list = variant === "list";

  return (
    <div
      key={cycle}
      className={cn(
        list
          ? "flex w-full max-w-sm flex-col gap-2"
          : "flex max-w-md flex-wrap justify-center gap-2",
        className,
      )}
    >
      {suggestions.map((suggestion, index) => (
        <button
          key={suggestion}
          type="button"
          aria-pressed={selectedSuggestion === suggestion}
          onClick={() => onSuggestion(suggestion)}
          className={cn(
            paper,
            "fade-in slide-in-from-bottom-2 animate-in fill-mode-both flex cursor-pointer items-center text-[13px] transition-transform duration-300 hover:-translate-y-px active:scale-[0.96] motion-reduce:animate-none",
            list
              ? "w-full rounded-2xl px-4 py-2.5 text-start"
              : "rounded-full px-4 py-2",
            selectedSuggestion === suggestion &&
              "bg-foreground text-background",
          )}
          style={{ animationDelay: `${index * 70}ms` }}
        >
          {suggestion}
        </button>
      ))}
    </div>
  );
}