From 58f1bafb984a30e9d3567909b4d32be56f492f35 Mon Sep 17 00:00:00 2001 From: Tobias Date: Mon, 5 Sep 2022 12:43:28 +0200 Subject: [PATCH] fix(Tooltip): ensure controlled active prop takes presence Fixes #1411 --- .../__snapshots__/Dialog.test.tsx.snap | 2 +- .../__snapshots__/Drawer.test.tsx.snap | 2 +- .../__snapshots__/Modal.test.tsx.snap | 2 +- .../src/components/tooltip/Tooltip.js | 4 +- .../src/components/tooltip/TooltipPortal.js | 25 ++++++---- .../tooltip/__tests__/Tooltip.test.js | 49 +++++++++++++++++++ .../__snapshots__/Tooltip.test.js.snap | 2 +- 7 files changed, 70 insertions(+), 16 deletions(-) diff --git a/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap b/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap index 2f063c5ebd3..eb895a4f995 100644 --- a/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/dialog/__tests__/__snapshots__/Dialog.test.tsx.snap @@ -432,7 +432,7 @@ exports[`Dialog component snapshot should match component snapshot 1`] = ` class={null} className={null} fixed_position={false} - group="main" + group={null} hide_delay={500} id="dialog_id-tooltip" no_animation={false} diff --git a/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap b/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap index c0e00491716..a3b707a5852 100644 --- a/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/drawer/__tests__/__snapshots__/Drawer.test.tsx.snap @@ -430,7 +430,7 @@ exports[`Drawer component snapshot should match component snapshot 1`] = ` class={null} className={null} fixed_position={false} - group="main" + group={null} hide_delay={500} id="drawer_id-tooltip" no_animation={false} diff --git a/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap b/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap index 4bbc4448484..12318c13c1c 100644 --- a/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap +++ b/packages/dnb-eufemia/src/components/modal/__tests__/__snapshots__/Modal.test.tsx.snap @@ -421,7 +421,7 @@ exports[`Modal component have to match snapshot 1`] = ` class={null} className={null} fixed_position={false} - group="main" + group={null} hide_delay={500} id="modal_id-tooltip" no_animation={false} diff --git a/packages/dnb-eufemia/src/components/tooltip/Tooltip.js b/packages/dnb-eufemia/src/components/tooltip/Tooltip.js index c4371d04343..5c0710759bd 100644 --- a/packages/dnb-eufemia/src/components/tooltip/Tooltip.js +++ b/packages/dnb-eufemia/src/components/tooltip/Tooltip.js @@ -76,7 +76,7 @@ export default class Tooltip extends React.PureComponent { static defaultProps = { id: null, - group: 'main', + group: null, size: 'basis', active: null, position: 'top', @@ -176,7 +176,7 @@ export default class Tooltip extends React.PureComponent { ...this.props, ...inherited, internal_id: this._id, - group: this.props.id || group, + group: this.props.id || group || 'main-' + this._id, } if (newProps.active === null) { delete newProps.active diff --git a/packages/dnb-eufemia/src/components/tooltip/TooltipPortal.js b/packages/dnb-eufemia/src/components/tooltip/TooltipPortal.js index 3fe69bc3c69..6c6fa195880 100644 --- a/packages/dnb-eufemia/src/components/tooltip/TooltipPortal.js +++ b/packages/dnb-eufemia/src/components/tooltip/TooltipPortal.js @@ -30,7 +30,7 @@ export default class TooltipPortal extends React.PureComponent { static defaultProps = { internal_id: null, active: false, - group: 'main', + group: null, hide_delay: 500, } @@ -46,7 +46,7 @@ export default class TooltipPortal extends React.PureComponent { tooltipPortal[group].count++ - this.setState({ isMounted: true, active }, () => { + this.setState({ isMounted: true, isActive: active }, () => { if (!this.isMainGorup()) { this.renderPortal() } @@ -64,16 +64,22 @@ export default class TooltipPortal extends React.PureComponent { componentDidUpdate(prevProps) { const { group, active, hide_delay } = this.props + if (this.props.children !== prevProps.children) { + this.renderPortal() + } + if (tooltipPortal[group] && active !== prevProps.active) { + clearTimeout(tooltipPortal[group].timeout) + if (active && !prevProps.active) { - this.setState({ active: true }, () => { + this.setState({ isActive: true }, () => { if (!this.isMainGorup()) { this.renderPortal() } }) } else if (!active && prevProps.active) { - this.timeout = tooltipPortal[group].timeout = setTimeout(() => { - this.setState({ active: false }, () => { + tooltipPortal[group].timeout = setTimeout(() => { + this.setState({ isActive: false }, () => { if (!this.isMainGorup()) { this.renderPortal() } @@ -85,18 +91,17 @@ export default class TooltipPortal extends React.PureComponent { isMainGorup() { const { group } = this.props - return group === 'main' + return group.includes('main') } componentWillUnmount() { const { group } = this.props - clearTimeout(this.timeout) - if (tooltipPortal[group]) { tooltipPortal[group].count-- if (!this.isMainGorup()) { + clearTimeout(tooltipPortal[group].timeout) ReactDOM.unmountComponentAtNode(tooltipPortal[group].node) } @@ -167,7 +172,7 @@ export default class TooltipPortal extends React.PureComponent { , tooltipPortal[group].node ) @@ -176,7 +181,7 @@ export default class TooltipPortal extends React.PureComponent { , tooltipPortal[group].node ) diff --git a/packages/dnb-eufemia/src/components/tooltip/__tests__/Tooltip.test.js b/packages/dnb-eufemia/src/components/tooltip/__tests__/Tooltip.test.js index 1b5c6af92e8..0000a5e5955 100644 --- a/packages/dnb-eufemia/src/components/tooltip/__tests__/Tooltip.test.js +++ b/packages/dnb-eufemia/src/components/tooltip/__tests__/Tooltip.test.js @@ -93,6 +93,55 @@ describe('Tooltip', () => { const Comp = mount() expect(await axeComponent(Comp)).toHaveNoViolations() }) + + it('should show when active prop is true', async () => { + const Component = () => { + const [active, setActive] = React.useState(false) + + return ( + { + setActive(true) + }} + onMouseLeave={() => { + setActive(false) + }} + > + Text + + } + > + Tooltip + + ) + } + + const Comp = mount() + + const mainElem = document.body.querySelector('.dnb-tooltip') + + Comp.find('button').simulate('mouseenter') + + expect(mainElem.classList.contains('dnb-tooltip--active')).toBe(true) + + Comp.find('button').simulate('mouseleave') + Comp.find('button').simulate('mouseenter') + + await wait(2) + + expect(mainElem.classList.contains('dnb-tooltip--active')).toBe(true) + + Comp.find('button').simulate('mouseleave') + + await wait(2) + + expect(mainElem.classList.contains('dnb-tooltip--hide')).toBe(true) + }) }) describe('Anchor with tooltip', () => { diff --git a/packages/dnb-eufemia/src/components/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap b/packages/dnb-eufemia/src/components/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap index 6e3924e69a2..5a534c1b7e6 100644 --- a/packages/dnb-eufemia/src/components/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap +++ b/packages/dnb-eufemia/src/components/tooltip/__tests__/__snapshots__/Tooltip.test.js.snap @@ -215,7 +215,7 @@ exports[`Tooltip with target_element have to match default tooltip snapshot 1`] class={null} className={null} fixed_position={false} - group="main" + group={null} hide_delay={0} id="tooltip" no_animation={false}