Design system/Patterns
Upgrade prompt
When a feature isn't in the current plan, the same prompt appears everywhere: the feature name, the name of the plan that includes it, an upgrade button, and, if there's another way, that way.
In codecomponents/plan-gate.tsx
Live example
The server still refuses on its own; this component only turns the readable half of that refusal, { gate: "plan", requiredPlan, requiredPlanName }, into one sentence and one button. The plan name comes from the plan row in the database, so renaming a plan updates every prompt with it.
This feature is part of the Prime plan.
Without it the assistant still works with ready-made questions and plans.
This feature is part of the Prime plan.
Rules
Do
If there's a way forward without upgrading, put it alongside: "Continue without AI".
Don't
Blocking the task when its simple version works.
Do
One place, right next to the thing that was asked for.
Don't
An upgrade popup on every sign-in.
Do
The button goes to the subscription page with that plan already selected.
Don't
Sending people to the pricing page to figure out again what they wanted.
if (isPlanGate(res)) return <PlanGate info={res} detail={tr("…")} onFallback={runScripted} />;A limit, not a penalty
A plan limit is a cap on "adding", never a reason to take something away. A workspace whose plan has run out keeps all its members and just can't invite the next one. The upgrade prompt says exactly that, not a threat.
Sizes and accessibility
radius 12px · padding 14px · gap 10pxcompact: 10px · gap 8px--accent-soft · border 1px var(--accent)32px · icon 14pxcompact 26px · 12px · #fff on --accent13px / 700 · leading 24pxcompact 12px12px · --text-secondarybtn-sm · btn-accent and btn-ghost36px · phone 40pxrole="note"Symbol aria-hidden- The title is --text on soft orange: 14.4 to 1 in light and 12.15 in dark.
- The description, --text-secondary on soft orange, is 4.55 to 1 in light and 4.98 in dark, AA in both; even so, the main message always goes in the heading.
- The upgrade button is btn-accent, white on --accent-strong (5.19 to 1 in both themes); its label is short and bold and has a lightning icon.
Related pages