Skip to content

fix(upgrade): stack paywall cards on narrow shell to stop cramping - #343

Merged
thomasluizon merged 1 commit into
mainfrom
fix/paywall-stack-on-narrow-shell
Jun 28, 2026
Merged

fix(upgrade): stack paywall cards on narrow shell to stop cramping#343
thomasluizon merged 1 commit into
mainfrom
fix/paywall-stack-on-narrow-shell

Conversation

@thomasluizon

Copy link
Copy Markdown
Owner

Problem

On the upgrade paywall, the three plan cards (Free / Yearly / Monthly) were crushed side-by-side and looked too tight — CTAs wrapped to two lines (Continuar grátis, Assinar Pro), prices jammed against /mês, and the monthly card's feature list wrapped badly.

Root cause

The web shell hard-caps content at --app-max-w: 640px (globals.css / app/(app)/layout.tsx), but PlanSelection flipped to 3 columns at sm: (640px) — exactly the cap. Three cards, each with their own CTA, end up at ~190px wide. Three pricing cards physically cannot breathe inside a 640px column.

Fix

Gate the entire 3-column mode behind lg: (grid, card order, hero -translate-y, and the loading skeleton — all flipped together so nothing reorders without the grid). Inside the 640px shell the cards now stack full-width: CTAs sit on one line, prices and the monthly feature list have room. The side-by-side 3-column comparison returns automatically once a wider desktop canvas exists (the parked desktop redesign).

Parity

Mobile is unaffected — it uses a separate stacked radio-card paywall (apps/mobile/.../plan-selection.tsx) that is already full-width and roomy. No mobile change needed; no new APK required.

Tests

  • apps/web/__tests__/components/upgrade/* — 9/9 pass (assert text/role/testid, not grid classes).
  • Type-check + lint clean.

🤖 Generated with Claude Code

…amping

The web shell hard-caps content at --app-max-w (640px), but the plan grid
flipped to three columns at sm: (640px) — so the Free/Yearly/Monthly cards,
each carrying its own CTA, were crushed into ~190px: CTAs wrapped to two
lines, prices jammed against /mês, and the monthly card's feature list wrapped
brutally. Three pricing cards physically cannot breathe inside a 640px column.

Gate the 3-column mode (grid, card order, hero lift, loading skeleton) behind
lg: so inside the shell the cards stack full-width — CTAs on one line, prices
and feature lists with room — and the side-by-side comparison returns once a
wider desktop canvas exists.

Mobile is unaffected: it uses a separate stacked radio-card layout that is
already full-width and roomy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
orbit-ui-mobile-web Ignored Ignored Jun 28, 2026 12:57am

Request Review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review: PR #343

Scope: PR #343 — fix(upgrade): stack paywall cards on narrow shell to stop cramping
Recommendation: APPROVE

Summary

Three web-only components (plan-card.tsx, plan-selection.tsx, pricing-section.tsx) are updated to swap sm:grid-cols-3 / sm:order-* / sm:-translate-y-3 to their lg: equivalents, preventing the three plan cards from cramping at the 640px shell maximum width. The change is a pure Tailwind breakpoint promotion with no logic, state, or type impact. All three files are consistent; the mobile platform is correctly unaffected.

Findings

Critical

None

High

None

Medium

None

Low / Info

None

Subagents

Agent Verdict
parity-checker PAIRED — mobile already uses a full-width stacked View layout; breakpoint-responsive grid is a web-platform adapter. No mirror change required.
i18n-syncer IN SYNC — no user-facing strings or i18n keys were added, removed, or altered.
contract-aligner N/A — no packages/shared types or endpoint constants changed.
security-reviewer N/A — no orbit-api code changed.

Validation

Check Result Details
Lint N/A Permission restrictions blocked automated re-run; PR author confirmed clean.
Type check N/A Permission restrictions blocked automated re-run; PR author confirmed clean.
Tests N/A Permission restrictions blocked automated re-run; PR author confirmed 9/9 pass. Tests assert on text/role/testid, not class names — structurally immune to the breakpoint rename.
Build (api) N/A orbit-api not touched.

Deferred — N/A dimensions

  • Dead/stale code (#2): N/A — diff removes no exports; all changed symbols still referenced.
  • SOLID/clean-arch (#3): N/A — no structural or architectural change; functions untouched.
  • Comment policy (#4): N/A — no comments added or changed in the diff.
  • No-workaround (#5): N/A — this is a layout root-cause fix at the correct layer (Tailwind breakpoints), not a workaround.
  • Type safety (#6): N/A — no TypeScript types changed.
  • No console.log (#7): N/A — no logging added.
  • Contract drift + backward-compat (#11): N/A — no shared types or DTO fields changed.
  • Security (#12): N/A — no auth, data exposure, or injection surface changed.
  • Backend hard rules (#13): N/A — orbit-api not touched.

What's good

  • Root-cause fix at the correct layer: breakpoint promotion is exactly the right lever — no workarounds, no special-case CSS, no JS.
  • All three grid/order/translate-y sites updated atomically: plan-selection.tsx, pricing-section.tsx (loading skeleton grid), and plan-card.tsx (card order + hero elevation) all flip together so the layout cannot partially regress.
  • anchor card order cleanup: removing the redundant sm:order-3 (which is already the default stacking position) is a clean simplification.
  • Tests are breakpoint-agnostic: assertions target text, roles, and data-testid — structurally immune to CSS class changes and correctly describe behavior, not implementation.
  • Mobile parity reasoning is sound: mobile uses a React Native View stack with no equivalent responsive grid to update.

Recommendation

Clean, minimal, correct fix. All three mutation sites are consistent, no logic is touched, parity and i18n are confirmed clear. Approve and merge.

@thomasluizon
thomasluizon merged commit ab66e6f into main Jun 28, 2026
9 checks passed
@thomasluizon
thomasluizon deleted the fix/paywall-stack-on-narrow-shell branch June 28, 2026 01:00
@sonarqubecloud

Copy link
Copy Markdown

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