Skip to content

chore: Update ToolTip to default to be dismissed after parent target is clicked#3388

Open
LinKCoding wants to merge 14 commits into
mainfrom
kl-gmt-1666-gamut-tooltips-blur
Open

chore: Update ToolTip to default to be dismissed after parent target is clicked#3388
LinKCoding wants to merge 14 commits into
mainfrom
kl-gmt-1666-gamut-tooltips-blur

Conversation

@LinKCoding

@LinKCoding LinKCoding commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Overview

Adds close-on-click behavior to ToolTip and IconButton tooltips. By default, hovering over an IconButton shows its tooltip — clicking the button now immediately hides it, requiring the cursor to leave and re-enter before it reappears. An opt-out (closeOnClick={false}) supports patterns like copy → copied where the tooltip should stay visible after the click.

  • Added closeOnClick prop to ToolTipProps and TipPlacementComponentProps
  • Implemented suppress/unsuppress state in InlineTip using a CSS suppress state on ToolTipWrapper that overrides the base :hover styles by injection order
  • Used data-tooltip-body attribute to target only the tooltip body element in the CSS selector, avoiding interference with TargetContainer
  • Switched show/hide CSS from :focus-within to :has(:focus-visible) to prevent mouse-click focus from keeping the tooltip alive
  • Added relatedTarget instanceof Node guard on onMouseEnter/onMouseLeave to skip synthetic events fired when tooltip visibility changes
  • IconButton now passes closeOnClick by default; override via tipProps={{ closeOnClick: false }}
  • Extended FloatingTip to forward closeOnClick to the inner tip
  • Updated MenuItem tooltip element to align with blur-close behavior
  • Added unit tests to IconButton.test.tsx covering closeOnClick scenarios
  • Added CloseOnClick story to both IconButton.stories.tsx and ToolTip.stories.tsx with floating/inline variants; updated corresponding MDX docs

PR Checklist

  • Related to designs:
  • Related to JIRA ticket: GMT-1666
  • Version plan added/updated (or not needed)
  • I have run this code to verify it works
  • This PR includes unit tests for the code change
  • This PR includes testing instructions tests for the code change
  • The alpha package of this PR is passing end-to-end tests in all relevant Codecademy repositories

Testing Instructions

Don't make me tap the sign.

  1. Open the IconButton story in Storybook and hover over any IconButton — the tooltip should appear. Click the button; the tooltip should disappear immediately even though the cursor is still hovering. Move the cursor off and back on — the tooltip should reappear normally.
  2. Open the IconButton › Close on Click story. Verify the first two buttons (floating and inline) close on click, and the last two (floating and inline with closeOnClick={false}) stay open after clicking.
  3. Open the ToolTip › Close on Click story. Verify the same four-button pattern using StrokeButton wrapped in <ToolTip> directly — two close on click, two stay open.
  4. Tab to an IconButton using keyboard only — the tooltip should appear on :focus-visible and should not be suppressed by a prior mouse click.
  5. Check it with VO
  6. Finish and do a celebratory dance

PR Links and Envs

Repository PR Link
Monolith Monolith PR
Mono Mono PR

@nx-cloud

nx-cloud Bot commented Jun 29, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 061b086


☁️ Nx Cloud last updated this comment at 2026-07-08 20:35:36 UTC

@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.11765% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.10%. Comparing base (c9200cc) to head (061b086).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
packages/gamut/src/Tip/shared/FloatingTip.tsx 80.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3388      +/-   ##
==========================================
- Coverage   90.55%   90.10%   -0.46%     
==========================================
  Files         398      270     -128     
  Lines        6586     5699     -887     
  Branches     2141     1924     -217     
==========================================
- Hits         5964     5135     -829     
+ Misses        613      555      -58     
  Partials        9        9              
Flag Coverage Δ
main ?
pull-request 90.10% <94.11%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@LinKCoding LinKCoding force-pushed the kl-gmt-1666-gamut-tooltips-blur branch from a9a3a7a to 2c47b8e Compare July 1, 2026 20:22

return (
<ToolTip info={tip} {...(tipProps as any)}>
<ToolTip closeOnClick info={tip} {...(tipProps as any)}>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

very similar to still including info as a prop, where it gets overridden if tipProps includes info --
where if tipProps doesn't include closeOnClick, then closeOnClick becomes the default (the ToolTip disappears after the target is clicked)

@LinKCoding LinKCoding marked this pull request as ready for review July 6, 2026 15:42
@LinKCoding LinKCoding requested a review from a team as a code owner July 6, 2026 15:42
@LinKCoding LinKCoding changed the title first attempt at closing tooltip after click chore: Update ToolTip to default to be dismissed after parent target is clicked Jul 6, 2026
@LinKCoding LinKCoding force-pushed the kl-gmt-1666-gamut-tooltips-blur branch from e4cfa8d to 061b086 Compare July 8, 2026 20:32
@codecademydev

Copy link
Copy Markdown
Collaborator

📬 Published Alpha Packages:

Package Version npm Diff
@codecademy/gamut 72.2.5-alpha.75f51e.0 npm diff
@codecademy/gamut-icons 9.57.11-alpha.75f51e.0 npm diff
@codecademy/gamut-illustrations 0.58.16-alpha.75f51e.0 npm diff
@codecademy/gamut-kit 3.0.9-alpha.75f51e.0 npm diff
@codecademy/gamut-patterns 0.10.35-alpha.75f51e.0 npm diff
@codecademy/gamut-styles 20.0.3-alpha.75f51e.0 npm diff
@codecademy/gamut-tests 6.0.6-alpha.75f51e.0 npm diff
@codecademy/variance 0.26.2-alpha.75f51e.0 npm diff
eslint-plugin-gamut 2.4.4-alpha.75f51e.0 npm diff

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a closeOnClick capability to Gamut tooltips and wires it through key interactive components so hover-tooltips can be dismissed immediately after activation (with an opt-out for “copy → copied” style patterns).

Changes:

  • Introduces closeOnClick in tooltip types/components and implements dismiss/undismiss behavior for inline + floating tooltip variants.
  • Defaults IconButton tooltips to close on click; adds MenuItem support and updates related stories/docs.
  • Adds Storybook stories + MDX docs and extends IconButton unit tests around click handling.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.stories.tsx Adds “Close on Click” story variants for ToolTip (floating + inline).
packages/styleguide/src/lib/Molecules/Tips/ToolTip/ToolTip.mdx Documents close-on-click behavior and how to opt out.
packages/styleguide/src/lib/Molecules/Menu/Menu.stories.tsx Updates Menu stories to demonstrate tooltip close-on-click behavior (and opt-out).
packages/styleguide/src/lib/Atoms/Buttons/IconButton/IconButton.stories.tsx Adds IconButton “CloseOnClick” story variants and demonstrates tipProps.closeOnClick=false.
packages/styleguide/src/lib/Atoms/Buttons/IconButton/IconButton.mdx Documents IconButton tooltip close-on-click default and opt-out usage.
packages/gamut/src/Tip/ToolTip/index.tsx Adds closeOnClick prop to ToolTip public API (but needs defaulting in implementation).
packages/gamut/src/Tip/shared/types.tsx Adds closeOnClick to shared placement component props.
packages/gamut/src/Tip/shared/InlineTip.tsx Implements inline tooltip dismissal state + event handling for close-on-click.
packages/gamut/src/Tip/shared/FloatingTip.tsx Implements click-to-close behavior for floating tooltip variant.
packages/gamut/src/Tip/shared/elements.tsx Updates tooltip wrapper CSS selectors/state to support dismissal and focus-visible behavior.
packages/gamut/src/Menu/MenuItem.tsx Adds closeOnClick to icon-only MenuItem tooltips (default true).
packages/gamut/src/Menu/elements.tsx Forwards closeOnClick through MenuToolTipWrapper into ToolTip.
packages/gamut/src/Button/IconButton.tsx Defaults IconButton tooltips to closeOnClick (with tipProps override).
packages/gamut/src/Button/tests/IconButton.test.tsx Adds tests around click handling with closeOnClick.
.nx/version-plans/version-plan-1782928816938.md Adds version plan for the patch release.

Comment on lines +1 to +2
import { useCallback, useState } from 'react';

Comment on lines +16 to +20
/**
* If true, the tooltip closes immediately when the trigger is clicked or activated via keyboard.
* Pass `false` via `tipProps` on IconButton to opt out (e.g. copy → copied patterns).
*/
closeOnClick?: boolean;
Comment on lines +87 to +93
it('does not prevent button onClick when the floating tip click handler fires', async () => {
const { view } = renderFloatingView();

await userEvent.click(view.getByRole('button', { name: label }));

expect(onClick).toHaveBeenCalledTimes(1);
});
gamut: patch
---

enable dismissable of ToolTip via onClick for interactive components like IconButton, MenuItem (icon-only), and FloatingToolTip + InlineToolTip
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.

3 participants