Repository navigation
Prevent pricing CTA loading layout shifts - #8806
Conversation
📝 WalkthroughWalkthroughCheckout loading content is centralized in ChangesCheckout pending UI
Estimated code review effort: 2 (Simple) | ~10 minutes Sequence Diagram(s)sequenceDiagram
participant ProCtaLink
participant CheckoutPendingContent
participant CheckoutSpinner
ProCtaLink->>CheckoutPendingContent: pass pending state and CTA children
CheckoutPendingContent->>CheckoutSpinner: render centered spinner while pending
CheckoutPendingContent-->>ProCtaLink: preserve label with pending visibility styling
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 inconclusive)
✅ Passed checks (24 passed)
✨ 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. Comment |
Greptile SummaryThis PR fixes layout shifts on pricing CTAs during checkout loading by keeping the button label in the DOM (visually hidden via
Confidence Score: 5/5Safe to merge — the change is a contained rendering fix with no behavioral side-effects. The change wraps children in a lightweight span and adds absolute positioning for the spinner overlay. The parent anchors already carry No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A["CheckoutButton / ProCtaLink\n(class: pricingActionClassName + relative)"] --> B["CheckoutPendingContent\n{ pending, children }"]
B --> C{pending?}
C -- true --> D["span.invisible{children}\n(keeps layout, hides visually)"]
C -- true --> E["span.absolute.inset-0.flex.items-center.justify-center\n CheckoutSpinner aria-hidden"]
C -- false --> F["span{children}\n(visible, no class)"]
A -- aria-busy={pending} --> G["Screen reader: element is loading"]
Reviews (3): Last reviewed commit: "test pricing checkout spinner presence" | Re-trigger Greptile |
| describe("checkout loading content", () => { | ||
| test("keeps the label in layout and centers the pending spinner", () => { | ||
| const html = renderToStaticMarkup( | ||
| <CheckoutPendingContent pending>Get Teams</CheckoutPendingContent>, | ||
| ); | ||
|
|
||
| expect(html).toContain('class="invisible"'); | ||
| expect(html).toContain( | ||
| 'class="absolute inset-0 flex items-center justify-center"', | ||
| ); | ||
| expect(html).toContain("Get Teams"); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
The test only exercises
pending=true. A second case for pending={false} would guard against regressions where the spinner leaks into the non-loading state (e.g., if the conditional is accidentally inverted) or the label is accidentally hidden when the button is idle.
| describe("checkout loading content", () => { | |
| test("keeps the label in layout and centers the pending spinner", () => { | |
| const html = renderToStaticMarkup( | |
| <CheckoutPendingContent pending>Get Teams</CheckoutPendingContent>, | |
| ); | |
| expect(html).toContain('class="invisible"'); | |
| expect(html).toContain( | |
| 'class="absolute inset-0 flex items-center justify-center"', | |
| ); | |
| expect(html).toContain("Get Teams"); | |
| }); | |
| }); | |
| describe("checkout loading content", () => { | |
| test("keeps the label in layout and centers the pending spinner", () => { | |
| const html = renderToStaticMarkup( | |
| <CheckoutPendingContent pending>Get Teams</CheckoutPendingContent>, | |
| ); | |
| expect(html).toContain('class="invisible"'); | |
| expect(html).toContain( | |
| 'class="absolute inset-0 flex items-center justify-center"', | |
| ); | |
| expect(html).toContain("Get Teams"); | |
| }); | |
| test("shows the label and no spinner when not pending", () => { | |
| const html = renderToStaticMarkup( | |
| <CheckoutPendingContent pending={false}>Get Teams</CheckoutPendingContent>, | |
| ); | |
| expect(html).not.toContain("invisible"); | |
| expect(html).not.toContain("absolute inset-0"); | |
| expect(html).toContain("Get Teams"); | |
| }); | |
| }); |
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
There was a problem hiding this comment.
Added the complementary pending={false} regression case in c217e75. It verifies the idle label stays visible and no spinner overlay renders.
— Claude Code
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@web/tests/checkout-navigation.test.tsx`:
- Around line 26-28: Update the checkout navigation assertions in the relevant
test cases to check for the spinner’s stable marker or element directly: assert
it is absent in idle output and present in pending output. Retain the existing
positioning-class assertions and the “Get Teams” content check.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3511c874-a9ef-421f-b37c-94fdec57cd4b
📒 Files selected for processing (1)
web/tests/checkout-navigation.test.tsx
Summary
Testing
cd web && bun test tests/checkout-navigation.test.tsx tests/pricing-page.test.tsx tests/app-pricing-page.test.tsxcd web && bun run typecheckcd web && bunx eslint app/components/checkout-navigation.tsx app/[locale]/components/pro-cta-link.tsx tests/checkout-navigation.test.tsxNeed help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Fixes layout shifts in pricing CTAs during checkout by keeping the label in flow and overlaying a centered spinner. Works for both full-size and compact buttons, with tests for pending and idle spinner presence.
CheckoutPendingContentto keep labelsinvisibleand center the spinner; CTA containers are nowrelative.CheckoutButtonandProCtaLinkto use it; addedweb/tests/checkout-navigation.test.tsxto assert label retention, centering classes, and spinner<svg>presence when pending, and absence when idle.Written for commit 31a2015. Summary will update on new commits.
Summary by CodeRabbit