A three step cancellation: a reason with an optional note, a retention offer, then a final confirm.
FreeWeb and MobileMotion
Preview
npx shadcn add @fetaui/cancel-flowPlaygroundRenews Oct 14
Team plan
Halcyon Studio · 8 seats · $96 a month
- Reason
- Offer
- Confirm
Why are you cancelling?
Your answer shapes what we suggest next. Nothing changes until you confirm on the last step.
0/500
What would feel like a fair price for your team?
OfferRenews Oct 14 50% off
Team plan
Halcyon Studio · 8 seats · $96 a month
- Reason
- Offer
- Confirm
Stay for half price?
You said cost is the issue. Keep Team at 50% off for the next three months, then decide.
$48 a month
instead of $96 · 3 months · 8 seats kept
Or pause for up to 3 months and keep everything as it is.
ConfirmRenews Oct 14
Team plan
Halcyon Studio · 8 seats · $96 a month
- Reason
- Offer
- Confirm
Cancel your plan?
You keep access until the end of this billing period. Nothing is deleted.
Icons animation
Fail next action
Motion
Installation
Terminal· bash
npx shadcn add @fetaui/cancel-flow
Accessibility
- Reasons are a labelled radio group of native radios.
- The step bar is an ordered list with the current step marked.
- Focus moves to the new heading on each step.
Motion
- The panel fades and rises 8 over 400 ms, and rows fade in 40 ms apart.
- Each step fades and rises 8 over 240 ms.
- The step bar fills over 240 ms.
- With reduced motion, the panel fades only and values swap.
Responsive behavior
- Reasons stack below 480 wide.
Performance
- Only the current step is mounted, and steps swap through AnimatePresence.
Note for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Import CancelFlow from @/components/fetaui/cancel-flow. It composes Radio, Textarea and Button with Tag from product-kit.
- onCancel receives reason and note. A rejected promise stays on the confirm step and shows failedMessage.
- onAccept receives the reason. The closing messages are fixed text, including the note about a confirmation email, so send that email.
- offer is one object and does not change with the reason. Pick it from defaultReason or a key if the offer depends on it.
Related
Alert DialogComponentA modal that interrupts with something important and waits for an answer.Plan CardComponentOne plan: name, price, pitch, features and a full width Button.Billing OverviewProBlockBilling settings: current plan, card on file, usage meters and invoices.QuestionnaireComponentAsks one question at a time in a soft tray, with single or multiple answers, shortcuts, validation, restore, and conditional steps.