Patterns · composition guide
Feedback pattern
How to build transient and post-action feedback — toasts, the DS V3 Alert inline banner, inline correct/incorrect result panels, and the CSAT thumbs widget — from existing components, plus when NOT to use a toast.
◆ generated from guidelines/feedback.json + parts/feedback.guide.md — do not edit by hand
Based on
The rationale, worked examples, and the full assertion set live in the design skill — this pattern distils the enforceable subset and links each rule back to it.
aha-design:aha-design-feedback
judge aha-design:aha-design-feedback-judge
Choose the surface
| Surface | Use for | Example |
|---|---|---|
| Toast (fixed bottom-right pill) | transient, non-actionable confirmation; auto-dismiss ~3s | "Thanks for your feedback", "Copied" |
| Alert (inline banner) | persistent, in-context message the user may need to act on; stays in layout | inline error/info/warning/branding banner |
| Inline result panel (correct/incorrect) | in-place result feedback shown after an answer | quiz correct/incorrect with explanation |
| CSAT thumbs widget | a satisfaction (thumbs up/down) prompt with optional follow-up | post-flow "How was this?" rating |
Composed of
What a compliant feedback surface reuses from this design system — the pattern's link into the component graph.
| Reuses | Kind | For | In DS? |
|---|---|---|---|
icon | component | the DS system status glyph per Alert type (check-circle / x-circle / info-circle / warning-triangle / lightbulb), the × close glyph, the thumbs glyphs — functional icons only, stroke 1.5 | available |
--aha-colorSuccess | token | inline correct-result border and Alert success border — never hardcode a hex | available |
--aha-colorSuccessBg | token | inline correct-result background surface | available |
--aha-colorError | token | inline incorrect-result border and Alert error border | available |
--aha-colorErrorBg | token | inline incorrect-result background surface | available |
alert | component | the DS V3 AhaAlert inline banner — 5 types (success/error/info/warning/branding) × regular/small sizes, DS surface/border/icon tokens, distinct glyph per type; NOT a bare AntD Alert | missing |
toast | component | the bespoke fixed bottom-right pill (role=status, ~3s auto-dismiss, portalled to document.body) for custom bottom-right content | missing |
message | component | AntD message/notification API for ordinary app-level success/info toasts | missing |
csat | component | the shared Csat thumbs widget — binary rating with optional thumbs-down follow-up, required source token, best-effort csat.* analytics | missing |
Rules
The shippable checklist — each rule traces to an assertion in aha-design:aha-design-feedback.
| Rule | Skill assertion |
|---|---|
| Use a toast only for a transient, non-actionable confirmation. Render it as a small fixed pill at the viewport bottom-right that rises from below so it never shifts surrounding layout, and auto-dismiss after ~3s, clearing the timer on unmount. | FEEDBACK-01 |
| A toast carries role="status" so it is announced without stealing focus, and is portalled via createPortal(node, document.body) to escape any transformed/filtered/overflow ancestor that would clip a position:fixed element. | FEEDBACK-02 |
| For ordinary app-level success/info toasts, prefer AntD's message/notification APIs; reserve the bespoke fixed pill for when you need the specific bottom-right placement and custom content. | FEEDBACK-03 |
| Build the DS V3 AhaAlert wrapper per references/alert.md — DS surface/border/icon tokens per type plus size (regular: 12/16 padding, 8px radius, 14px text; small: 8px padding, 4px radius, 12px text). Never ship a bare AntD <Alert>: it cannot express the branding type, the regular/small sizes, the DS surface/border tokens, or the DS system glyphs. | FEEDBACK-08 |
| Support five types — success, error, info, warning, branding — each with its own DS bg-surface/border/icon token AND a distinct system glyph (check-circle / x-circle / info-circle / warning-triangle / lightbulb); colour is never the only signal. | FEEDBACK-09 |
| Alert text uses only Plus Jakarta Sans 400 (message and inline link) and 600 (title) — no 300/500/700; snap any other supplied weight to the nearest (title → 600, body → 400). | FEEDBACK-10 |
| The Alert title/heading is sentence case — capitalize the first letter only (plus proper nouns); never Title Case, never ALL CAPS. | FEEDBACK-11 |
| The Alert spec is token/role based so it applies unchanged to AntD, Vue, or plain CSS — wire the DS --p-color-* tokens onto whatever token layer the target app uses (e.g. the app's --aha-* / AntD theme tokens). | FEEDBACK-08 |
| Use an Alert for a persistent, in-context message the user may need to act on; use a toast for a transient auto-dismissing confirmation. | FEEDBACK-08 FEEDBACK-01 |
| Inline post-action (correct/incorrect) feedback uses role="status" with aria-live="polite" (informational, not urgent). | FEEDBACK-04 |
| Colour the inline result container with semantic tokens — border var(--aha-colorSuccess)/var(--aha-colorError) and background var(--aha-colorSuccessBg)/var(--aha-colorErrorBg); never hardcode hex. | FEEDBACK-04 |
| Lead the inline result with a strong correct/incorrect label; show the correct answer and any explanation below when incorrect. | FEEDBACK-04 |
| Expose stable data-* hooks (data-correct, data-element-id) on the inline result for testing. | FEEDBACK-04 |
| Use the shared Csat widget — a binary thumbs rating with an optional follow-up on thumbs-down. Do not build a bespoke rating control. | FEEDBACK-05 |
| Pass a required source token from the closed CsatSource union (one per placement) so Mixpanel sees stable, typo-proof segmentation; add a union member when adding a placement. | FEEDBACK-05 |
| CSAT emits CSAT_SHOWN (once per mount), CSAT_RATED, and CSAT_FEEDBACK_SUBMITTED; tracking is best-effort — a throwing/uninitialised track() must never break rendering or block the thank-you toast. | FEEDBACK-06 |
| Do NOT put these in a toast: an actionable error (inline Alert in context or an overlay Alert), a field validation error (FieldErrorDisplay / a11y FieldError, shared-components), a destructive confirmation (a modal, aha-design-overlays), or a full-page failure (ErrorPage, shared-components). A toast that auto-dismisses must never be the only place a required message lives. | FEEDBACK-07 |
Composition code
Doc-only — this pattern ships no wrapper from this repo. Doc-only pattern — ships no composition wrapper from this repo. The canonical feedback components (the Csat widget at components/csat/Csat.tsx, InlineFeedback at features/respondent/shared/InlineFeedback.tsx, the AhaAlert wrapper per references/alert.md, and the bespoke toast pill) live in the product app. If a wrapper graduates into this DS, add a reuse block and it is gated like a composite.
Guide
Feedback — composition guide
aha-design-feedback plugin skill is generated FROM this artifact. The judge criteria and evals stay in the skill (aha-design-feedback-judge); when the two ever disagree on construction, this file wins."Feedback" means any non-blocking signal that an action happened or how it turned out: transient confirmations (toasts), inline banners (the DS V3 Alert), in-context result feedback (correct/incorrect), and satisfaction prompts (CSAT) — not field-validation errors or blocking dialogs. These surfaces reuse existing components — Icon, the semantic --aha-color* tokens — so this pattern adds no new control; it defines the conventions that keep every feedback surface reading as one product.
Pick the surface first
| Surface | Use for |
|---|---|
| Toast (fixed bottom-right pill) | A transient, non-actionable confirmation that auto-dismisses (~3s) |
| Alert (inline banner) | A persistent, in-context message the user may need to act on; stays in layout |
| Inline result panel (correct/incorrect) | In-place result feedback shown after an answer |
| CSAT thumbs widget | A satisfaction (thumbs up/down) prompt with an optional follow-up |
Toasts (transient confirmations)
- Use a toast only for a transient, non-actionable confirmation ("Thanks for your feedback", "Copied").
- Position: a small fixed pill at the viewport bottom-right; it rises up from below so it never shifts surrounding layout.
- Auto-dismiss after ~3s (the cross-product convention); clear the timer on unmount.
- Carry
role="status"so it is announced without stealing focus. - Portal to
document.bodyviacreatePortal(node, document.body). Aposition: fixedtoast is clipped by any ancestor that establishes a containing block (transform,filter,backdrop-filter,will-change); portalling keeps it truly viewport-fixed from every mount point. - For ordinary app-level success/info toasts, prefer AntD's
message/notificationAPIs; reach for the bespoke fixed pill only when you need the specific bottom-right placement and custom content.
Alert (inline banner)
The Design System V3 Alert — an inline banner for feedback that stays in the layout (unlike a toast). Full spec, tokens, size metrics, and Figma node IDs live in the skill's references/alert.md.
- Do not ship a bare AntD
<Alert>. It cannot express the DSbrandingtype, theregular/smallsizes, the DS surface/border tokens, or the DS system glyphs. Build the thinAhaAlertwrapper the reference specifies. - Five types, each with its own DS
bg-surface/border/icontoken and a distinct glyph — colour is never the only signal:
| Type | Glyph |
|---|---|
success | check-circle |
error | x-circle |
info | info-circle |
warning | warning-triangle |
branding | lightbulb |
- Two sizes:
| Regular | Small | |
|---|---|---|
| Padding | 12 vertical / 16 horizontal | 8 all sides |
| Border radius | 8 | 4 |
| Text size | 14 | 12 |
- Font weight — 400 and 600 only. Plus Jakarta Sans 400 (Regular) for the message and inline link; 600 (SemiBold) for the optional title. No 300 / 500 / 700 — snap any other weight to the nearest (title → 600, body → 400).
- Heading is sentence case — capitalize the first letter only (plus proper nouns). Never Title Case, never ALL CAPS.
- The spec is token/role based, so it applies unchanged to AntD, Vue, or plain CSS — wire the DS
--p-color-*tokens onto whatever token layer the target app uses. - Alert vs toast: use an Alert for a persistent, in-context message the user may need to act on; use a toast for a transient auto-dismissing confirmation.
Inline post-action feedback (correct/incorrect)
For result feedback shown in place after an answer:
role="status"witharia-live="polite"(it's informational, not urgent).- Colour the container with semantic tokens: border
var(--aha-colorSuccess)/var(--aha-colorError)and backgroundvar(--aha-colorSuccessBg)/var(--aha-colorErrorBg). Never hardcode hex. - Lead with a strong correct/incorrect label; show the correct answer and any explanation below when incorrect.
- Expose stable
data-*hooks (data-correct,data-element-id) for testing.
CSAT (satisfaction) prompts
- Use the shared
Csatwidget — a binary thumbs rating with an optional follow-up on thumbs-down. Do not build a bespoke rating control. - Pass a required
sourcetoken from the closedCsatSourceunion (one per placement) so Mixpanel sees a stable, typo-proof segmentation. Add a union member when adding a placement. - It emits
CSAT_SHOWN(once per mount — the response-rate denominator),CSAT_RATED, andCSAT_FEEDBACK_SUBMITTED. Tracking is best-effort: a throwing/uninitialisedtrack()must never break rendering or block the thank-you toast.
When NOT to use a toast
| Situation | Use instead |
|---|---|
| Error the user must act on | Inline Alert banner in context (or an overlay Alert) |
| Field validation error | FieldErrorDisplay / a11y FieldError (shared-components) |
| Destructive confirmation | A modal (aha-design-overlays) |
| Full-page failure (not found, expired) | ErrorPage (shared-components) |
A toast that auto-dismisses must never be the only place a required message lives.
*Full detail, the complete references/alert.md spec (tokens, size metrics, Figma node IDs), and
all FEEDBACK-xx assertions live in the aha-design-feedback skill. Self-check any built surface with aha-design-feedback-judge and fix every FAIL before shipping.*