Floating Focus Manager
Provides flexible modal or non-modal focus management for a floating element. Modal behavior is the default — focus is fully trapped inside the floating element while it is rendered.
This is necessary to ensure that focus is properly managed for keyboard interaction.
This component should only be rendered when the floating element is open and directly wrap it.
Props
context
The context
object returned from useFloating()
.
disabled
default: false
Disables all focus management entirely. Useful to delay focus management until after a transition completes or some other conditional state.
initialFocus
default: 0
Which element to initially focus. Can be either a number
(tabbable index as specified by the order
) or a ref.
Negative number
You can set this to a negative number to ignore the initial
focus. This is required to prevent conflicts if your floating
element has no tabbable content and is instead controlled by the
useListNavigation()
Hook which has its own focus
management.
If there is no list navigation, then modal
behavior’s focus trap will no longer work. To maintain the trap,
you can place the initial focus on the floating element:
returnFocus
default: true
Determines if focus should be returned to the reference element (or if that is not available, the previously focused element). This prop is ignored if the floating element lost focus. It can be also set to a ref to explicitly control the element to return focus to.
restoreFocus
default: false
Determines if focus should be restored to the nearest tabbable element if the currently focused element inside the floating element was removed from the DOM (causing focus to be lost otherwise).
guards
default: true
Determines if the focus guards are rendered. If not, focus can escape into the address bar/console/browser UI, like in native dialogs.
modal
default: true
Determines if focus is “modal”, meaning focus is fully trapped inside the floating element and outside content cannot be accessed. This includes screen reader virtual cursors.
Non-modal behavior
The floating element should be rendered after the reference
element in the React tree. It can be portaled using
<FloatingPortal>
. Other portal solutions are not supported
or accessible when using Floating UI’s focus manager.
Modal behavior
Ensure you have an explicit “close” button. This can be either
visible to all users, or visually-hidden so it is only available
to assistive tech (see
visuallyHiddenDismiss
).
Touch-based screen readers often will not have an esc
key
available to dismiss the element, so an explicit close button is
required, otherwise the user will be trapped in the floating
element if they don’t want to select anything (thus needing to
reload the page).
Comboboxes
When the reference element has a combobox
role
present, the focus manager behavior changes.
The listbox part (floating element) of a combobox (input + listbox popup) can be portaled and accessible to touch screen readers when using modal focus management, but DOM focus does not become modal. Screen reader virtual cursors do become modal, allowing a touch screen reader to immediately access the portaled listbox items.
visuallyHiddenDismiss
default: false
If your focus management is modal and there is no explicit close
button available, you can use this prop to render a
visually-hidden dismiss button at the start and end of the
floating element. This allows touch-based screen readers to
escape the floating element due to lack of an esc
key.
You can pass a string which will be announced by the screen
reader, e.g. for languages other than English. The default string
when using true
is Dismiss
.
closeOnFocusOut
default: true
Determines whether focusout
event listeners that
control whether the floating element should be closed if the
focus moves outside of it are attached to the reference and
floating elements. This affects non-modal focus management.
outsideElementsInert
default: false
Determines whether outside elements are inert
when
modal
is enabled. This enables pointer modality
without a backdrop.
order
default: ['content']
The order in which focus cycles.
Troubleshooting
Page scrolls to top when opening the floating element
This can happen if you’re placing the autoFocus
prop
on an element inside the floating element. This is because the
floating element is initially rendered at the top-left of the
page, and the browser scrolls to it when it receives focus.
Instead, use the initialFocus
prop on
<FloatingFocusManager>
to focus the desired element, which
waits for the position to be ready first.
Usage with <FloatingPortal>
Ensure the focus manager is rendered as a child (can be a nested
descendant) of <FloatingPortal>
.
If you’re using non-modal focus management, you must use
<FloatingPortal>
and not another portal solution. This is
because it tightly integrates with the focus manager to ensure
that focus is moved correctly when tabbing, including the
VoiceOver virtual cursor.