Skip to content

feat(tooltips): add toggletip support#2136

Open
jgorfine-zendesk wants to merge 4 commits into
v9from
jgorfine/toggletip
Open

feat(tooltips): add toggletip support#2136
jgorfine-zendesk wants to merge 4 commits into
v9from
jgorfine/toggletip

Conversation

@jgorfine-zendesk

@jgorfine-zendesk jgorfine-zendesk commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description

Adds toggletip support to the Tooltip component via a new isToggletip prop, backed by the toggletip API in @zendeskgarden/container-tooltip. When enabled, the tooltip switches from hover/focus behavior to click-to-toggle: it opens and closes on click, dismisses on outside click or Escape, and announces its content through a role="status" live region. The trigger must be a <button> element.

Detail

  • isToggletip is threaded through Tooltip into useTooltip. The render tree stays unified — the toggletip path applies the live-region props to the always-mounted wrapper and gates the visible bubble on isAnnouncementReady, while the tooltip path keeps its hover handlers on the bubble.
  • Gating the visible bubble (rather than the live region) avoids an empty-bubble flash on open and preserves screen-reader re-announcement on each open.
  • The Tooltip story exposes isToggletip as a control (default false).
  • New [patterns] demos: Toggletip, Toggletip with anchor (interactive content), and Info toggletip (icon-only IconButton trigger with an explicit aria-label).

⚠️ Temporary: this branch depends on the @zendeskgarden/container-tooltip 2.2.3-alpha.1 tarball (committed at the repo root) so CI can install it and build the Storybook preview for manual testing. Once the react-containers PR merges and the container is published, the tarball will be removed and the dependency will point at the released @zendeskgarden/container-tooltip.

Checklist

  • 👌 design updates will be Garden Designer approved (add the designer as a reviewer)
  • 🌐 demo is up-to-date (npm start)
  • ⬅️ renders as expected with reversed (RTL) direction
  • ⚫ renders as expected in dark mode
  • 🤘 renders as expected with Bedrock CSS (?bedrock)
  • 💂‍♂️ includes new unit tests. Maintain existing coverage (always >= 96%)
  • ♿ tested for WCAG 2.2 AA accessibility compliance
  • 📝 tested in Chrome, Firefox, Safari, and Edge

jgorfine-zendesk and others added 3 commits June 24, 2026 16:32
Add an isToggletip prop that switches Tooltip to click-to-toggle behavior
backed by the container's toggletip API. The role="status" live region is
applied to the always-mounted wrapper while the visible bubble is gated on
isAnnouncementReady, preventing an empty-bubble flash on open. Add toggletip
control to the Tooltip story and Toggletip, Toggletip-with-anchor, and
info-toggletip patterns.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Temporarily depend on the @zendeskgarden/container-tooltip 2.2.3-alpha.1
tarball so CI can install it and build the Storybook preview for manual
testing of the toggletip feature.

TEMPORARY: once the react-containers PR merges and the container is
published, remove the tarball and depend on the released
@zendeskgarden/container-tooltip instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop prose comments that don't match the codebase's sparse commenting
convention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coveralls

coveralls commented Jun 24, 2026

Copy link
Copy Markdown

Coverage Status

Coverage is 95.863%jgorfine/toggletip into v9. No base build found for v9.

Cover the integration glue that lives in Tooltip: role="status" live
region, aria-expanded/aria-controls passthrough on the trigger, the gated
bubble that mounts only when open, and type/size styling in toggletip mode.
Behavioral coverage (click, Escape, outside-click, re-announcement) stays in
the container spec to avoid duplication.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
"@zendeskgarden/container-tooltip": "^2.2.0",
"@zendeskgarden/container-tooltip": "file:../../zendeskgarden-container-tooltip-2.2.3-alpha.1.tgz",

This comment was marked as resolved.

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.

Definitely. My understanding is that this is the typical way we test container changes before they're merged in. 🙂 👍

## Toggletip

Setting the `isToggletip` prop switches the `Tooltip` into a toggletip: it opens
and closes on click rather than hover/focus, dismisses on outside click or

This comment was marked as resolved.

This comment was marked as resolved.


## Toggletip with interactive content

Because a toggletip is dismissed on click rather than blur, its content can

@bmson bmson Jul 7, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This demo's premise — interactive content that stays open while you interact, doesn't hold under a mouse click, given the bundled container's outside dismiss handler:

const clickedTrigger = triggerRef.current?.contains(target);
if (!clickedTrigger) { closeTooltip(0); }   // never checks tooltipRef

tooltipRef is never consulted, so a mousedown on interactive content inside the toggletip counts as an outside click and dismisses it.

The Anchor here happens to look fine only because clicking a link is terminal (it navigates as it closes). Any non-navigational interactive content (input, copy button, toggle) will dismiss on mousedown. The outside handler should probably exclude tooltipRef.current?.contains(target). Fix is in the container, but this demo asserts the behavior, so we should probably fix that

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.

Hey @bmson, that's a totally fair point, and I appreciate you flagging it.

Reading all of that, my question is: can/should we try and restrict the kinds of children a toggletip bubble can have, so that it's not even possible to render interactive elements (especially non-navigational interactive content) inside of them? 🤔

I ask for a few reasons:

  1. Having interactive content inside of a toggletip sorta goes against the idea of what a toggletip is: "toggletips exist to reveal information balloons, and serve no other purpose." —Inclusive Components
  2. Live regions don’t handle rich text
  3. Live regions are not suitable for notifications with interactive elements

If we're being honest, even having links inside of toggletips is a bit of a stretch...but I've seen designs with tooltips + links, out in the wild, and I wanted to try and be accommodating. 👀

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Yea, I've seen us have links in the tooltip 😆
It's probably fine, since it's not really a regression.

I'll leave this one up to you as the expert on this subject.

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

Development

Successfully merging this pull request may close these issues.

3 participants