fix(ui): render the Avatar fallback as a blank placeholder - #9398
Conversation
Avatar.Fallback still takes children, but it no longer paints them: an entity without a picture reads as an absent image rather than as two letters. The children move into an `avatar-fallback-content` slot held at `visibility: hidden`, which takes them out of the page, the accessibility tree, and the tab order at once while leaving hit-testing alone, so a consumer can style them back into view. The fallback pulses only while an image is genuinely resolving (`data-pending`); someone who has no picture is not waiting on anything, so their mark holds still.
🦋 Changeset detectedLatest commit: d013999 The changes in this PR will be included in the next version bump. This PR includes changesets to release 0 packagesWhen changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types 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 |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
@clerk/astro
@clerk/backend
@clerk/chrome-extension
@clerk/clerk-js
@clerk/electron
@clerk/electron-passkeys
@clerk/eslint-plugin
@clerk/expo
@clerk/expo-google-signin
@clerk/expo-passkeys
@clerk/express
@clerk/fastify
@clerk/hono
@clerk/localizations
@clerk/nextjs
@clerk/nuxt
@clerk/react
@clerk/react-router
@clerk/shared
@clerk/tanstack-react-start
@clerk/testing
@clerk/ui
@clerk/upgrade
@clerk/vue
commit: |
API Changes Report
Summary
No API Changes DetectedAll packages have stable APIs with no detected changes. Report generated by Break Check Last ran on |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository YAML (base), Organization UI (inherited) Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughAvatar fallbacks now hide fallback content by default and wrap it in a dedicated content slot. The fallback exposes pending state while an image request remains unresolved, applies a pulse animation, and stops pulsing after an error. Tests cover pending, error, and no-source states. A pending-image endpoint and story demonstrate the behavior. Avatar documentation and user-button comments were updated. An empty Changeset file was added. Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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 @.changeset/mosaic-avatar-skeleton-fallback.md:
- Around line 1-2: Add an `@clerk/ui` changeset entry in
mosaic-avatar-skeleton-fallback.md with the appropriate release bump and a
concise release note describing the updated default Avatar.Fallback output; do
not leave the changeset empty.
In `@packages/swingset/src/app/api/pending-image/route.ts`:
- Around line 17-29: Add unit tests covering the GET route’s delayed response
contract: use fake timers to verify normal resolution after HOLD_MS and
request-signal cancellation before the delay completes, and assert both PNG
content type and no-store cache-control headers for the returned Response.
In `@packages/ui/src/mosaic/components/avatar/avatar.styles.ts`:
- Around line 5-7: Reduce comments across the listed sites to only terse
non-obvious rationale: in avatar.styles.ts lines 5-7 and 53-58, replace each
explanation with one concise rationale line, and remove lines 63-64; remove
narration at avatar.test.tsx lines 16-18, 228-230, and 261-262; shorten the
accessibility and avatarName comments in user-button.view.tsx lines 135-136 and
186-188, remove lines 157-158 and 683, and remove narration in
user-button.view.test.tsx lines 653-654; shorten the route-purpose and cache
comments in pending-image/route.ts lines 1-4 and 13-14, remove line 7; and
remove the story narration in avatar.stories.tsx lines 49-50. Preserve code
behavior and leave comments only where they explain non-obvious rationale.
🪄 Autofix
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: Repository YAML (base), Organization UI (inherited)
Review profile: CHILL
Plan: Pro Plus
Run ID: ea7ed4b3-ea6a-424f-80b8-5477ae8450cd
📒 Files selected for processing (9)
.changeset/mosaic-avatar-skeleton-fallback.mdpackages/swingset/src/app/api/pending-image/route.tspackages/swingset/src/stories/avatar.mdxpackages/swingset/src/stories/avatar.stories.tsxpackages/ui/src/mosaic/components/avatar/avatar.styles.tspackages/ui/src/mosaic/components/avatar/avatar.test.tsxpackages/ui/src/mosaic/components/avatar/avatar.tsxpackages/ui/src/mosaic/user-button/__tests__/user-button.view.test.tsxpackages/ui/src/mosaic/user-button/user-button.view.tsx
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
clerk/clerk_go(manual)clerk/dashboard(manual)clerk/accounts(manual)clerk/backoffice(manual)clerk/clerk(manual)clerk/clerk-docs(manual)clerk/cloudflare-workers(manual)clerk/cli(auto-detected)clerk/clerk-ios(auto-detected)clerk/clerk-android(auto-detected)
Description
Avatar.Fallbackkeeps its API — it still takes children, initials or an icon — but it no longer paints them. The children move into a newavatar-fallback-contentslot held atvisibility: hidden, so what's left is the neutral fill on its own.visibilityis the one property that takes the content out of the page, the accessibility tree, and the tab order together, and unlikeinertit leaves hit-testing alone, so a click still reaches the button row these sit in. A consumer who wants the initials back overrides that one slot.The fallback also pulses now, but only while an image is genuinely on its way (
status === 'loading', reflected asdata-pending). Someone who simply has no picture is not waiting on anything, so their mark holds still rather than pulsing for as long as it's on screen. The pulse matchesskeleton.tsx's timing and drops tononeunderprefers-reduced-motion.user-button.view.tsxis comments only — it still computes and passesinitials(name), so the name is there for anyone who styles the slot back into view.Swingset gets a
Pendingexample./api/pending-imageholds its response for a minute withcache-control: no-store, so the pulse is the component's own status rather than a pinned attribute.Checklist
pnpm testruns as expected.pnpm buildruns as expected.Type of change