Skip to content

feat(cli): animate the "Next steps" header with a mauve reflex sweep#322

Merged
rafa-thayto merged 3 commits into
mainfrom
feat/next-steps-gradient-animation
Jun 11, 2026
Merged

feat(cli): animate the "Next steps" header with a mauve reflex sweep#322
rafa-thayto merged 3 commits into
mainfrom
feat/next-steps-gradient-animation

Conversation

@rafa-thayto

Copy link
Copy Markdown
Contributor

Summary

Gives the Next steps header a subtle one-shot animation, inspired by Claude Code's animated keywords.

  • Renders the "Next steps" header in a dusty mauve (#bd84b0) and sweeps a white reflex highlight across it once (~450ms), then settles on the flat color.
  • Applies to the three commands that show a Next steps header: clerk auth login, clerk link, and the clerk deploy wizard (via outro(string[]) and finishDeploy).
  • The 11 commands that use printNextSteps (bare lines, no header) are unchanged.

New lib/gradient.ts carries the color math (hslToRgb, rgbTo256), the shineText renderer (flat base + moving reflex), and animateHeader (the one-shot sweep). outro becomes async so callers await the sweep before the steps print and before the post-action update notification fires.

Behavior & safety

  • Gated to interactive TTYs only. Piped output, CI, and NO_COLOR get the plain fallback styling with no cursor control or carriage returns, so logs stay clean. Agents never see it (isHuman() gate upstream).
  • Truecolor with a 256-color fallback chosen via COLORTERM.
  • Cursor restore backstop: a process.on("exit") listener re-shows the cursor if Ctrl-C lands mid-sweep (the SIGINT handler's process.exit skips the finally).
  • FORCE_COLOR parsed correctly so 0/false/"" don't override NO_COLOR.

Test plan

  • bun run typecheck, bun run lint, bun run format:check — all clean.
  • bun test on touched files: gradient (24), spinner (1), deploy/index (58), deploy/copy (13), link (55), auth/login (17) — all pass.
  • gradient.test.ts covers the color math, flat-vs-reflex rendering, the empty/whitespace guard, the non-interactive fallback, cursor hide/restore balance, and the full NO_COLOR × FORCE_COLOR gating matrix.
  • Manual: ran the sweep on an interactive TTY (mauve base + white reflex, settles flat); verified the exit guard restores the cursor on a mid-sweep process.exit.

A multi-agent audit confirmed which next-steps surfaces are animated vs not, and an adversarial bug hunt surfaced the cursor-restore and FORCE_COLOR issues that are fixed here.

@changeset-bot

changeset-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9d98b89

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
clerk Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a4dc7494-298c-4d0c-a07e-586ee8411104

📥 Commits

Reviewing files that changed from the base of the PR and between 01cf139 and 9d98b89.

📒 Files selected for processing (3)
  • packages/cli-core/src/lib/gradient.ts
  • packages/cli-core/src/lib/spinner.test.ts
  • packages/cli-core/src/lib/spinner.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/cli-core/src/lib/spinner.ts

📝 Walkthrough

Walkthrough

Adds a new gradient module that renders a per-character “shine” effect and an async animateHeader function gated on TTY/color environment. spinner.outro is made async and awaits animateHeader for array-style next-steps; deploy, auth login, and link commands are updated to use/await the animated header, and deploy’s copy is split into header and body helpers. Tests and a changeset entry are included.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% 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 describes the main feature: animating the 'Next steps' header with a mauve reflex sweep effect.
Description check ✅ Passed The description clearly explains the implementation, behavior, safety measures, and testing approach for the animated Next steps header feature.
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.


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.

@coderabbitai coderabbitai 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.

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 `@packages/cli-core/src/lib/gradient.ts`:
- Around line 58-61: The space branch in the gradient rendering (the if (ch ===
" ") block that appends to out) currently appends the space while the previous
foreground color is still active, causing spaces to inherit color; modify this
branch in the function containing variables ch and out so it resets or clears
the current foreground color (use whatever foreground-reset sequence or helper
your codebase uses) before appending the space and then continue without
reapplying the color—i.e., emit a foreground-reset, append the space to out, and
return.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8fc59a77-9a4f-4bc5-b961-bccde7575d95

📥 Commits

Reviewing files that changed from the base of the PR and between 4bd85a8 and 120c8bc.

📒 Files selected for processing (8)
  • .changeset/next-steps-gradient-animation.md
  • packages/cli-core/src/commands/auth/login.ts
  • packages/cli-core/src/commands/deploy/copy.ts
  • packages/cli-core/src/commands/deploy/index.ts
  • packages/cli-core/src/commands/link/index.ts
  • packages/cli-core/src/lib/gradient.test.ts
  • packages/cli-core/src/lib/gradient.ts
  • packages/cli-core/src/lib/spinner.ts

Comment thread packages/cli-core/src/lib/gradient.ts
Render the "Next steps" header in a dusty mauve and sweep a white reflex
highlight across it once after `clerk deploy`, `clerk link`, and
`clerk auth login`, then settle on the flat color.

The animation only runs on an interactive color TTY; piped output, CI, and
NO_COLOR fall back to plain styling. A process exit guard restores the cursor
if Ctrl-C lands mid-sweep, and FORCE_COLOR is parsed so 0/false/"" don't
override NO_COLOR.
…eText

Spaces were inheriting the previous character's foreground color because
the space branch appended the character while the ANSI color escape was
still active. Now resets to the default foreground color (\x1b[39m) before
the space is output, and also awaits outro() in withGutter since outro is
now async.

Addresses CodeRabbit review comment on PR #322.
@rafa-thayto rafa-thayto force-pushed the feat/next-steps-gradient-animation branch from 120c8bc to 01cf139 Compare June 9, 2026 12:53

@coderabbitai coderabbitai 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.

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 `@packages/cli-core/src/lib/gradient.ts`:
- Around line 113-139: The animateHeader function is writing directly via log.ui
(in the initial fallback path and inside the animation loop) which can conflict
with callers that provide a custom UI writer; update AnimateHeaderOptions to
accept a ui writer (e.g., ui: (s: string) => void) and replace all direct log.ui
calls in animateHeader with that ui writer (use the provided ui for the
non-interactive/fallback branch, each frame write, and the final line including
the newline). Keep existing option defaults (frames, intervalMs) and ensure the
string payloads (including the \r\x1b[K sequences and newline) are passed
unchanged to the supplied ui function.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e867f4e1-7b4a-42e3-acb0-b5f096a75477

📥 Commits

Reviewing files that changed from the base of the PR and between 120c8bc and 01cf139.

📒 Files selected for processing (8)
  • .changeset/next-steps-gradient-animation.md
  • packages/cli-core/src/commands/auth/login.ts
  • packages/cli-core/src/commands/deploy/copy.ts
  • packages/cli-core/src/commands/deploy/index.ts
  • packages/cli-core/src/commands/link/index.ts
  • packages/cli-core/src/lib/gradient.test.ts
  • packages/cli-core/src/lib/gradient.ts
  • packages/cli-core/src/lib/spinner.ts
✅ Files skipped from review due to trivial changes (1)
  • .changeset/next-steps-gradient-animation.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • packages/cli-core/src/commands/auth/login.ts
  • packages/cli-core/src/commands/link/index.ts
  • packages/cli-core/src/commands/deploy/copy.ts
  • packages/cli-core/src/lib/gradient.test.ts
  • packages/cli-core/src/commands/deploy/index.ts

Comment thread packages/cli-core/src/lib/gradient.ts
Add a `write` option to `AnimateHeaderOptions` (defaults to `log.ui`) so
callers can direct header output to the same stream as the surrounding UI.
Pass `writeUi` from `spinner.ts` so the "Next steps" header lands on the
active UI output stream instead of bypassing it via `log.ui` directly.

Fix the spinner test to properly await the now-async `outro` call inside
the stderr capture helper.
@rafa-thayto rafa-thayto merged commit ca44851 into main Jun 11, 2026
10 checks passed
@rafa-thayto rafa-thayto deleted the feat/next-steps-gradient-animation branch June 11, 2026 20:50
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.

2 participants