refactor: extract tooltip integration into reusable decorator (#9938) - #10343
refactor: extract tooltip integration into reusable decorator (#9938)#10343deleonio wants to merge 3 commits into
Conversation
…ator (#9938) Introduce a composable TooltipDecorator that encapsulates the TooltipController lifecycle (init, listener sync, teardown) and the tooltip rendering. Migrate kol-abbr, kol-button-wc and kol-link-wc to compose it instead of re-implementing the wiring in every component. The rendered output is kept byte-identical, so existing snapshots stay green. No API, dependency or configuration changes.
There was a problem hiding this comment.
Code Review
This pull request introduces a new TooltipDecorator class to encapsulate the tooltip controller lifecycle and rendering logic, simplifying the integration of tooltips across components like KolAbbr, KolButtonWc, and KolLinkWc. Unit tests for the decorator are also added. Feedback suggests removing a redundant clsx call and its unused import in the TooltipDecorator implementation.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
🚀 MCP preview deployed to Vercel: https://kolibri-m4l56jso1-public-ui-kolibri-mcp.vercel.app |
|
Netlify Draft Deployment |
|
🚀 Preview deployed to GitHub Pages: https://public-ui.github.io/kolibri/pr-10343/91031c5/ |
There was a problem hiding this comment.
Pull request overview
This PR refactors tooltip wiring in @public-ui/components by extracting the repeated TooltipController lifecycle + rendering integration into a reusable TooltipDecorator, then migrating kol-abbr, kol-button-wc, and kol-link-wc to compose that decorator instead of duplicating the same boilerplate.
Changes:
- Added
TooltipDecoratorto encapsulate tooltip controller lifecycle hooks, watchers, hide behavior, and tooltip VNode rendering. - Updated
kol-abbr,kol-button-wc, andkol-link-wcto delegate tooltip behavior to the decorator. - Added a focused unit test covering the decorator’s render guard behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/components/src/internal/functional-components/tooltip/test/decorator.spec.ts | Adds unit tests for TooltipDecorator.render guard behavior. |
| packages/components/src/internal/functional-components/tooltip/decorator.tsx | Introduces the reusable decorator wrapping TooltipController lifecycle + rendering. |
| packages/components/src/components/link/component.tsx | Replaces inline tooltip wiring/rendering with TooltipDecorator usage for link. |
| packages/components/src/components/button/component.tsx | Replaces inline tooltip wiring/rendering with TooltipDecorator usage for button. |
| packages/components/src/components/abbr/shadow.tsx | Replaces inline tooltip wiring/rendering with TooltipDecorator usage for abbr. |
…9938) - Drop redundant clsx call/import; pass wrapperClass directly. - Track the previous trigger in componentDidRender and detach its listeners when the anchored element changes or is removed, so the reusable decorator cannot leak listeners on trigger changes. - Make visibility the sole responsibility of the caller: render() now guards only on 'visible', so the migrated components reproduce their original (byte-identical) markup, including the link hide-label edge case.
Resolve conflict in abbr after its skeleton-architecture migration on develop: keep the new AbbrController/AbbrFC structure and replace the manual TooltipController wiring with the reusable TooltipDecorator (consistent with button and link).
Closes #9938
Problem
Since #9605 the tooltip is wired directly into each component. The same boilerplate (controller instantiation,
watchLabel/watchAlign,componentWillLoad/componentDidRender/disconnectedCallbacklifecycle,hideTooltipon click, and the<TooltipFC>rendering) is duplicated acrosskol-abbr,kol-button-wcandkol-link-wc.Change
TooltipDecorator(internal/functional-components/tooltip/decorator.tsx): a composable helper that encapsulates theTooltipControllerlifecycle and the tooltip rendering. Components compose it viagetTrigger(lazy accessor for the anchor element) and an optionalwrapperClass.kol-abbr,kol-button-wcandkol-link-wcto use the decorator instead of re-implementing the wiring. Each component now delegates in single lines (watchLabel,watchAlign,componentWillLoad,componentDidRender,disconnectedCallback,hide,render).The rendered output is kept byte-identical (Button/Link keep their
__tooltipwrapper, Abbr stays wrapper-less), so existing snapshots remain green. No API, dependency or configuration changes; no breaking changes.Scope / follow-up
This PR deliberately targets only the three web components that hold a stable controller instance.
FieldControl/FormFielduse a per-idMap<string, TooltipController>because their functional component is recreated on every render — unifying that with the decorator is left as a follow-up to keep this diff small and review-friendly.Manual verification
The tooltip behavior is demonstrable in the sample app via the existing
_hideLabelexamples for Button, Link and Abbr (the tooltip appears on hover/focus when the label is hidden).This PR addresses a contributor-reported issue.
Generated by Claude Code