feat(headless): migrate remaining primitives to useRender#9232
Conversation
Introduces a base-ui-style useRender hook: a render prop that accepts a
React element (render={<Link/>}) or a function, with internal ref merging
and state-to-data-attribute mapping. renderElement stays exported for the
phased migration. Migrates Mosaic Box, Heading, Text and the dialog
trigger/popup primitives onto the hook.
Convert the rest of the primitive families (accordion, autocomplete, collapsible, dialog, drawer, file-upload, menu, otp, popover, select, tabs, tooltip) from the renderElement function to the useRender hook. Refs move to useRender's ref param; mounted guards become the enabled param; Composite/CompositeItem render callbacks extract the injected roving-tabindex ref and carry a rules-of-hooks disable justified by floating-ui invoking the callback synchronously during render. renderElement remains exported for the final cleanup PR.
🦋 Changeset detectedLatest commit: a24606c 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: |
|
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 (60)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📝 WalkthroughWalkthroughThe headless primitives replace Estimated code review effort: 4 (Complex) | ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Warning Review ran into problems🔥 ProblemsLinked repositories: Couldn't analyze
Errors logged to '/home/jailuser/git/.git/lfs/logs/20260723T223201.601324587.log'. Errors logged to '/home/jailuser/git/.git/lfs/logs/20260723T223321.746095183.log'. Comment |
Stacked on #9231. Merge that first.
PR2 of the
renderElement→useRendermigration. #9231 added theuseRenderhook and converted Mosaic + a couple representative primitives. This converts every remaining primitive family sorenderElementhas no callers left (final PR deletes it).What changed
58 primitives across accordion, autocomplete, collapsible, dialog, drawer, file-upload, menu, otp, popover, select, tabs, tooltip. Mechanical swap, three transforms:
Refs merge inside the hook. Per-site
useMergeRefsdisappears.mountedguard becomesenabled. Hook stays unconditional (returns null).Composite/CompositeItem callbacks. floating-ui invokes the
rendercallback synchronously during its own render (seerenderJsx), souseRenderthere is runtime-safe but tripsreact-hooks/rules-of-hooks— carries a justified disable. The callback's injected roving-tabindex ref is extracted to therefparam (leaving it in props would let the hook's merged ref clobber it and break keyboard nav).Ref safety
useRenderoverwrites anyrefleft inpropswith its own merged ref. So every ref was routed to therefparam, nothing left in props. Roving-focus/ref-forwarding tests cover the Composite cases.Verified
@clerk/headless: 601 tests pass, typecheck clean, eslint clean (zero warnings)renderElementcallers remain insrc/primitivesEmpty changeset:
@clerk/headlessis private.