Skip to content

feat(tooltip)!: port to pf-v6-tooltip#3141

Open
bennypowers wants to merge 14 commits into
staging/pfv6from
feat/tooltip/v6
Open

feat(tooltip)!: port to pf-v6-tooltip#3141
bennypowers wants to merge 14 commits into
staging/pfv6from
feat/tooltip/v6

Conversation

@bennypowers

Copy link
Copy Markdown
Member

Summary

  • New pf-v6-tooltip element ported from v5 with v6 design tokens
  • FloatingDOMController with arrow element positioning
  • Cancellable TooltipShowEvent/TooltipHideEvent with reason enum for selective trigger prevention
  • trigger attribute (IDREF) and property (Element ref) for external trigger elements
  • entry-delay/exit-delay (default 300ms), alignment (start/end/left/right), position, no-flip, flip-behavior
  • light-dark() CSS fallbacks for correct inverse color scheme
  • ariaDescribedByElements wiring between trigger and tooltip content
  • 9 demos: basic, placement, trigger-ref, trigger-element, slotted-content, dynamic-content, left-aligned, color-scheme, options playground
  • 17 unit tests

Test plan

  • Verify tooltip shows on hover and focus in all demos
  • Verify tooltip hides on mouseleave, focusout, and Escape
  • Verify light-dark color scheme inversion in color-scheme demo
  • Verify external trigger via IDREF (trigger-ref) and Element ref (trigger-element)
  • Verify alignment attribute changes text-align
  • Verify entry-delay/exit-delay in options playground
  • Verify no-flip disables repositioning
  • Run /review-a11y, /review-api, /review-demos
  • Visual parity with patternfly.org tooltip

Closes #3048

@changeset-bot

changeset-bot Bot commented May 11, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 9e82d97

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@patternfly/elements Major

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

✅ Commitlint tests passed!

More Info
{
  "valid": true,
  "errors": [],
  "warnings": [],
  "input": "feat(tooltip)!: port to `pf-v6-tooltip`"
}

@github-actions

github-actions Bot commented May 11, 2026

Copy link
Copy Markdown
Contributor

Deploy Preview for patternfly-elements ready!

Name Link
🔨 Latest commit b302f12
😎 Deploy Preview https://deploy-preview-3141--patternfly-elements.netlify.app/

To edit notification comments on pull requests, go to your Netlify site settings.

@github-actions github-actions Bot added the AT passed Automated testing has passed label May 11, 2026
@github-actions

Copy link
Copy Markdown
Contributor

SSR Test Run for 4e4a328: Report

@github-actions

This comment has been minimized.

@bennypowers bennypowers marked this pull request as ready for review May 12, 2026 11:19
@github-actions

Copy link
Copy Markdown
Contributor

SSR Test Run for 6b79b33: Report

@github-actions

Copy link
Copy Markdown
Contributor

SSR Test Run for d88bd77: Report

@bennypowers

bennypowers commented May 25, 2026

Copy link
Copy Markdown
Member Author

Cross-root aria-describedby limitation

The tooltip sets ariaDescribedByElements on the trigger to reference the shadow-internal #content div. This is the correct API for cross-root ARIA relationships, but it silently fails in all browsers today: the accessibility tree shows no describedby relationship.

Per the current spec, ARIA element reflection only works when shadow roots are in an ancestor/descendant relationship, and even then only in the shadow-to-light direction. Our use case (light DOM trigger referencing shadow DOM content) goes the wrong way. The WPT test explicitly asserts that cross-root refs produce an empty computed label.

This means tooltip triggers currently have no programmatic describedby relationship in any browser. The tooltip content is still announced when visible (via role="tooltip" and proximity in the accessibility tree), but there is no formal ARIA association.

The Reference Target proposal (Chrome origin trial) would solve the slotted trigger case. The external trigger case (sibling elements) would need the relaxation discussed in WICG/aom#192. Both whatwg/html#5401 and whatwg/html#10707 track the broader spec work.

Keeping the ariaDescribedByElements call as progressive enhancement -- it will start working once browsers ship a solution. No workaround attempted; the alternatives (hidden light DOM spans, aria-label mirroring) add complexity for a temporary gap.

@adamjohnson and @hellogreg -- could you verify the actual screen reader experience here? Want to confirm the tooltip content is still announced via proximity/role="tooltip" even without the formal describedby association.

@zeroedin zeroedin self-requested a review June 11, 2026 14:33

@zeroedin zeroedin left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Rename PR feat(tooltip)!: port to pf-v6-tooltip

Comment thread .changeset/keen-newts-fly.md Outdated
Comment thread elements/pf-v6-tooltip/README.md Outdated
Comment thread elements/pf-v6-tooltip/README.md Outdated
Comment thread elements/pf-v6-tooltip/README.md Outdated
@bennypowers bennypowers changed the title feat(tooltip): add pf-v6-tooltip element feat(tooltip)!: port to pf-v6-tooltip Jun 14, 2026
@bennypowers

bennypowers commented Jun 14, 2026

Copy link
Copy Markdown
Member Author

NB: i found no instances of react Tooltip component's minWidth prop in the wild, scanning across 510 repos (160 importing Tooltip). I found one instance of Popover react component's minWidth prop, so I think we're justified in removing it, since there's a (already popularly used) workaround - using minWidth css on the contents.

See generated report below. I don't endorse every recommendation here, this is just for reference.

Tooltip Audit Summary

2296 instances across 105/160 repos | 48 spread usages

Props: PF React vs Actual Usage

Prop PF React Used Count Recommendation
content yes yes 2277 (99%) Keep - core prop
position yes yes 629 (27%) Keep
children yes yes (implicit) Keep - trigger slot
triggerRef yes yes 125 (5%) Keep - ref-based trigger
trigger yes yes 110 (5%) Keep (simplified) - mostly mouseenter/click/manual
id yes yes 63 (3%) Native HTML
isContentLeftAligned yes yes 59 (3%) Keep (simplified) - CSS class toggle
enableFlip yes yes 56 (2%) Keep - Popper/Floating UI concern
entryDelay yes yes 52 (2%) Keep
isVisible yes yes 40 (2%) Keep - programmatic control
aria yes yes 24 (1%) Keep (simplified) - describedby/labelledby/none
aria-live yes yes 20 (1%) Keep
maxWidth yes yes 21 (1%) Keep - CSS custom property
appendTo yes yes 21 (1%) Drop candidate - web components handle shadow DOM differently
distance yes yes 20 (1%) Keep - CSS custom property
exitDelay yes yes 19 (1%) Keep
flipBehavior yes yes 15 (1%) Keep (simplified) - Floating UI handles natively
className yes yes 28 (1%) Native HTML - class
animationDuration yes yes 8 (<1%) Keep - CSS custom property
onTooltipHidden yes yes 6 (<1%) Keep - event
hidden HTML yes 38 (2%) Native HTML
removeFindDomNode yes yes 7 (<1%) Drop - React-specific workaround
zIndex yes yes 1 (<1%) Drop candidate - CSS custom property
minWidth yes yes 1 (<1%) Drop candidate - 1 usage across 2296 instances
role HTML yes 2 (<1%) Native HTML
data-testid HTML yes 28 (1%) Native HTML
data-test HTML yes 5 (<1%) Native HTML
aria-label HTML yes 30 (1%) Native HTML

Web Component API Recommendations

Core attributes: content, position, trigger, distance, entry-delay, exit-delay, max-width, animation-duration, enable-flip

Boolean attributes: content-left-aligned, visible, no-flip (invert of enableFlip)

Events: pf-hidden (replaces onTooltipHidden)

Drop: minWidth, zIndex, removeFindDomNode, appendTo, flipBehavior (Floating UI handles). All handleable via CSS custom properties or Floating UI defaults.

48 spread usages may pass unlisted props -- worth spot-checking those repos.

Port tooltip to v6 design tokens and patterns.

- FloatingDOMController with arrow element positioning
- Cancellable TooltipShowEvent/TooltipHideEvent with reason enum
- `trigger` attribute (IDREF) and property (Element ref)
- `entry-delay`/`exit-delay` attributes (default 300ms)
- `alignment` attribute (start/end/left/right)
- `position`, `no-flip`, `flip-behavior` carried from v5
- `light-dark()` CSS fallbacks for inverse color scheme
- `ariaDescribedByElements` wiring on show/hide
- Escape key dismissal
- 9 demos including playground, color-scheme, and element-ref trigger
- 17 unit tests covering API, a11y, events, and cancellation

Closes #3048

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaced by pf-v6-tooltip.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Static document keydown listener for Escape (works with external triggers)
- Screen reader announcer via static `role="status"` live region
- `silent` attribute to opt out of announcements
- Remove physical `'left'`/`'right'` from `TooltipAlignment`, keep logical
  `'start'`/`'end'` only
- Remove `color-scheme: light dark` from `:host` so tooltip inherits
  container scheme and inverts correctly via `light-dark()`
- Fix `user-select: initial` to `auto`
- Why-comments on `ariaDescribedByElements` cross-root limitation
  and intentional bidirectional `visible` state
- Improved JSDoc for cem health (66 -> 85): element description,
  slot a11y notes, CSS token refs, event detail shapes, added missing
  `--pf-v6-c-tooltip__arrow--BoxShadow` `@cssprop`

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- hide event firing and reason
- focusin/focusout triggers
- Element reference trigger property
- flip-behavior attribute parsing
- visible attribute (declarative)
- slot overrides content attribute
- cancel hide event
- Escape key with external trigger (document listener)
- silent attribute

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Demonstrate feature parity with React trigger modes using cancelable
show/hide events:
- click-trigger: click-to-toggle tooltip via preventDefault on hover
- manual-trigger: checkbox-controlled tooltip via preventDefault on
  both hover and focus triggers

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Not a standalone demo on patternfly.org; alignment is covered by the
options playground demo.

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add static live-region announcer pattern for tooltip/popover content
  (from rh-tooltip)
- Update cross-root ARIA section with WPT test link and spec references
  (WICG/aom#192, whatwg/html#5401, WICG/webcomponents#1086)

Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Assisted-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

SSR Test Run for 86b1f12: Report

@bennypowers bennypowers requested a review from zeroedin June 14, 2026 06:09
@github-actions

Copy link
Copy Markdown
Contributor

SSR Test Run for b302f12: Report

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

Labels

AT passed Automated testing has passed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants