# Build the "Rated response with reason" pattern: `ResponseRating`

## Stack (edit this block to match your project)
- React 18+ with TypeScript: one function component, typed props, no `any`.
- Tailwind CSS, using your design system's tokens if you have them.
- Presentational only: data comes in through props, decisions go out through callbacks. No fetching or global state inside.
- If your codebase already has conventions (naming, shared components, tokens), follow them over this spec.

## What the pattern is for
Thumbs plus a short structured reason, so the signal is diagnosable rather than a bare score.

Use it when: Any generative surface you intend to evaluate and improve.

## What to build
Thumbs up and down controls on an AI response that, after a rating, ask for a short structured reason (chips plus an optional note) and show exactly what will be sent. It turns a bare score into a diagnosable report. It renders in the action row under each response.

### Props
- `rating`: "up" | "down" | null, controlled.
- `reasons`: { up: Array<{ id: string; label: string }>; down: Array<{ id: string; label: string }> }, e.g. "Inaccurate", "Outdated", "Wrong source", "Too long".
- `selectedReasons`: string[] and `note`: string.
- `status`: "idle" | "asking" | "submitting" | "submitted" | "error".
- `contextSummary`: Array<{ label: string; value: string }>, what is attached to the rating, e.g. conversation, response id, model version, sources.
- `onRate(rating)`, `onReasonsChange(ids)`, `onNoteChange(text)`, `onSubmit()` and `onSkip()`: callbacks. The component never sends anything itself.
- `noteMaxLength?`: number (default 500).

### States it must render
- Idle: two icon buttons with labels in tooltips.
- Asking: after a rating, a small panel with reason chips for that direction, an optional note, a "What we'll send" disclosure listing `contextSummary`, and Send / Skip.
- Submitting: Send disabled with a busy indicator.
- Submitted: "Thanks, sent to the quality team" with the chosen reasons echoed; the thumb stays pressed.
- Error: "Couldn't send" with Retry, keeping the selections.

### Interactions
- Clicking a thumb calls `onRate` and opens the reason panel; clicking the pressed thumb again clears the rating.
- Chips are multi-select toggles calling `onReasonsChange`.
- Send calls `onSubmit`; Skip calls `onSkip`, which keeps the bare rating rather than discarding it.
- Changing direction after submitting reopens the panel with the other reason set.

### Edge cases
- A down rating with no reason chosen: allow Send but nudge once ("A reason helps us fix it"), never block.
- Note contains personal data: show a hint that it is attached to the conversation, and the context list makes clear what is shared.
- Many responses in a thread: only one reason panel open at a time.
- Ratings on a still-streaming response: thumbs disabled until done.

## Must avoid
Thumbs with no follow-up, producing volume you cannot act on and users who stop bothering.

## Engineering constraint
Log the full request context with the rating; free-text reasons need clustering to be useful.

## Accessibility
- Thumbs are toggle buttons with `aria-pressed` and labels "Good response" / "Bad response".
- When the reason panel opens, move focus to its first chip; on close, return focus to the thumb.

## House rules
- Real `<button>`/`<input>` elements, full keyboard use, visible focus; announce status changes with `aria-live="polite"`; respect `prefers-reduced-motion`.
- All user-facing text comes from props (or a `labels` prop) so it can be translated.
- One consistent accent marks anything the AI made or is doing; amber means "needs a person", red means risky, green means done. Never rely on colour alone.
- Fits a 360 px wide container without horizontal scrolling.

## Acceptance checks
- [ ] Every state above can be rendered by passing props, with no internal fake data.
- [ ] Every interaction and edge case above behaves as described.
- [ ] Nothing in "Must avoid" can happen with this component.

## Deliver
1. The component file with its exported prop types.
2. A short usage example that renders each state.
