use Dismiss
Closes the floating element when a dismissal is requested — by
default, when the user presses the escape
key or outside of the
floating element.
import {useDismiss} from '@floating-ui/react';
import {useDismiss} from '@floating-ui/react';
Usage
This hook is an interaction hook that returns event handler props.
To use it, pass it the context
context
object returned from
useFloating()
useFloating()
, and then feed its result into the
useInteractions()
useInteractions()
array. The returned prop getters are
then spread onto the elements for rendering.
function App() {
const [isOpen, setIsOpen] = useState(false);
const {x, y, strategy, refs, context} = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
});
const dismiss = useDismiss(context);
const {getReferenceProps, getFloatingProps} = useInteractions([
dismiss,
]);
return (
<>
<div ref={refs.setReference} {...getReferenceProps()}>
Reference element
</div>
{isOpen && (
<div
ref={refs.setFloating}
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
}}
{...getFloatingProps()}
>
Floating element
</div>
)}
</>
);
}
function App() {
const [isOpen, setIsOpen] = useState(false);
const {x, y, strategy, refs, context} = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
});
const dismiss = useDismiss(context);
const {getReferenceProps, getFloatingProps} = useInteractions([
dismiss,
]);
return (
<>
<div ref={refs.setReference} {...getReferenceProps()}>
Reference element
</div>
{isOpen && (
<div
ref={refs.setFloating}
style={{
position: strategy,
top: y ?? 0,
left: x ?? 0,
}}
{...getFloatingProps()}
>
Floating element
</div>
)}
</>
);
}
Props
interface Props {
enabled?: boolean;
escapeKey?: boolean;
referencePress?: boolean;
referencePressEvent?: 'pointerdown' | 'mousedown' | 'click';
outsidePress?: boolean | ((event: MouseEvent) => boolean);
outsidePressEvent?: 'pointerdown' | 'mousedown' | 'click';
ancestorScroll?: boolean;
bubbles?:
| boolean
| {escapeKey?: boolean; outsidePress?: boolean};
}
interface Props {
enabled?: boolean;
escapeKey?: boolean;
referencePress?: boolean;
referencePressEvent?: 'pointerdown' | 'mousedown' | 'click';
outsidePress?: boolean | ((event: MouseEvent) => boolean);
outsidePressEvent?: 'pointerdown' | 'mousedown' | 'click';
ancestorScroll?: boolean;
bubbles?:
| boolean
| {escapeKey?: boolean; outsidePress?: boolean};
}
enabled
default: true
true
Conditionally enable/disable the hook.
useDismiss(context, {
enabled: false,
});
useDismiss(context, {
enabled: false,
});
escapeKey
default: true
true
Whether to dismiss the floating element upon pressing the esc
key.
useDismiss(context, {
escapeKey: false,
});
useDismiss(context, {
escapeKey: false,
});
referencePress
default: false
false
Whether to dismiss the floating element upon pressing the reference element.
useDismiss(context, {
referencePress: true,
});
useDismiss(context, {
referencePress: true,
});
You likely want to ensure the move
move
option in the
useHover()
useHover()
hook has been disabled when this is in use.
Keyboard press dismissal
If you’d like to ensure the floating element is also dismissed upon “pressing” the reference element via the keyboard, you can add in your own handler(s) for this.
getReferenceProps({
// for a native <button>
onClick() {
setOpen(false);
},
});
getReferenceProps({
// for a native <button>
onClick() {
setOpen(false);
},
});
referencePressEvent
default: 'pointerdown'
'pointerdown'
The type of event to use to determine a “press”.
useDismiss(context, {
// eager on both mouse + touch input
referencePressEvent: 'pointerdown',
// eager on mouse input, lazy on touch input
referencePressEvent: 'mousedown',
// lazy on both mouse + touch input
referencePressEvent: 'click',
});
useDismiss(context, {
// eager on both mouse + touch input
referencePressEvent: 'pointerdown',
// eager on mouse input, lazy on touch input
referencePressEvent: 'mousedown',
// lazy on both mouse + touch input
referencePressEvent: 'click',
});
outsidePress
default: true
true
Whether to dismiss the floating element upon pressing outside of both the floating and reference elements.
useDismiss(context, {
outsidePress: false,
});
useDismiss(context, {
outsidePress: false,
});
If you have another element, like a toast, that is rendered outside the floating element’s React tree and don’t want the floating element to close when pressing it, you can guard the check like so:
useDismiss(context, {
// Same as `true`, but with a custom guard check.
outsidePress: (event) => !event.target.closest('.toast'),
});
useDismiss(context, {
// Same as `true`, but with a custom guard check.
outsidePress: (event) => !event.target.closest('.toast'),
});
function App() {
// The toast is not inside the Dialog's React tree, so we
// need to add a guard to consider it a child of the Dialog
// to prevent the Dialog's outside press from closing it.
return (
<>
<Dialog />
<Toast className="toast" />
</>
);
}
function App() {
// The toast is not inside the Dialog's React tree, so we
// need to add a guard to consider it a child of the Dialog
// to prevent the Dialog's outside press from closing it.
return (
<>
<Dialog />
<Toast className="toast" />
</>
);
}
outsidePressEvent
default: 'pointerdown'
'pointerdown'
The type of event to use to determine a “press”.
useDismiss(context, {
// eager on both mouse + touch input
outsidePressEvent: 'pointerdown',
// eager on mouse input, lazy on touch input
outsidePressEvent: 'mousedown',
// lazy on both mouse + touch input
outsidePressEvent: 'click',
});
useDismiss(context, {
// eager on both mouse + touch input
outsidePressEvent: 'pointerdown',
// eager on mouse input, lazy on touch input
outsidePressEvent: 'mousedown',
// lazy on both mouse + touch input
outsidePressEvent: 'click',
});
ancestorScroll
default: false
false
Whether to dismiss the floating element upon scrolling an overflow ancestor.
useDismiss(context, {
ancestorScroll: true,
});
useDismiss(context, {
ancestorScroll: true,
});
bubbles
default: undefined
undefined
When dealing with nested floating elements, this determines
whether the dismissal bubbles through the entire
<FloatingTree />
<FloatingTree />
or stops at the current node.
When false
false
, the floating element must have focus inside
it.
Generally, nested modal dialogs (where focus cannot escape the current node) will prefer no bubbling, while other nested floating elements will prefer bubbling.
useDismiss(context, {
bubbles: false,
});
useDismiss(context, {
bubbles: false,
});
The boolean value of bubbles
applies to both escapeKey
and
outsidePress
event bubbling. In case of a need to only disable
bubbling of one of those events, specify an object to the prop.
Any omitted events will use the default value.
useDismiss(context, {
bubbles: {
escapeKey: true, // false by default
outsidePress: false, // true by default
},
});
useDismiss(context, {
bubbles: {
escapeKey: true, // false by default
outsidePress: false, // true by default
},
});