packages/core/src/hooks/overlays/use-overlay-stack.md
@# 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.
The useOverlayStack() hook allows Blueprint components to interact with the global overlay stack
in an application. Compared to the deprecated Overlay component,
this hook avoids storing global state at the JS module level.
@## Usage
First, make sure OverlaysProvider is configured correctly at the root of your React application.
Then, use the hook to interact with the global overlay stack:
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;
}