A cancellation survey with reason options and a retention offer to keep the subscription.
Help us improve — why are you cancelling?
Install with the CLI, or add the packages and paste the source below.
Add Cancel Flow to your app with its source-owned dependencies.
npx cooud-ui add cancel-flow
Install the Cooud UI packages, then paste the block below.
Copy the source for Cancel Flow. Every class is a semantic token, so it re-themes with your app.
import {Banner,Button,Card,CardContent,CardFooter,CardHeader,CardTitle,Label,RadioGroup,RadioGroupItem,Separator,} from "@cooud-ui/ui";import { Sparkles } from "lucide-react";const cancelReasons = [{ id: "reason-expensive", label: "Too expensive" },{ id: "reason-features", label: "Missing features I need" },{ id: "reason-switching", label: "Switching to another tool" },{ id: "reason-usage", label: "Not using it enough" },{ id: "reason-other", label: "Other" },];export function CancelFlowBlock() {return (<section aria-label="Cancel subscription" className="mx-auto w-full max-w-md"><Card className="shadow-md"><CardHeader><CardTitle className="font-display text-lg">We're sorry to see you go</CardTitle><p className="col-span-full text-sm text-fg-secondary">Help us improve — why are you cancelling?</p></CardHeader><CardContent className="flex flex-col gap-5"><RadioGroupdefaultValue="reason-expensive"aria-label="Reason for cancelling"className="gap-2">{cancelReasons.map(({ id, label }) => (<Labelkey={id}htmlFor={id}className="flex cursor-pointer items-center justify-between gap-3 rounded-lg border border-border bg-surface-inset px-3 py-2.5 font-normal text-fg has-[:checked]:border-primary">{label}<RadioGroupItem value={id} id={id} /></Label>))}</RadioGroup><Bannervariant="success"align="start"dismissible={false}icon={<Sparkles aria-hidden="true" />}title="Stay and get 30% off for the next 3 months"description="Apply the discount and keep everything you have today."action={<Button variant="outline" size="sm">Apply offer</Button>}/></CardContent><Separator /><CardFooter className="justify-end gap-3"><Button variant="ghost" size="sm" className="text-error hover:text-error">Cancel anyway</Button><Button variant="gradient" size="sm">Keep my subscription</Button></CardFooter></Card></section>);}
Help us improve — why are you cancelling?