Skip to content

useDismiss

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 contextcontext 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 {refs, floatingStyles, 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={floatingStyles}
          {...getFloatingProps()}
        >
          Floating element
        </div>
      )}
    </>
  );
}
function App() {
  const [isOpen, setIsOpen] = useState(false);
 
  const {refs, floatingStyles, 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={floatingStyles}
          {...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: truetrue

Conditionally enable/disable the hook.

useDismiss(context, {
  enabled: false,
});
useDismiss(context, {
  enabled: false,
});

escapeKey

default: truetrue

Whether to dismiss the floating element upon pressing the esc key.

useDismiss(context, {
  escapeKey: false,
});
useDismiss(context, {
  escapeKey: false,
});

referencePress

default: falsefalse

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 movemove 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: truetrue

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: falsefalse

Whether to dismiss the floating element upon scrolling an overflow ancestor.

useDismiss(context, {
  ancestorScroll: true,
});
useDismiss(context, {
  ancestorScroll: true,
});

bubbles

default: undefinedundefined

When dealing with nested floating elements, this determines whether the dismissal bubbles through the entire <FloatingTree /><FloatingTree /> or stops at the current node.

When falsefalse, 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
  },
});