Feedback buttons

Feedback buttons let people rate an AI answer, summary or flashcard with thumbs up or down, and copy it. Use them under generated content.

  • Beta
  • Accessibility
  • Figma Chat Custom button 8:20313 (under answers: chat card hover 292:10689)
  • packages/ui/src/components/FeedbackButtons

Beta until design confirms the code-only parts (md size, ghost appearance, filled thumb when pressed, the thank-you text, Tell us more and the copied colour) and the buttons are tested with VoiceOver, NVDA and TalkBack. The live app has Copy only; thumbs come from Figma.

Preview

Change the controls to try every supported combination. Copy writes the sample answer to your clipboard.

tsx
const [rating, setRating] = useState<FeedbackValue>(null)

<div className="answer-actions">
  <CopyButton text={answer} />
  <FeedbackButtons
    value={rating}
    onValueChange={setRating}
    onTellUsMore={(r) => openFeedbackForm(r)}
  />
</div>

Installation

Availability

@nuton/ui and @nuton/tokens are private workspace packages and aren't published yet (D4, D12). Inside the Nuton monorepo, add them as workspace dependencies.

bash
pnpm add @nuton/ui @nuton/tokens
tsx
import '@nuton/tokens/tokens.css'
import '@nuton/ui/styles.css'

Usage

tsx
import { CopyButton, FeedbackButtons, type FeedbackValue } from '@nuton/ui'

const [rating, setRating] = useState<FeedbackValue>(null)

<CopyButton text={answer} />
<FeedbackButtons
  value={rating}
  onValueChange={(r) => { setRating(r); saveRating(answerId, r) }}
  onTellUsMore={(r) => openFeedbackForm(answerId, r)}
/>
  • FeedbackButtons is a named group of two toggle buttons (aria-pressed). Pressing the pressed one clears the rating.
  • After a rating it says “Thanks for your feedback” in a polite status message. With onTellUsMore it also offers “Tell us more”; open a short form and move focus into it.
  • CopyButton shows the check and “Copied” for 2 seconds only after the clipboard write succeeds, and announces it. Its name stays “Copy”.
  • Inside a region that already announces changes, such as a chat log, set announce={false} so nothing is read twice.
  • Rename the strings for the content: “Rate this summary”, “Copy card”.

Variants and sizes

Appearances

Figma's Type: Lighter (default) and Stroke. Ghost (no fill) is code-only, for dense toolbars.

Sizes

sm (28)
md (36)
Partsm (Figma, live)md (code-only)
Button28 × 28, radius 836 × 36, radius 10
Icon16 (Figma draws 20; live and Chat use 16)20
Gap4 between buttons, 8 before the thank-you
Thank-youParagraph/X Small, Text/Sub-600
Copy with textIcon + Label/X Small, padding 8

Copy with a text label

States and interactions

DefaultBg/Weak-50, Icon/Sub-600 (Figma State=Default, Type=Lighter).
PressedBg/Strong-950, white filled thumb (Figma State=Active). The filled icon is code-only.
HoverBg/Soft-200 (Stroke: Bg/Weak-50). Only on hover-capable pointers.
Copied (code-only colour)Press it: a green-700 check and “Copied” for 2 seconds, after a successful write only.
Focus (code-only)Press Tab: the primary focus halo, as on Chat buttons. Figma has none.
Disabled (code-only)Icon/Disabled-300, not focusable. Use it while a rating is being saved.

State tokens

Set on .nu-feedback-action.

TokenValueUsed for
--nu-feedback-action-size · --nu-feedback-action-icon28 · 16 (md 36 · 20)Geometry
--nu-feedback-action-bg · --nu-feedback-action-borderBg/Weak-50 · none (Stroke: Bg/White · Stroke/Sub-300)Default
--nu-feedback-action-bg-hover · --nu-feedback-action-border-hoverBg/Soft-200 (Stroke: Bg/Weak-50 · Bg/Weak-50)Hover
(pressed)Bg/Strong-950 · Icon/White; hover Bg/Surface-800Figma Active

Composition examples

AI Tutor answer with a follow-up form

“Tell us more” opens a short form and moves focus into it. Sending it confirms in a status message.

Photosynthesis turns light energy into chemical energy. Chlorophyll absorbs light, water is split to release oxygen, and the energy is stored in glucose made from carbon dioxide.

Summaries and flashcards

Rename the strings for the content being rated and copied.

Summary: The water cycle

Water evaporates, condenses into clouds and falls as precipitation, then collects and evaporates again.

In Chat

ChatMessageActions in Chat shows the same Copy and rating buttons under AI Tutor answers.

API reference

FeedbackButtons props

FeedbackButtons props
PropTypeDefaultDescription
value · defaultValue'good' | 'bad' | nullnullControlled or uncontrolled rating.
onValueChange(value: FeedbackValue) => void—Called with the new rating; null when the pressed button is pressed again.
onTellUsMore(value: 'good' | 'bad') => void—Shows "Tell us more" after a rating and calls this with it.
confirmation'visible' | 'hidden' | 'none''visible'The thank-you after a rating: shown, for screen readers only, or off. It appears only after a rating made here.
announcebooleantruePuts the thank-you in a polite status region. Turn off inside a live region.
size'sm' | 'md''sm'28px (Figma) or 36px buttons.
appearance'lighter' | 'stroke' | 'ghost''lighter'Figma Type Lighter or Stroke, or no fill.
tooltipsbooleantrueShows each button name as a tooltip.
disabledbooleanfalseDisables both buttons.
labelsPartial<FeedbackButtonsLabels>FEEDBACK_BUTTONS_LABELSgroup (“Rate this response”), good (“Good response”), bad (“Bad response”), thanks, tellUsMore.
className · …div propsHTMLAttributes<HTMLDivElement>—Go to the group element; the ref points at it.

CopyButton props

CopyButton props
PropTypeDefaultDescription
textstring | (() => string | Promise<string>)—What to copy, read when pressed.
onCopy(text: string | undefined) => void | Promise<unknown>—Called after the write. Return a promise to show success only when it resolves. Without text, it does the copying.
onCopyError(error: unknown) => void—Called when nothing was copied (no clipboard access, permission denied, or onCopy rejected).
copiedDurationnumber2000How long the success state shows, in ms.
showLabelbooleanfalseShows "Copy" / "Copied" as text; no tooltip then.
tooltipbooleantrueShows "Copy", then "Copied", as a tooltip.
announcebooleantrueAnnounces "Copied" in a polite status region.
size · appearance'sm' | 'md' · 'lighter' | 'stroke' | 'ghost''sm' · 'lighter'As for FeedbackButtons.
labelsPartial<CopyButtonLabels>COPY_BUTTON_LABELScopy (“Copy”) and copied (“Copied”).
…button propsButtonHTMLAttributes—disabled, onClick (call preventDefault to stop the copy) and other attributes go to the button; the ref points at it.

Accessibility

Keyboard

KeyBehaviour
TabMoves to Copy, Good response, Bad response, then Tell us more
Enter / SpaceCopies, or presses and releases a rating
EscCloses a tooltip

Screen readers

The ratings are toggle buttons in a group: “Rate this response, group. Good response, toggle button, not pressed”. After a rating, “Thanks for your feedback” is announced politely. Copy keeps its name and announces “Copied”. Tooltips repeat the names, so they aren't linked as descriptions.

Focus

The primary focus halo on each button. Focus doesn't move after a rating; “Tell us more” comes next in the tab order.

Contrast and colour

Icons Sub-600 on Weak-50 (6.24:1, 5.61:1 on the Soft-200 hover); pressed is white on Strong-950 and also swaps to a filled thumb, so the state isn't shown by colour alone. Thank-you text Sub-600 (6.69:1). In forced-colours mode the pressed button uses Highlight.

Touch and pointer

Buttons are 28 or 36px square with 4px between them (WCAG 2.5.8). Tooltips don't show on touch, so the names never rely on them. Transitions stop with reduced motion.

You must: save the rating, keep the label strings specific to the content, and turn announce off inside an existing live region.

Figma mapping

Figma propertyFigma valuesCode
TypeLighter · Strokeappearance lighter · stroke (ghost is code-only)
StateDefault · Hover · ActiveInteractive states; Active = pressed rating
Iconfile-copy-line · thumb-up-line · thumb-down-lineCopyButton, FeedbackButtons

Guidelines and related components

Use feedback buttons for

  • Rating AI answers, summaries, flashcards and podcasts
  • Copying generated text

Don't use them for

  • Star ratings or surveys (use a form)
  • Liking or saving content (use a toggle Button)
  • Quiz answers (use Quiz)

Do and don't

DoName what is being rated “Rate this summary” tells screen reader users what the thumbs refer to.
Don'tShow a thumb with no name or tooltip An unlabelled icon could mean like, approve or vote.
Thanks for your feedback
DoThank people once, quietly A short polite message confirms the rating without interrupting.
Please explain your rating (required)
Don'tOpen a form for every rating Offer “Tell us more” instead, so giving detail is a choice.