diff --git a/src/App.tsx b/src/App.tsx index 18a48af9..fab130f0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -47,8 +47,15 @@ function App() { > My button - + Tooltip content { + if (!id) return + + function getAriaDescribedBy(element: HTMLElement | null) { + return element?.getAttribute('aria-describedby')?.split(' ') || [] + } + + function removeAriaDescribedBy(element: HTMLElement | null) { + const newDescribedBy = getAriaDescribedBy(element).filter((s) => s !== id) + if (newDescribedBy.length) { + element?.setAttribute('aria-describedby', newDescribedBy.join(' ')) + } else { + element?.removeAttribute('aria-describedby') + } + } + + if (show) { + removeAriaDescribedBy(previousActiveAnchor) + const currentDescribedBy = getAriaDescribedBy(activeAnchor) + const describedBy = [...new Set([...currentDescribedBy, id])].filter(Boolean).join(' ') + activeAnchor?.setAttribute('aria-describedby', describedBy) + } else { + removeAriaDescribedBy(activeAnchor) + } + + // eslint-disable-next-line consistent-return + return () => { + // cleanup aria-describedby when the tooltip is closed + removeAriaDescribedBy(activeAnchor) + removeAriaDescribedBy(previousActiveAnchor) + } + }, [activeAnchor, show, id, previousActiveAnchor]) + /** * this replicates the effect from `handleShow()` * when `isOpen` is changed from outside diff --git a/src/components/Tooltip/TooltipTypes.d.ts b/src/components/Tooltip/TooltipTypes.d.ts index ebb75b90..13904d18 100644 --- a/src/components/Tooltip/TooltipTypes.d.ts +++ b/src/components/Tooltip/TooltipTypes.d.ts @@ -153,6 +153,7 @@ export interface ITooltip { afterShow?: () => void afterHide?: () => void disableTooltip?: (anchorRef: HTMLElement | null) => boolean + previousActiveAnchor: HTMLElement | null activeAnchor: HTMLElement | null setActiveAnchor: (anchor: HTMLElement | null) => void border?: CSSProperties['border'] diff --git a/src/components/TooltipController/TooltipController.tsx b/src/components/TooltipController/TooltipController.tsx index fd70a431..0276a9d8 100644 --- a/src/components/TooltipController/TooltipController.tsx +++ b/src/components/TooltipController/TooltipController.tsx @@ -81,6 +81,7 @@ const TooltipController = React.forwardRef( const [tooltipPositionStrategy, setTooltipPositionStrategy] = useState(positionStrategy) const [tooltipClassName, setTooltipClassName] = useState(null) const [activeAnchor, setActiveAnchor] = useState(null) + const previousActiveAnchorRef = useRef(null) const styleInjectionRef = useRef(disableStyleInjection) /** * @todo Remove this in a future version (provider/wrapper method is deprecated) @@ -375,7 +376,15 @@ const TooltipController = React.forwardRef( afterHide, disableTooltip, activeAnchor, - setActiveAnchor: (anchor: HTMLElement | null) => setActiveAnchor(anchor), + previousActiveAnchor: previousActiveAnchorRef.current, + setActiveAnchor: (anchor: HTMLElement | null) => { + setActiveAnchor((prev) => { + if (!anchor?.isSameNode(prev)) { + previousActiveAnchorRef.current = prev + } + return anchor + }) + }, role, } diff --git a/src/test/__snapshots__/tooltip-attributes.spec.js.snap b/src/test/__snapshots__/tooltip-attributes.spec.js.snap index c4b2b54a..57f73998 100644 --- a/src/test/__snapshots__/tooltip-attributes.spec.js.snap +++ b/src/test/__snapshots__/tooltip-attributes.spec.js.snap @@ -3,6 +3,7 @@ exports[`tooltip attributes basic tooltip 1`] = `
@@ -26,6 +27,7 @@ exports[`tooltip attributes basic tooltip 1`] = ` exports[`tooltip attributes tooltip with class name 1`] = `
diff --git a/src/test/__snapshots__/tooltip-props.spec.js.snap b/src/test/__snapshots__/tooltip-props.spec.js.snap index 9a4a0ab4..a0eb9472 100644 --- a/src/test/__snapshots__/tooltip-props.spec.js.snap +++ b/src/test/__snapshots__/tooltip-props.spec.js.snap @@ -3,6 +3,7 @@ exports[`tooltip props basic tooltip 1`] = `
Lorem Ipsum @@ -25,6 +26,7 @@ exports[`tooltip props basic tooltip 1`] = ` exports[`tooltip props clickable tooltip 1`] = `
Lorem Ipsum @@ -49,6 +51,7 @@ exports[`tooltip props clickable tooltip 1`] = ` exports[`tooltip props tooltip with custom position 1`] = `
Lorem Ipsum @@ -81,6 +84,7 @@ exports[`tooltip props tooltip with delay hide 1`] = ` exports[`tooltip props tooltip with delay show 1`] = `
Lorem Ipsum @@ -103,6 +107,7 @@ exports[`tooltip props tooltip with delay show 1`] = ` exports[`tooltip props tooltip with disableTooltip return false 1`] = `
Lorem Ipsum @@ -125,6 +130,7 @@ exports[`tooltip props tooltip with disableTooltip return false 1`] = ` exports[`tooltip props tooltip with float 1`] = `
Lorem Ipsum @@ -147,6 +153,7 @@ exports[`tooltip props tooltip with float 1`] = ` exports[`tooltip props tooltip with html 1`] = `
Lorem Ipsum @@ -174,20 +181,21 @@ exports[`tooltip props tooltip with html 1`] = ` exports[`tooltip props tooltip with place 1`] = `
Lorem Ipsum