feat(webapp): let customers compare and switch plans in-app - #6907
feat(webapp): let customers compare and switch plans in-app#6907macko911 wants to merge 10 commits into
Conversation
Preview Deploy
|
There was a problem hiding this comment.
All reported issues were addressed across 15 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
The default variant hardcoded the icon to text-disabled regardless of the link's own color, so external-link icons always rendered gray instead of matching the surrounding link text.
Card now accepts a `selected` prop that swaps the border to border/selected (Figma's selected-state token), and CardFooter uses the muted panel background from Figma's Card Footer spec instead of inheriting the panel's own background.
Adds a client-side-only plan override to the dev panel (Ctrl+Shift+D) that lets any plan (including hidden/legacy ones) be previewed without touching the account's real billing state. usePlan.tsx gains useCurrentPlan(), a drop-in replacement for useEnvironment() that overlays the override (looked up from the already-fetched plan list) onto the environment's plan field, and useApiGetCurrentPlan() applies the same overlay. Every read site that gates UI on the current plan is swapped to the new hook so the override is reflected consistently across the sidebar, Connect UI settings, the auto-idling banner, and the function enable/disable switch.
Replaces the plans table with side-by-side comparison cards (Free / Starter / Growth / Enterprise) matching the Figma redesign — each card lists its key limits, the current plan is marked with the selected-state border, and Enterprise (or any other custom/negotiated plan) routes to Contact Us instead of self-serve upgrade/downgrade. Limit bullets are hardcoded display copy (planCardCopy.ts) rather than derived from PlanDefinition.flags, since paid-plan flags are null (uncapped, metered via Orb) and can't produce these numbers. A compact "CURRENT PLAN" card is shown in place of the grid when the account is on a plan outside the 4 self-serve tiers (e.g. a legacy plan) — the existing legacy-plan messaging already surfaces in the Usage section above, so no separate banner is duplicated here. Upgrade/downgrade CTAs reuse the existing plan-change dialog and postPlanChange mutation unchanged; only the presentation and the self-serve eligibility check (now keyed off the active plan being non-hidden, not just its own canChange flag) are new.
6aeab38 to
3910e0c
Compare
useApiGetCurrentPlan/useCurrentPlan's override lookup fetched the full plans list unconditionally, so every consumer (sidebar, Connect UI settings, auto-idling banner, function switches, ...) fired an extra request even with dev tools never opened. Only enable it once an override is actually set.
Accounts on a legacy/custom plan never saw a pending scheduled downgrade or cancellation — the notice only rendered inside the 4 self-serve cards, none of which are ever the active one for a hidden plan. Extracted the notice into ScheduledChangeNotice and render it in CurrentPlanCard too.
The selected state (border/selected) added for the billing plan cards had no Storybook coverage.
It only exposed a Back button, unlike Token Editor, forcing the keyboard shortcut or an extra navigation step to dismiss the panel.
Collapsed CardFooter's className back onto one line to match prettier's output — left multi-line by mistake during a rebase conflict resolution.
StyledLink already conveys its link affordance via text-link color and hover/active states; the underline was redundant/unwanted styling.
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Confidence score: 4/5
- In
packages/webapp/src/components/ui/StyledLink.tsx, removing the baseunderlinecan leave non-iconlinks (like inline Signin “Sign up.” and external links in Connection/List) distinguished by color only, which risks reduced discoverability/accessibility and inconsistent UX — restore an underline for default text links (or add an explicit non-color affordance) and verify the affected call sites.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/webapp/src/components/ui/StyledLink.tsx">
<violation number="1" location="packages/webapp/src/components/ui/StyledLink.tsx:8">
P2: Removing `underline` from the base style means some StyledLink usages (those without the `icon` prop, e.g. inline `"Sign up."` links on Signin or external links in Connection/List) now rely solely on `text-text-link` color to indicate they are links. Per WCAG 1.4.1 (Use of Color), color should not be the only visual means of conveying information — users with color vision deficiency may not perceive the link affordance. Consider adding `underline` back to the default variant, or conditionally applying it when `icon` is false.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| true: '', | ||
| false: '' | ||
| } | ||
| const styledLinkVariants = cva('w-fit inline-flex items-center cursor-pointer focus-default disabled:text-text-disabled disabled:[&_svg]:text-text-disabled', { |
There was a problem hiding this comment.
P2: Removing underline from the base style means some StyledLink usages (those without the icon prop, e.g. inline "Sign up." links on Signin or external links in Connection/List) now rely solely on text-text-link color to indicate they are links. Per WCAG 1.4.1 (Use of Color), color should not be the only visual means of conveying information — users with color vision deficiency may not perceive the link affordance. Consider adding underline back to the default variant, or conditionally applying it when icon is false.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/webapp/src/components/ui/StyledLink.tsx, line 8:
<comment>Removing `underline` from the base style means some StyledLink usages (those without the `icon` prop, e.g. inline `"Sign up."` links on Signin or external links in Connection/List) now rely solely on `text-text-link` color to indicate they are links. Per WCAG 1.4.1 (Use of Color), color should not be the only visual means of conveying information — users with color vision deficiency may not perceive the link affordance. Consider adding `underline` back to the default variant, or conditionally applying it when `icon` is false.</comment>
<file context>
@@ -5,37 +5,34 @@ import { Link } from 'react-router-dom';
- true: '',
- false: ''
- }
+const styledLinkVariants = cva('w-fit inline-flex items-center cursor-pointer focus-default disabled:text-text-disabled disabled:[&_svg]:text-text-disabled', {
+ variants: {
+ variant: {
</file context>
| const styledLinkVariants = cva('w-fit inline-flex items-center cursor-pointer focus-default disabled:text-text-disabled disabled:[&_svg]:text-text-disabled', { | |
| const styledLinkVariants = cva('w-fit underline inline-flex items-center cursor-pointer focus-default disabled:text-text-disabled disabled:[&_svg]:text-text-disabled', { |
Problem
Plan comparison and switching lived on a separate section with a bare table of rows (name, price, a button) — no limits shown, current plan marked with just a small dot, and no way to preview the app under a different plan without actually changing an account's billing.
Solution
canChangeflag, so a legacy plan whose definition happens to still permit a downgrade doesn't leak a self-serve buttonCtrl+Shift+D) that previews any plan (including hidden/legacy ones) across the whole app — sidebar, Connect UI settings, auto-idling banner, function switches — without touching real billingselectedstate to the design-systemCardand a muted background toCardFooter, and fixStyledLink's icon color defaulting to gray instead of matching the link textFixes NAN-6223
Testing
npm run ts-buildandnpm run lintpass cleanScheduled downgrade
