UNPKG

@blueprintjs/core

Version:

Core styles & components

83 lines (65 loc) 2.61 kB
@# useOverlayStack <div class="@ns-callout @ns-intent-warning @ns-icon-warning-sign @ns-callout-has-body-content"> <h5 class="@ns-heading">Internal API</h5> This hook is mainly intended to be an internal Blueprint API used by the **Overlay2** component. Its usage outside of `@blueprintjs/` packages is not fully supported. </div> The `useOverlayStack()` hook allows Blueprint components to interact with the global overlay stack in an application. Compared to the deprecated [**Overlay**](#core/components/overlay) component, this hook avoids storing global state at the JS module level. @## Usage First, make sure [**OverlaysProvider**](#core/context/overlays-provider) is configured correctly at the root of your React application. Then, use the hook to interact with the global overlay stack: ```tsx import { OverlayInstance, OverlayProps, Portal, useOverlayStack, usePrevious } from "@blueprintjs/core"; import * as React from "react"; export function Example(props: OverlayProps) { const { autoFocus, children, enforceFocus, hasBackdrop, isOpen, usePortal } = props; const { openOverlay, closeOverlay } = useOverlayStack(); const containerElement = React.useRef<HTMLDivElement>(null); const bringFocusInsideOverlay = React.useCallback(() => { // TODO: implement }, []); const handleDocumentFocus = React.useCallback((e: FocusEvent) => { // TODO: implement }, []); const id = React.useId(); const instance = React.useMemo<OverlayInstance>( () => ({ bringFocusInsideOverlay, containerElement, handleDocumentFocus, id, props: { autoFocus, enforceFocus, hasBackdrop, usePortal, }, }), [autoFocus, bringFocusInsideOverlay, enforceFocus, handleDocumentFocus, hasBackdrop, id, usePortal], ); const prevIsOpen = usePrevious(isOpen) ?? false; React.useEffect(() => { if (!prevIsOpen && isOpen) { // just opened openOverlay(instance); } if (prevIsOpen && !isOpen) { // just closed closeOverlay(instance); } }, [isOpen, openOverlay, closeOverlay, prevIsOpen, instance]); // run once on unmount React.useEffect(() => { return () => { if (isOpen) { closeOverlay(instance); } }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return usePortal ? <Portal>{children}</Portal> : children; } ```