githubnext/chopinPublic

Let's compose rich plans together

Hide tooltips over the menus they open #334

MergedMaggieAppletonmerged 2 commits intomainfromrefs/pull/334/head
  1. MA

    ## Why Clicking an icon control (for example "Mention docs") left its tooltip drawn over the picker it opened. The fade also used native `ease-out`, and moving across a toolbar re-waited 400ms for every tooltip.

    ## What changed - A tooltip hides at once (no fade) on pointerdown and when its trigger gets `aria-expanded="true"`, and stays hidden until the pointer leaves that trigger. - A 300ms warm window: after a tooltip was visible, the next one opens with no delay and no fade-in. Otherwise the 400ms open delay is unchanged. - `icon-tooltip.css` uses `var(--ease-out)`; the preserved-value exception for the native curve is removed. - Only `hide`, `enter` and the pointerdown listener changed in `icon-tooltip.tsx`, so it does not touch the lines #299 edits (`pointerOver`, `focusIn`, `scroll`).

    ## Screenshots Before: tooltip over the open picker. ![before](./before-menu-open.png)

    After: no tooltip. ![after](./after-menu-open.png)

    ## Testing - `bun run ci`, `bun run types`: pass. - New e2e cases in `e2e/shell.e2e.ts`: press hides the tooltip and it stays hidden after 600ms with the pointer still, then shows again after leave and return; keyboard focus shows it and a popup trigger expanding hides it; a second tooltip opens within 200ms with `data-instant`. - PR CI (format/lint/types/tests, container, e2e): all pass. - Manual headless Chromium run against the fake server, before and after (see screenshots).

    🤖 Generated with [Claude Code](https://claude.com/claude-code)

    ![before](https://github.com/user-attachments/assets/ca714b1d-d2db-4f00-99c9-8094b6d49b51)

    ![after](https://github.com/user-attachments/assets/ffb91641-2b3c-4552-9c7b-20a0df3eacee)

  2. MA
    Author

    **Review:** Changes needed

    Code read end to end (not run in a browser; CI was still pending when I posted). The logic is sound; the one blocker is test coverage.

    **Blocking** 1. No test covers the new behaviour. The PR touches only `icon-tooltip.css/.tsx` and the contract JSON; `icon-tooltip.test.ts` only covers `tooltipText`. The pointerdown listener and the `MutationObserver` are DOM wiring that `bun test` cannot exercise, and "local e2e suspended" means nothing verified it in CI-equivalent form. Add a Playwright case (next to the existing `[data-icon-tooltip]` cases in `e2e/shell.e2e.ts` or `e2e/toolbar.e2e.ts`) that: hovers an icon button that opens a menu or picker (e.g. "Mention docs"), clicks it, asserts `[data-icon-tooltip]` is hidden immediately and still hidden after >400ms while the pointer stays put, then moves the pointer off and back on after closing the menu and asserts the tooltip can show again. A second case for the keyboard path (below) is worth adding.

    **Non-blocking** 2. `icon-tooltip.tsx` (`expandedChange`): when a trigger is opened by keyboard (focus tooltip visible, Enter), it hides but `pressed` is not set, since that only happens when `target === hovered`. That is correct, but untested. Please assert in the e2e that Tab-focusing a toolbar button still shows its tooltip, and that Enter on an expandable trigger hides it. 3. `hide()` sets `warmUntil` whenever the tooltip was visible, including on scroll, resize, Escape and instant press-hides. After Escape on a focused button, Tab to the next shows its tooltip with no delay. Probably fine, but only pointer-leave arguably warrants the warm window. Optional. 4. Warm path calls `show()` synchronously and `show()` removes `data-instant`, so the warm tooltip still fades in over `--duration-fast`. That matches "no 400ms wait" but not the "opens instantly" wording in the description. Fine; just keep the wording accurate.

    **Checked, no issue** - MutationObserver: `attributeFilter: ["aria-expanded"]` on `document.body` subtree is cheap, and `observer.disconnect()` runs in cleanup. `resize` is now a stable reference, so the listener is removed correctly (the previous `hide` reference would have broken once `hide` took an argument). - Touch: `pointerOver` ignores `pointerType === "touch"`, so the new pressed state never blocks anything on touch; `pressed` clears on the trailing `pointerout`. The changed lines (`hide`, `enter`, `pointerDown`, `expandedChange`, `pointerOut` clearing) do not overlap #299's `pointerOver`/`focusIn`/`scroll` hunks, though `pointerOut` is adjacent, so expect a trivial textual conflict whichever lands second. - Reduced motion: the existing `@media (prefers-reduced-motion)` rule still sets `transition: none`; `[data-instant]` is order-safe. - Tokens: `var(--ease-out)` replaces the native curve and the preserved-value exception is correctly removed. Conventions (tabs, `let`, minimal comments) are fine.

  3. MA
    Author

    Addressed in 61d29ab8: three e2e cases in `e2e/shell.e2e.ts` (press then stay hidden past 400ms, shows again after leave and return; keyboard focus shows and an expanded popup trigger hides; warm second tooltip is instant). Warm path now sets `data-instant`, so no fade-in. Suppression now applies only to `aria-haspopup` triggers, so the sidebar toggle (aria-expanded, no popup) keeps its tooltip. Body Testing updated. CI is green (lint/types/tests, container, e2e).

  4. MaggieAppletonhead-ref-force-pushed 7c2391cdf66flast month on GitHub

  5. MaggieAppletonmerged 38ec7b58650elast month on GitHub

  6. MaggieAppletonclosedlast month on GitHub

  7. MaggieAppletonhead-ref-deletedlast month on GitHub