Skip to content
Sign in
ConversationCompare responsesMenu

Compare responsesPro

Two candidate answers stream side by side; pick one, call a tie or skip, and the kept answer settles into the thread.

ProTwo changelog drafts stream side by side; pick one with 1 or 2 and it settles into the thread.

Installation

$ pnpm dlx shadcn@latest add @chatcn-pro/compare-responses

Usage

tsx
import { CompareResponses } from "@/components/ui/chatcn/pro/compare-responses"

<CompareResponses
  responses={[
    { id: "a", text: a.text, status: a.status },
    { id: "b", text: b.text, status: b.status },
  ]}
  onChoose={(choice) => record(choice)}
/>

Both answers stream at once in their own scroll columns, and the choice waits until both are done. Pick with I prefer this one, or 1 and 2 on the keyboard; About the same and Skip sit underneath. Once chosen, the kept answer slides from its column to the thread's measure and becomes an ordinary reply, with a quiet line recording the choice and the other answer one click away. Below stackBelow (600 px) the two stack behind a two way toggle. hotkeys="global" listens for 1 and 2 anywhere outside text fields, for the newest comparison in a thread.

Examples

States

ProBoth still writing, one failed with retry, rated about the same, and the stacked toggle in a narrow column.

Props

PropTypeNotes
responses[Candidate, Candidate]{ id, text, status?, error? }, Markdown text
choice, defaultChoice, onChoose{ type: "pick", id } | { type: "tie" } | { type: "skip" }Controlled or not
onRetry(id) => voidShows Retry on a failed response
hotkeys"focus" | "global" | falseDefault focus
stackBelownumberDefault 600 px
maxHeightnumber | stringColumn height cap, default 26 rem
renderBody(candidate) => ReactNodeDefaults to Markdown
labelsPartial<…Labels>Every string, for translation

Keyboard

KeyAction
1 and 2Prefer that response, once both are done
TabEach column scrolls from the keyboard, then its choice button

Accessibility

  • The comparison is a section named by its question; each column is a focusable region named Response 1 or 2.
  • Columns are busy while they stream; the status line under the question is polite.
  • The settle is announced once, as in Response 2 kept in the thread.
  • The stacked toggle uses pressed buttons, so the open response is stated.

Motion

The settle is the one moment that moves: the kept answer slides from its column to the thread in 280 ms, transform only, and the record of the choice fades in after it. Chosen from the keyboard, the layout changes without the slide. Reduced motion keeps the fades.