Skip to content

feat(marketing): simplify product menu and show yearly discount#3691

Merged
saddlepaddle merged 1 commit into
mainfrom
ambiguous-saltasaurus
Apr 23, 2026
Merged

feat(marketing): simplify product menu and show yearly discount#3691
saddlepaddle merged 1 commit into
mainfrom
ambiguous-saltasaurus

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented Apr 23, 2026

Summary

  • Remove the "The terminal for coding agents" feature card from the Product nav dropdown; menu now just lists Overview and Changelog.
  • Show $20 struck through next to $15 on the Pro pricing card when Yearly is selected, making the 25% discount explicit.
  • Pin the price row to a fixed height with leading-none so toggling Monthly/Yearly doesn't cause a vertical shift.

Test plan

  • Open marketing site, hover Product — only the two link items render, no card.
  • Open /pricing — Pro card on Monthly shows "$20 per user/month".
  • Toggle to Yearly — Pro card shows "$20 $15 per user/month" with $20 at the left edge, no height change on the card or billing toggle.
  • Free and Enterprise cards unchanged.

Summary by cubic

Simplifies the Product dropdown to two links and makes the Pro yearly discount explicit. Locks the price row height so switching Monthly/Yearly doesn't shift the card.

  • New Features
    • Product nav: removed the feature card; dropdown now lists Overview and Changelog.
    • Pricing: when Yearly is selected, shows "$20" struck through next to "$15" on Pro.
    • UI polish: fixed price row height with leading-none to prevent vertical jump.

Written for commit 58d22a8. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Added strikethrough pricing to display monthly rates when viewing annual billing options.
  • Style

    • Simplified the Product navigation dropdown menu layout.

Remove the feature card from the Product nav dropdown; show $20 struck
through next to $15 on the Pro pricing card when Yearly is selected to
make the discount explicit. Pin the price row height so toggling between
Monthly and Yearly doesn't cause a vertical shift.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

📝 Walkthrough

Walkthrough

Two UI refinements: the Product dropdown navigation is simplified by removing a feature card component and consolidating to a single-column list layout, while the pricing card now displays strikethrough pricing to highlight savings for yearly billing cycles.

Changes

Cohort / File(s) Summary
Navigation Simplification
apps/marketing/src/app/components/Header/components/DesktopNav/DesktopNav.tsx
Removed FeatureCard and SupersetLogo from Product dropdown; converted two-column grid layout to single-column <ul> rendering only PRODUCT_LINKS.
Pricing Display Enhancement
apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx
Added strikethrough field consumption from resolvePrice to render optional line-through price label. Updated price header layout to fixed-height flex container and adjusted typography classes. resolvePrice now returns strikethrough value (null for fixed/custom pricing, monthly price for yearly display otherwise).

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 The Product menu hops anew,
One card removed, the view shines through!
Strikethrough prices boldly stand,
Showing savings, oh so grand!
Cleaner nav with purpose bright—spring marketing takes flight! 🌸

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: simplifying the product menu and displaying the yearly discount on pricing.
Description check ✅ Passed The description covers all key changes with clear test cases, though it deviates from the template structure by using a custom format with auto-generated summary.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ambiguous-saltasaurus

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 23, 2026

Greptile Summary

This PR makes two focused marketing-site changes: it simplifies the Product nav dropdown to a plain link list by removing the FeatureCard component, and it updates the Pro pricing card to show the monthly price struck through next to the discounted yearly price, with a fixed h-10 row to prevent layout shift on toggle.

Confidence Score: 5/5

Safe to merge — changes are UI-only with no data, auth, or runtime risk.

Both changes are small, well-scoped UI updates. The only finding is a P2 defensive guard for a future-proof edge case that doesn't affect current data. All three price kinds are handled correctly in resolvePrice, and the unused SupersetLogo import is properly removed.

No files require special attention.

Important Files Changed

Filename Overview
apps/marketing/src/app/components/Header/components/DesktopNav/DesktopNav.tsx Removes the FeatureCard component and its SupersetLogo import; simplifies the Product dropdown to a plain link list at w-[320px].
apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx Adds strikethrough price display and fixes price-row height with h-10/leading-none; resolvePrice extended cleanly for all three price kinds.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[PricingCard renders] --> B{tier.price.kind?}
    B -->|fixed| C[display=fixed, strikethrough=null]
    B -->|custom| D[display=custom, strikethrough=null]
    B -->|variable| E{isYearly?}
    E -->|true| F[display=yearly.display\nstrikethrough=monthly.display]
    E -->|false| G[display=monthly.display\nstrikethrough=null]
    C --> H[Render price row]
    D --> H
    F --> H
    G --> H
    H --> I{strikethrough set?}
    I -->|yes| J[Render struck-through span + current price]
    I -->|no| K[Render current price only]
    J --> L[Fixed h-10 row — no layout shift]
    K --> L
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx
Line: 103

Comment:
**Strikethrough shown even when prices are identical**

`strikethrough` is always set to `tier.price.monthly.display` when `isYearly` is true, regardless of whether there's actually a discount. If a future `variable` tier has the same `monthly.display` and `yearly.display` (e.g. a launch price with no yearly discount), the UI would show a struck-through price identical to the current price, silently misleading users. A simple guard would prevent this:

```suggestion
		strikethrough: isYearly && tier.price.monthly.display !== entry.display ? tier.price.monthly.display : null,
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "feat(marketing): simplify product menu a..." | Re-trigger Greptile

return { display: entry.display, note: entry.note, cadence: entry.cadence };
return {
display: entry.display,
strikethrough: isYearly ? tier.price.monthly.display : null,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Strikethrough shown even when prices are identical

strikethrough is always set to tier.price.monthly.display when isYearly is true, regardless of whether there's actually a discount. If a future variable tier has the same monthly.display and yearly.display (e.g. a launch price with no yearly discount), the UI would show a struck-through price identical to the current price, silently misleading users. A simple guard would prevent this:

Suggested change
strikethrough: isYearly ? tier.price.monthly.display : null,
strikethrough: isYearly && tier.price.monthly.display !== entry.display ? tier.price.monthly.display : null,
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx
Line: 103

Comment:
**Strikethrough shown even when prices are identical**

`strikethrough` is always set to `tier.price.monthly.display` when `isYearly` is true, regardless of whether there's actually a discount. If a future `variable` tier has the same `monthly.display` and `yearly.display` (e.g. a launch price with no yearly discount), the UI would show a struck-through price identical to the current price, silently misleading users. A simple guard would prevent this:

```suggestion
		strikethrough: isYearly && tier.price.monthly.display !== entry.display ? tier.price.monthly.display : null,
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx (1)

83-106: Optional: tighten the return type of resolvePrice.

Because the fixed/custom branches return note: "" (string literal) and strikethrough: null, while the monthly/yearly branch returns note: entry.note (likely string) and strikethrough: string | null, TypeScript will infer a union across branches. An explicit return type would make the contract clearer and catch accidental shape drift between branches.

type ResolvedPrice = {
  display: string;
  strikethrough: string | null;
  note: string;
  cadence: string | null | undefined;
};

function resolvePrice(tier: PricingTier, isYearly: boolean): ResolvedPrice { ... }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx`
around lines 83 - 106, The resolvePrice function returns inconsistent shapes
across branches which causes TypeScript to widen the inferred return type;
declare an explicit ResolvedPrice type (e.g., display: string; strikethrough:
string | null; note: string; cadence: string | null | undefined) and annotate
resolvePrice(tier: PricingTier, isYearly: boolean): ResolvedPrice, then update
the fixed/custom branches to return values matching that shape (set cadence to
null or undefined and ensure note is a string) so all branches conform to
ResolvedPrice and prevent union widening.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx`:
- Around line 41-48: The strikethrough price in PricingCard is only visually
indicated with the "line-through" class so screen readers will read both values
indistinguishably; update the JSX rendering of the strikethrough (the element
that uses the strikethrough variable) to be semantically explicit for assistive
tech—for example replace the plain span with an <s> (or add role="text" and an
aria-label) or prepend a visually-hidden label like "Original price" to the
strikethrough element so screen readers announce it as the old price while
keeping the visual styling; ensure you modify the element that currently renders
{strikethrough} in PricingCard so the displayed value and the accessible label
convey "old/original price" versus the current {display} price.

---

Nitpick comments:
In
`@apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx`:
- Around line 83-106: The resolvePrice function returns inconsistent shapes
across branches which causes TypeScript to widen the inferred return type;
declare an explicit ResolvedPrice type (e.g., display: string; strikethrough:
string | null; note: string; cadence: string | null | undefined) and annotate
resolvePrice(tier: PricingTier, isYearly: boolean): ResolvedPrice, then update
the fixed/custom branches to return values matching that shape (set cadence to
null or undefined and ensure note is a string) so all branches conform to
ResolvedPrice and prevent union widening.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6297dc10-c121-43f8-a450-7477de11ec5c

📥 Commits

Reviewing files that changed from the base of the PR and between 8b3ff23 and 58d22a8.

📒 Files selected for processing (2)
  • apps/marketing/src/app/components/Header/components/DesktopNav/DesktopNav.tsx
  • apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx

Comment on lines +41 to 48
{strikethrough && (
<span className="text-2xl font-medium tracking-tight leading-none text-muted-foreground line-through">
{strikethrough}
</span>
)}
<span className="text-4xl font-medium tracking-tight leading-none text-foreground">
{display}
</span>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Consider accessibility for the strikethrough price.

The line-through class is purely visual — screen readers won't convey that $20 is the old/struck-through price, so users will hear "$20 $15 per user/month" which is confusing. Consider using a semantic <s> element and/or an aria-label/visually-hidden prefix to communicate the discount.

🛡️ Suggested change
-				{strikethrough && (
-					<span className="text-2xl font-medium tracking-tight leading-none text-muted-foreground line-through">
-						{strikethrough}
-					</span>
-				)}
+				{strikethrough && (
+					<s
+						aria-label={`Was ${strikethrough}`}
+						className="text-2xl font-medium tracking-tight leading-none text-muted-foreground"
+					>
+						{strikethrough}
+					</s>
+				)}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{strikethrough && (
<span className="text-2xl font-medium tracking-tight leading-none text-muted-foreground line-through">
{strikethrough}
</span>
)}
<span className="text-4xl font-medium tracking-tight leading-none text-foreground">
{display}
</span>
{strikethrough && (
<s
aria-label={`Was ${strikethrough}`}
className="text-2xl font-medium tracking-tight leading-none text-muted-foreground"
>
{strikethrough}
</s>
)}
<span className="text-4xl font-medium tracking-tight leading-none text-foreground">
{display}
</span>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/marketing/src/app/pricing/components/PricingTiers/components/PricingCard/PricingCard.tsx`
around lines 41 - 48, The strikethrough price in PricingCard is only visually
indicated with the "line-through" class so screen readers will read both values
indistinguishably; update the JSX rendering of the strikethrough (the element
that uses the strikethrough variable) to be semantically explicit for assistive
tech—for example replace the plain span with an <s> (or add role="text" and an
aria-label) or prepend a visually-hidden label like "Original price" to the
strikethrough element so screen readers announce it as the old price while
keeping the visual styling; ensure you modify the element that currently renders
{strikethrough} in PricingCard so the displayed value and the accessible label
convey "old/original price" versus the current {display} price.

@saddlepaddle saddlepaddle merged commit 7b1fc02 into main Apr 23, 2026
13 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

🚀 Preview Deployment

🔗 Preview Links

Service Status Link
Neon Database (Neon) View Branch
Vercel API (Vercel) Open Preview
Vercel Web (Vercel) Open Preview
Vercel Marketing (Vercel) Open Preview
Vercel Admin (Vercel) Open Preview
Vercel Docs (Vercel) Open Preview

Preview updates automatically with new commits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant