← All proposals

Feedback Bar

A small atomic component: a thumbs-up and thumbs-down pair with one piece of state, built from the local IconButton (its existing isPressed toggle, which maps to aria-pressed).

Net-new componentOpen in Storybook

proposals/FeedbackBar/decisions.md68 lines · View on GitHub

Decisions: Feedback Bar

Its own atomic component (2026-10-19)

  • Decision: FeedbackBar is its own small component, not part of Chat Message or Suggestion Card.
  • Why: it appears in several places (under a chat message, in an accepted Suggestion Card, under a Chain of Thought or a Code Diff). Built into one of them, the others would copy it. Chat Message and Suggestion Card stay slot-based; the screen places the bar.
  • Port impact: none.

UI only (2026-10-19)

  • Decision: the bar reports up, down or null through onValueChange and does nothing else. No analytics, no reason flow, no copy.
  • Why: what the signal is for (quality tracking, evals, training) is not decided. The designer asked for the UI in case it is needed. The screen sends the choice with the context that makes it useful (which message or suggestion, which model, whether it was accepted).
  • Port impact: the screen wires onValueChange to whatever it uses.

Built from the existing buttons (2026-10-19)

  • Decision: the thumbs are the local IconButton with isPressed (it maps to aria-pressed) and the thumbsUp / thumbsDown icons; there is no dismiss button. No solid icon variant was found, so pressed shows the IconButton's pressed styling, not a filled thumb.
  • Why: reuse. Pressing the chosen thumb again clears it (null).
  • Port impact: uses the local IconButton and Icon until they are ported.

One look: the bare thumbs (2026-10-19)

  • Decision: the bar is just the two thumbs (plus statusLabel and the children slot). A bordered prompt-bar look (leading icon, visible question label, divider and dismiss button) was built from the designer's second screenshot, then removed with its variant, label, iconName, onDismiss and dismissLabel props and the CloseButton dependency: the designer does not need that design.
  • Why: nothing in the product screens used it. statusLabel replaces the thumbs in a role='status' region that stays in the DOM so it is announced.
  • Port impact: none. If a prompt bar is wanted later, it is a new proposal, or a variant added back.

No text hardcoded, and the wording must not promise an outcome (2026-10-19)

  • Decision: upLabel, downLabel and groupLabel are required; statusLabel is optional. The stories use "Thanks for the feedback" and "Good response" / "Bad response", not wording about training.
  • Why: page translation, and the team has not decided what the feedback is used for. If it is used for training, the screen needs a plain disclosure.
  • Port impact: none.

Status text is xs and secondary (2026-10-19)

  • Decision: statusLabel renders as Copy XS (pds-copy-xs) in --pds-color-foreground-default-secondary, quiet and small.
  • Why: the designer's call: a confirmation should sit back from the content.
  • Port impact: none.

Interactive story, and the PDS Clipboard Button for copy (2026-10-19)

  • Decision: the main story is Interactive (it replaced Default): press a thumb, the status text shows for 4.5 seconds, then the thumbs return with the choice pressed; the controls still change the labels. In All States the copy action in the extras slot is the package ClipboardButton (icon copy, animating to check when pressed), not a plain icon button.
  • Why: the designer asked. The copy-to-check swap is what the PDS Clipboard Button already does (it passes icon2Name='check' to IconButton), so it is reused, not replicated.
  • Port impact: none; the timing is story-only.

Usage says it is built on IconButton (2026-10-19)

  • Decision: the Usage page states that the bar is two IconButton toggles in a labelled group, and what the component adds on top (the pairing logic, the group label, the status text).
  • Why: the designer asked, so engineers see how thin the component is and where its behavior comes from.
  • Port impact: none.

Top-level in the sidebar, not under Conversation (2026-10-19)

  • Decision: the story title is Component Proposals/Feedback Bar (it started under AI Chat/Conversation).
  • Why: nothing in it is chat-specific. It does not know about messages, and anything that outputs agent work can use it (a chat reply, a Chain of Thought, a Code Diff, an Autopilot page). The sidebar already keeps Timeline, Thinking State and Chain of Thought at the top level for the same reason; Chat Message and Suggestion Card stay in Conversation because they only make sense in a chat.
  • Port impact: none. The story ids changed (component-proposals-feedback-bar--*), so figma.json's frame keys were updated; the Figma page is unchanged.

Thumbs and thanks fade in when they swap (2026-10-20)

  • Decision: the thumbs sit in an __actions wrapper, and both the wrapper and the status text fade in (--pds-animation-duration-reveal) when they appear. Off with prefers-reduced-motion. The timing stays with the screen.
  • Why: the thanks line was replaced by the thumbs with a hard cut after a few seconds. The fade makes the thanks ease away.
  • Port impact: adds the __actions part and one keyframe.

Open questions

  • What is the signal used for, and who owns it (analytics, ML)? It decides whether a reason (free text or a list) after thumbs-down is needed.
  • Is a filled (solid) thumb wanted for the pressed state? The icon set has none; it would be a new icon.
  • Should the extra actions (copy, retry) have their own component, as a message actions bar?