Skip to content

fix(app): stop left-nav rail tooltips flickering on hover (CS-773)#3502

Merged
tofikwest merged 2 commits into
mainfrom
tofik/cs-773-nav-tooltip-glitch
Jul 24, 2026
Merged

fix(app): stop left-nav rail tooltips flickering on hover (CS-773)#3502
tofikwest merged 2 commits into
mainfrom
tofik/cs-773-nav-tooltip-glitch

Conversation

@tofikwest

@tofikwest tofikwest commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Problem (CS-773)

Hovering the far-left product rail icons (Compliance, Trust, Security, Settings, Admin) showed each tooltip for ~0.1s, then it vanished while the cursor was still over the icon.

Root cause

ShellRailNavItem passed a label-derived id (app-shell-rail-<label>) to the design system's AppShellRailItem.

AppShellRail re-renders the same rail items into the always-mounted mobile drawer (via setRailContent), so each id lands on two DOM elements. The design system forwards that id to the Base UI tooltip trigger, so both copies register the same deterministic trigger id and collide in Base UI's floating tree. When the desktop tooltip opens, Base UI's closeOnActiveTriggerUnmount logic treats the active trigger as unmounted and closes the tooltip one microtask later — the flash.

Notably, this is not caused by the <Link>/<a> nesting (a common first guess): a bare tooltip trigger inside an anchor stays open fine. The trigger is the duplicate id.

Fix

Don't set an explicit id on the rail items. The id was unused anywhere in comp or comp-private (only referenced at its own definition site). Without it, the design system generates a unique id per instance, so the two copies no longer collide.

  • Extracted ShellRailNavItem into its own file so it can be unit-tested.
  • Added a regression test asserting rail items carry no hard-coded / duplicate ids (fails with the old id, passes with the fix).

How it was verified

  • Reproduced the flash with the real design system components in a headless browser: duplicate id → flash 5/5; no id → stable 5/5.
  • Confirmed the exact Base UI close path (closeOnActiveTriggerUnmount) via temporary runtime instrumentation (reverted).
  • ShellRailNavItem.test.tsx: 2/2 passing; verified it fails when the id is reintroduced.
  • ESLint clean; no new TypeScript errors in the changed files (the repo's pre-existing red is in unrelated test fixtures).

Follow-up (design system, out of scope here)

AppShellRailItem forwarding a consumer id straight to the Base UI tooltip trigger — combined with AppShellRail duplicating rail content into the mobile drawer — means any consumer that sets an id hits this bug. Worth hardening upstream (e.g., don't use a consumer id as the trigger id, or don't remount identical triggers in the drawer).


Summary by cubic

Fixes tooltip flicker in the left nav rail (CS-773). Removes hard-coded ids from rail items so the desktop rail and mobile drawer no longer collide, keeping tooltips open on hover.

  • Bug Fixes
    • Extracted ShellRailNavItem; stopped passing id to AppShellRailItem from @trycompai/design-system.
    • Added regression tests to prevent hard-coded/duplicate rail-item ids and to verify unique ids across rail and mobile drawer (prettier-format only).

Written for commit f177919. Summary will update on new commits.

Review in cubic

The far-left product rail (Compliance, Trust, Security, Settings, Admin)
showed each icon's tooltip for ~0.1s on hover, then it vanished while the
cursor was still over the icon.

Root cause: ShellRailNavItem passed a label-derived `id`
(`app-shell-rail-<label>`) to the design system's AppShellRailItem.
AppShellRail re-renders the same rail items into the always-mounted mobile
drawer, so each `id` ends up on two DOM elements. The design system forwards
that `id` to the Base UI tooltip trigger, so the two copies register the same
deterministic trigger id and collide in Base UI's floating tree. When the
desktop tooltip opens, Base UI's closeOnActiveTriggerUnmount logic treats the
active trigger as unmounted and closes the tooltip a microtask later — the
flash.

Fix: don't set an explicit `id` on the rail items. The `id` was unused
anywhere in either repo, and without it the design system generates a unique
id per instance, so the two copies no longer collide. Extracted
ShellRailNavItem into its own file so it can be unit-tested; added a
regression test asserting no hard-coded / duplicate rail-item ids.

Verified by reproducing the flash with the real design system components in a
headless browser (dup id => flash 5/5; no id => stable 5/5) and confirming the
Base UI close path via runtime instrumentation.
@linear

linear Bot commented Jul 24, 2026

Copy link
Copy Markdown

CS-773

@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
app Ready Ready Preview, Comment Jul 24, 2026 5:58pm
comp-framework-editor Ready Ready Preview, Comment Jul 24, 2026 5:58pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
portal Skipped Skipped Jul 24, 2026 5:58pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

cubic analysis

All reported issues were addressed across 3 files

Linked issue analysis

Linked issue: CS-773: [BUG] Left Side Menu Navigation Tooltip Is Glitching during onHover State

Status Acceptance criteria Notes
Tooltips remain visible while the mouse cursor hovers over left-side rail icons (no flicker) The root cause (duplicate, label-derived id forwarded to the tooltip trigger) was removed: the rail item no longer receives an explicit id, preventing duplicate trigger ids and the Base UI close-path that caused the flash. The PR description documents headless reproduction showing flicker with the old id and stability with the fix.
Regression tests added to ensure no hard-coded/duplicate rail-item ids and unique ids across desktop rail and mobile drawer A new test file asserts there is no hard-coded label-derived id and that the mirrored rail items do not produce duplicate ids, preventing the regression.

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread apps/app/src/app/(app)/[orgId]/components/ShellRailNavItem.test.tsx Outdated
@vercel
vercel Bot temporarily deployed to Preview – portal July 24, 2026 17:55 Inactive
@tofikwest
tofikwest merged commit e7ce85c into main Jul 24, 2026
11 checks passed
@tofikwest
tofikwest deleted the tofik/cs-773-nav-tooltip-glitch branch July 24, 2026 18:01
claudfuen pushed a commit that referenced this pull request Jul 24, 2026
## [3.108.1](v3.108.0...v3.108.1) (2026-07-24)

### Bug Fixes

* **app:** stop left-nav rail tooltips flickering on hover (CS-773) ([#3502](#3502)) ([e7ce85c](e7ce85c))
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.108.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants