feat(pricing): align desktop and marketing comparison tables#3867
Conversation
Renames Cloud → Remote workspaces, swaps the (Coming Soon) text for proper Beta/Coming-soon Badges, adds an Automations row (Pro+), and reorders Features so they read top-to-bottom by surface (workspaces → automations → mobile → integrations → collab). The marketing /pricing page mirrors the desktop billing comparison.
📝 WalkthroughWalkthroughA boolean Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.Comment |
Greptile SummaryThis PR aligns the desktop billing comparison table and the marketing Confidence Score: 5/5Safe to merge; all remaining findings are P2 style/copy issues that don't block functionality. All changes are purely presentational data/UI updates with no logic, state, or API surface affected. The two P2 findings (uppercase badge casing in marketing, stale tier card feature bullets) are cosmetic inconsistencies that do not cause runtime errors or data problems. No files require special attention.
|
| Filename | Overview |
|---|---|
| apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx | Replaces comingSoon boolean with a structured badge config, adds Badge import, reorders/renames features rows to match marketing — looks correct. |
| apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx | Replaces ComingSoonBadge with RowBadge; the uppercase CSS class causes badge labels to render in ALL-CAPS on marketing while the desktop Badge renders normal-cased text, creating a visual inconsistency. |
| apps/marketing/src/app/pricing/constants.ts | Comparison table data aligned with desktop (reorder, rename, new Automations row, badge config); PRICING_TIERS feature bullets still reference the dropped CLI and old "Mobile (coming soon)" label. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["ComparisonRow data\n{ label, values, badge? }"] --> B["Desktop page.tsx\n<Badge variant> from @superset/ui"]
A --> C["Marketing constants.ts\nCOMPARISON_SECTIONS"]
C --> D["ComparisonTable.tsx\n<RowBadge> span with CSS"]
B --> E["Renders: 'Beta' / 'Coming soon'\n(normal case)"]
D --> F["Renders: 'BETA' / 'COMING SOON'\n(uppercase via CSS class)"]
E -.->|"Visual mismatch"| F
Comments Outside Diff (1)
-
apps/marketing/src/app/pricing/constants.ts, line 35-41 (link)Stale CLI and Mobile feature bullets in tier cards
The comparison table now drops the CLI row and renames "Mobile" to "Mobile app", but
PRICING_TIERSstill lists"CLI (coming soon)"in the Free tier features and"Mobile (coming soon)"in the Pro tier. If those bullet lists are rendered anywhere on the pricing page, visitors will see the dropped CLI feature and a mismatched name for Mobile. Worth updating to keep the tier card copy consistent with the comparison table.Prompt To Fix With AI
This is a comment left during a code review. Path: apps/marketing/src/app/pricing/constants.ts Line: 35-41 Comment: **Stale CLI and Mobile feature bullets in tier cards** The comparison table now drops the CLI row and renames "Mobile" to "Mobile app", but `PRICING_TIERS` still lists `"CLI (coming soon)"` in the Free tier features and `"Mobile (coming soon)"` in the Pro tier. If those bullet lists are rendered anywhere on the pricing page, visitors will see the dropped CLI feature and a mismatched name for Mobile. Worth updating to keep the tier card copy consistent with the comparison table. How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx
Line: 176-189
Comment:
**Badge text casing differs from desktop**
`RowBadge` applies `uppercase tracking-wide` in the marketing component, so "Beta" renders as **BETA** and "Coming soon" renders as **COMING SOON**. The desktop `<Badge>` component renders text exactly as-is, giving "Beta" and "Coming soon". Since this PR explicitly aligns the two tables, the uppercase transform creates a visible inconsistency that will be obvious when both surfaces show the same label.
Consider dropping `uppercase` from the class list (or applying it in both), so the rendered text matches what's in the data.
```suggestion
function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) {
const isPrimary = badge.variant === "default";
return (
<span
className={cn(
"rounded-sm px-2 py-0.5 text-[10px] font-medium tracking-wide",
isPrimary
? "bg-foreground text-background"
: "bg-accent/40 text-muted-foreground",
)}
>
{badge.label}
</span>
);
}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: apps/marketing/src/app/pricing/constants.ts
Line: 35-41
Comment:
**Stale CLI and Mobile feature bullets in tier cards**
The comparison table now drops the CLI row and renames "Mobile" to "Mobile app", but `PRICING_TIERS` still lists `"CLI (coming soon)"` in the Free tier features and `"Mobile (coming soon)"` in the Pro tier. If those bullet lists are rendered anywhere on the pricing page, visitors will see the dropped CLI feature and a mismatched name for Mobile. Worth updating to keep the tier card copy consistent with the comparison table.
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "feat(pricing): align desktop and marketi..." | Re-trigger Greptile
| function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) { | ||
| const isPrimary = badge.variant === "default"; | ||
| return ( | ||
| <span | ||
| className={cn( | ||
| "rounded-sm bg-accent/40 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", | ||
| "rounded-sm px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide", | ||
| isPrimary | ||
| ? "bg-foreground text-background" | ||
| : "bg-accent/40 text-muted-foreground", | ||
| )} | ||
| > | ||
| Coming soon | ||
| {badge.label} | ||
| </span> | ||
| ); |
There was a problem hiding this comment.
Badge text casing differs from desktop
RowBadge applies uppercase tracking-wide in the marketing component, so "Beta" renders as BETA and "Coming soon" renders as COMING SOON. The desktop <Badge> component renders text exactly as-is, giving "Beta" and "Coming soon". Since this PR explicitly aligns the two tables, the uppercase transform creates a visible inconsistency that will be obvious when both surfaces show the same label.
Consider dropping uppercase from the class list (or applying it in both), so the rendered text matches what's in the data.
| function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) { | |
| const isPrimary = badge.variant === "default"; | |
| return ( | |
| <span | |
| className={cn( | |
| "rounded-sm bg-accent/40 px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground", | |
| "rounded-sm px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide", | |
| isPrimary | |
| ? "bg-foreground text-background" | |
| : "bg-accent/40 text-muted-foreground", | |
| )} | |
| > | |
| Coming soon | |
| {badge.label} | |
| </span> | |
| ); | |
| function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) { | |
| const isPrimary = badge.variant === "default"; | |
| return ( | |
| <span | |
| className={cn( | |
| "rounded-sm px-2 py-0.5 text-[10px] font-medium tracking-wide", | |
| isPrimary | |
| ? "bg-foreground text-background" | |
| : "bg-accent/40 text-muted-foreground", | |
| )} | |
| > | |
| {badge.label} | |
| </span> | |
| ); | |
| } |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx
Line: 176-189
Comment:
**Badge text casing differs from desktop**
`RowBadge` applies `uppercase tracking-wide` in the marketing component, so "Beta" renders as **BETA** and "Coming soon" renders as **COMING SOON**. The desktop `<Badge>` component renders text exactly as-is, giving "Beta" and "Coming soon". Since this PR explicitly aligns the two tables, the uppercase transform creates a visible inconsistency that will be obvious when both surfaces show the same label.
Consider dropping `uppercase` from the class list (or applying it in both), so the rendered text matches what's in the data.
```suggestion
function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) {
const isPrimary = badge.variant === "default";
return (
<span
className={cn(
"rounded-sm px-2 py-0.5 text-[10px] font-medium tracking-wide",
isPrimary
? "bg-foreground text-background"
: "bg-accent/40 text-muted-foreground",
)}
>
{badge.label}
</span>
);
}
```
How can I resolve this? If you propose a fix, please make it concise.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/marketing/src/app/pricing/constants.ts (1)
105-113:⚠️ Potential issue | 🟠 MajorMigrate remaining
comingSoonusage tobadgepattern.The
ComparisonRowmigration fromcomingSoon?: booleantobadge?: { label: string; variant }is incomplete. A stalecomingSoon: true,reference remains atapps/desktop/src/renderer/components/Paywall/constants.ts:75and must be updated to match the new interface.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/marketing/src/app/pricing/constants.ts` around lines 105 - 113, ComparisonRow's shape changed from comingSoon?: boolean to badge?: { label: string; variant: "default" | "secondary" }, so find the object still using comingSoon: true and replace that property with badge: { label: "Coming soon", variant: "secondary" } (or "default" if visually intended) so it conforms to the ComparisonRow interface; update the object literal where comingSoon appears and remove the comingSoon key, adding the badge key instead.
🧹 Nitpick comments (2)
apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx (1)
176-190: Prefer the sharedBadgeprimitive here.
RowBadgeis only restyling a badge chip; reusing@superset/ui/badgewould keep the marketing and desktop tables visually aligned and avoid a second variant map.Suggested change
+import { Badge } from "@superset/ui/badge"; import { cn } from "@superset/ui/utils"; @@ function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }) { - const isPrimary = badge.variant === "default"; - return ( - <span - className={cn( - "rounded-sm px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide", - isPrimary - ? "bg-foreground text-background" - : "bg-accent/40 text-muted-foreground", - )} - > - {badge.label} - </span> - ); + return <Badge variant={badge.variant}>{badge.label}</Badge>; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx` around lines 176 - 190, Replace the custom span in RowBadge with the shared Badge component from `@superset/ui/badge`: import Badge and render <Badge> instead of the span inside function RowBadge({ badge }: { badge: NonNullable<ComparisonRow["badge"]> }), map the local badge.variant ("default" vs other) to the Badge's variant prop (e.g., "default" -> Badge variant "primary" or the project equivalent) and pass badge.label as children; remove the custom className string and any duplicate styling so the component uses the shared Badge's styling and variants to keep visuals consistent.apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx (1)
50-54: Keep the comparison-row shape strict.
values: ComparisonValue[]is looser than the fixed 3-column grid, so a fourth value would compile even though the layout can't render it correctly. Reusing the shared tuple shape here would catch that mismatch earlier.Suggested change
type ComparisonRow = { label: string; - values: ComparisonValue[]; + values: [ComparisonValue, ComparisonValue, ComparisonValue]; badge?: { label: string; variant: "default" | "secondary" }; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx` around lines 50 - 54, The ComparisonRow type allows any-length arrays via values: ComparisonValue[] which lets a fourth value compile even though the UI renders a fixed three-column grid; change the values property to the fixed tuple type [ComparisonValue, ComparisonValue, ComparisonValue] (or the shared tuple alias if one exists) so the compiler enforces exactly three columns—update the ComparisonRow declaration to use that tuple and adjust any places that construct ComparisonRow to supply exactly three ComparisonValue items (or refactor to reuse the shared tuple type).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@apps/marketing/src/app/pricing/constants.ts`:
- Around line 105-113: ComparisonRow's shape changed from comingSoon?: boolean
to badge?: { label: string; variant: "default" | "secondary" }, so find the
object still using comingSoon: true and replace that property with badge: {
label: "Coming soon", variant: "secondary" } (or "default" if visually intended)
so it conforms to the ComparisonRow interface; update the object literal where
comingSoon appears and remove the comingSoon key, adding the badge key instead.
---
Nitpick comments:
In
`@apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsx`:
- Around line 50-54: The ComparisonRow type allows any-length arrays via values:
ComparisonValue[] which lets a fourth value compile even though the UI renders a
fixed three-column grid; change the values property to the fixed tuple type
[ComparisonValue, ComparisonValue, ComparisonValue] (or the shared tuple alias
if one exists) so the compiler enforces exactly three columns—update the
ComparisonRow declaration to use that tuple and adjust any places that construct
ComparisonRow to supply exactly three ComparisonValue items (or refactor to
reuse the shared tuple type).
In
`@apps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsx`:
- Around line 176-190: Replace the custom span in RowBadge with the shared Badge
component from `@superset/ui/badge`: import Badge and render <Badge> instead of
the span inside function RowBadge({ badge }: { badge:
NonNullable<ComparisonRow["badge"]> }), map the local badge.variant ("default"
vs other) to the Badge's variant prop (e.g., "default" -> Badge variant
"primary" or the project equivalent) and pass badge.label as children; remove
the custom className string and any duplicate styling so the component uses the
shared Badge's styling and variants to keep visuals consistent.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 70323c21-67e6-4793-b167-e362bf04efa0
📒 Files selected for processing (3)
apps/desktop/src/renderer/routes/_authenticated/settings/billing/plans/page.tsxapps/marketing/src/app/pricing/components/ComparisonTable/ComparisonTable.tsxapps/marketing/src/app/pricing/constants.ts
Summary
Mirrors the same set of changes on the desktop billing comparison table and the marketing
/pricingcomparison table:(Coming Soon)text with proper Badges:ComingSoonBadgewith aRowBadgethat picks primary/secondary styling from the row's badge configThe two comparison tables now show the exact same feature list in the exact same order.
Test plan
bun run typecheckandbun run lintclean (verified locally)/pricing, scroll to comparison table — desktop and mobile breakpoints both show new order, badges, Automations rowSummary by cubic
Aligns the desktop Billing and marketing
/pricingcomparison tables so they show the same features in the same order, and replaces inline “Coming soon” text with clear badges.RowBadgewith primary/secondary variants.Written for commit 7320a0f. Summary will update on new commits. Review in cubic
Summary by CodeRabbit
New Features
Style