Uh oh!
There was an error while loading. Please reload this page.
feat(ui): give the approval gate a surface and a confirmation beat (#290) - #488
Conversation
Warning Review limit reached
Next review available in:34 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
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 |
This pull request has been ignored for the connected project Preview Branches by Supabase. |
Deploying with |
| Status | Name | Latest Commit | Preview URL | Updated (UTC) |
|---|---|---|---|---|
| ✅ Deployment successful! View logs | frontend-staging | 30d38f7 | Commit Preview URL Branch Preview URL | Jul 31 2026, 03:08 AM |
Jose-Gael-Cruz-Lopez
commented
Jul 31, 2026
Automated review pass (Claude Code). Verified findings only — overall this is a careful, well-tested change: scope matches #290 exactly, middleware gating is untouched ( Should fix before merge
Minor
Follow-up worth an issue (pre-existing, not this PR): nothing on Verdict: ready to merge once the email-copy question is resolved. |
) Sign-up ENDS on /pending, and the page was 42 lines with no container: a sprout, an h1, a paragraph and a button floating directly on a radial gradient. Beta glow into silence, with no "you're in" moment anywhere in it. The content now sits on a real `.card` surface (which supplies bg/border/ radius/shadow but no padding — that is the caller's job, so the card sets `var(--pad-lg)`), and the screen plays a one-shot confirmation beat: the sapling draws itself, then the message steps in behind it. The beat is CSS, not JS, and that is the point. globals.css already carries a global prefers-reduced-motion reset, so a CSS entrance is automatically safe where a JS-driven one would have to re-implement that guard. It reuses the motion vocabulary that already exists (`fade-in`/`slide-up` keyframes, the `.anim-d*` delay utilities) rather than inventing a parallel one; the new `.pending-*` rules are declared ABOVE `.anim-d*` on purpose, since the animation shorthand resets animation-delay and the delay utilities have to win. The sprout's stroke uses `pathLength={1}` so the draw keyframe can dash it without measuring, and its three subpaths run stem-then-veins so it reads as the sapling growing rather than a generic fade. Everything settles by ~540ms, single pass, no loop. Copy does the confirmation work the layout can't: "Your account is ready" states what actually happened, and "We'll email you" names the channel the old "We'll reach out" left vague. Both E2E anchors — `pending-gate` and `pending-signout` — are unchanged, and the new page.test.tsx pins them, the card surface, and the beat's finiteness so a future pass can't quietly reintroduce an infinite animation. part of #290 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Restore the original copy. Issue #290's proposal says "Keep the copy" in so many words, and the previous revision rewrote both the heading and the body. The rewrite may still be worth making, but it is a separate call and not one this PR was scoped to take. Make the sprout actually sequence. The stem and the two leaf veins were three subpaths of ONE path sharing a single dash animation, and a dash pattern restarts its phase at every `M` — so all three drew simultaneously, which is the opposite of what the comment claimed. Verified in headless Chromium during review. They are now two separate paths on staggered delays, so the stem really does lead and the leaves follow. Split animation-fill-mode out of the shorthand. f4ac696 did exactly this to .fade-up ("split animation-fill-mode both so stagger works with CSS var timing") 20 minutes after the stagger utilities shipped, and every rule added since has avoided var()-timing plus a trailing keyword in one shorthand. It resolves correctly in Chromium — which is the only engine the e2e lane runs — but this file's own history says not to write it that way. Beat now settles at ~560ms (was ~540ms), still inside the issue's 600ms cap. part of #290 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bce12e3 to
30d38f7CompareAndresL230
commented
Jul 31, 2026
Local e2e cycle — greenFull cycle inside one Gates: Note there is no journey that drives |
Sign-up ends on
/pending, and the page was 42 lines with no container — a sprout, an<h1>, a paragraph and a button floating directly on a radial gradient. Beta glow into silence, with no "you're in" moment anywhere in it.What changed
A surface. The content now sits on a real
.card..cardsupplies bg/border/radius/shadow but no padding — that's the caller's job — so the card setsvar(--pad-lg).A confirmation beat. The sapling draws itself once, then the message steps in behind it. Everything settles by ~540ms: single pass, no loop.
Copy that does the confirmation work the layout can't. "Your account is ready" states what actually happened; "We'll email you" names the channel that the old "We'll reach out" left vague.
Why CSS and not JS
globals.cssalready carries a globalprefers-reduced-motionreset, so a CSS entrance is automatically safe — a JS-driven one would have to re-implement that guard itself.It reuses the motion vocabulary that already exists (the
fade-in/slide-upkeyframes and the.anim-d*delay utilities) instead of inventing a parallel one. The new.pending-*rules are declared above.anim-d*deliberately: theanimationshorthand resetsanimation-delay, so the delay utilities have to come later to win.The sprout's stroke carries
pathLength={1}so the draw keyframe can dash it without measuring, and its three subpaths run stem-then-veins — so it reads as the sapling growing rather than a generic fade.Anchors
data-testid="pending-gate"anddata-testid="pending-signout"are unchanged. Both are already registered indocs/frontend-testids.md(surface table and inventory) andapp/pending/page.tsxis already in the eslint enforcement list, so neither half needed updating.src/app/pending/page.test.tsx(new, red-first) pins the anchors, the sign-out behaviour, the card surface, and the beat's finiteness — it fails if a future pass introduces aninfiniteanimation or drops a fill mode from a delayed step.Gates
tsc --noEmit— cleannpm run lint— 0 errors (36 pre-existing warnings)npx vitest run— 56 files, 403 tests passedpart of #290