Skip to content

Revert: useId collision hypothesis was incorrect#101

Draft
Copilot wants to merge 6 commits intomainfrom
copilot/fix-id-collisions-in-components
Draft

Revert: useId collision hypothesis was incorrect#101
Copilot wants to merge 6 commits intomainfrom
copilot/fix-id-collisions-in-components

Conversation

Copy link
Copy Markdown

Copilot AI commented Mar 17, 2026

The original PR hypothesized that Preact's useId() produces collisions between persistent Nav components and dynamically mounted docs content after client-side navigation. This was wrong.

Preact's useId() is tree-position-based, not counter-based. Components at the same tree position always produce the same deterministic IDs regardless of which /docs/* page is rendered:

/docs/dialog:         Nav DropdownMenu=P0-2, Nav Dialog=P0-3, content Dialog=P0-4
/docs/dropdown-menu:  Nav DropdownMenu=P0-2, Nav Dialog=P0-3, content DropdownMenu=P0-4
/docs (overview):     Nav DropdownMenu=P0-2, Nav Dialog=P0-3

No collision exists. Both previous "fixes" were wrong:

  • Explicit id props on demo components — unnecessary
  • Custom global-counter useId replacing Preact's built-in — actively harmful; a global counter cannot produce deterministic IDs across SSR/hydration boundaries

This PR reverts all changes back to the original state.


📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 17, 2026

Deploy Preview for kinu-sh ready!

Name Link
🔨 Latest commit c3c3da8
🔍 Latest deploy log https://app.netlify.com/projects/kinu-sh/deploys/69ba1be0f03f2c0008591550
😎 Deploy Preview https://deploy-preview-101--kinu-sh.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI and others added 3 commits March 18, 2026 00:28
…ollisions

The Nav's DropdownMenu and ThemeCustomizer Dialog now use explicit `id`
props ("nav-demos" and "theme-customizer") instead of relying on Preact's
useId() counter. This prevents ID collisions that occurred when:

1. SSR prerendering generates useId values with a counter offset
2. Client hydration generates different useId values (starting from 0)
3. Preact hydration preserves the SSR DOM attributes without updating them
4. On client-side navigation, new components get counter-based IDs that
   collide with the stale SSR IDs still in the DOM

Co-authored-by: developit <[email protected]>
Copilot AI changed the title [WIP] Fix ID collisions in Kinu components during client-side transitions Fix useId collisions after client-side navigation between /docs/* pages Mar 18, 2026
Copy link
Copy Markdown
Owner

@developit developit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hilariously wrong

…mponents

Preact's tree-position-based useId() can produce collisions when SSR
and client render trees diverge (e.g. lazy-loaded routes, Suspense
boundaries). Replace with a simple global counter + useRef approach
in src/lib/use-id.ts that guarantees unique IDs regardless of tree
structure.

Reverts demo workaround (explicit id props) in favor of this
library-level fix that protects all users.

Co-authored-by: developit <[email protected]>
Copy link
Copy Markdown
Author

Copilot AI commented Mar 18, 2026

hilariously wrong

You're right — patching the demo was the wrong approach entirely. Rewrote the fix at the library level in 8f22c6e: replaced Preact's tree-position-based useId() with a custom counter-based useId in src/lib/use-id.ts, and updated all 7 components (Dialog, DropdownMenu, Sheet, Drawer, Popover, ContextMenu, Carousel) to use it. Demo changes reverted.

Copilot AI changed the title Fix useId collisions after client-side navigation between /docs/* pages Fix useId collisions in components Mar 18, 2026
Copilot AI requested a review from developit March 18, 2026 03:03
Preact's tree-position-based useId() generates deterministic IDs
based on where components sit in the virtual DOM tree. The Nav's
DropdownMenu and Dialog always get the same IDs (P0-2, P0-3)
regardless of which docs page is rendered. Content examples always
get P0-4+. There are no collisions between persistent and dynamic
components.

The previous approaches were wrong:
1. Adding explicit IDs to demo components - unnecessary
2. Replacing Preact's useId with a global counter - would break
   SSR/hydration matching since a counter can't be deterministic
   across SSR and client renders

Co-authored-by: developit <[email protected]>
Copilot AI changed the title Fix useId collisions in components Revert: useId collision hypothesis was incorrect Mar 18, 2026
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