-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Close the
Combobox
, Dialog
, Listbox
, Menu
and Popover
compo…
…nents when the trigger disappears (#3075) * add `useOnDisappear` hook This hook allows us to trigger a callback if the element becomes "hidden". We use the bounding client rect and check the dimensions to know wether we are "hidden" or not. * use new `useOnDisappear` hook in components with the `anchor` prop * update changelog * document `useOnDisappear`
- Loading branch information
1 parent
4ed69f6
commit c1d3b7e
Showing
7 changed files
with
69 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { useEffect, type MutableRefObject } from 'react' | ||
import { disposables } from '../utils/disposables' | ||
import { useLatestValue } from './use-latest-value' | ||
|
||
/** | ||
* A hook to ensure that a callback is called when the element has disappeared | ||
* from the screen. | ||
* | ||
* This can happen if you use Tailwind classes like: `hidden md:block`, once the | ||
* viewport is smaller than `md` the element will disappear. | ||
*/ | ||
export function useOnDisappear( | ||
ref: MutableRefObject<HTMLElement | null> | HTMLElement | null, | ||
cb: () => void, | ||
enabled = true | ||
) { | ||
let listenerRef = useLatestValue((element: HTMLElement) => { | ||
let rect = element.getBoundingClientRect() | ||
if (rect.x === 0 && rect.y === 0 && rect.width === 0 && rect.height === 0) { | ||
cb() | ||
} | ||
}) | ||
|
||
useEffect(() => { | ||
if (!enabled) return | ||
|
||
let element = ref === null ? null : ref instanceof HTMLElement ? ref : ref.current | ||
if (!element) return | ||
|
||
let d = disposables() | ||
|
||
// Try using ResizeObserver | ||
if (typeof ResizeObserver !== 'undefined') { | ||
let observer = new ResizeObserver(() => listenerRef.current(element)) | ||
observer.observe(element) | ||
d.add(() => observer.disconnect()) | ||
} | ||
|
||
// Try using IntersectionObserver | ||
if (typeof IntersectionObserver !== 'undefined') { | ||
let observer = new IntersectionObserver(() => listenerRef.current(element)) | ||
observer.observe(element) | ||
d.add(() => observer.disconnect()) | ||
} | ||
|
||
return () => d.dispose() | ||
}, [ref, listenerRef, enabled]) | ||
} |