Focus Trap

Utility that traps focus inside a given DOM element.

Features

  • Watches for DOM changes inside the focus trap and updates accordingly
  • Properly restores focus when the trap gets disabled
  • Very customizable

Usage

import { createFocusTrap } from 'corvu'
const DialogContent: Component<{
  open: boolean
}> = (props) => {
  const [contentRef, setContentRef] = createSignal<HTMLElement | null>(null)

  createFocusTrap({
    element: contentRef,
    enabled: () => props.open
  })

  return (
    <Show when={props.open}>
      <div ref={setContentRef}>Dialog</div>
    </Show>
  )
}

The first focusable element within the focus trap element will be focused initially. When the trap is disabled, the focus will be restored to the element that was focused before the trap was enabled.

Custom initial focus element

This example shows how to customize the initial focus element so that the focus moves to a specific element when the trap gets enabled.

const DialogContent: Component<{
  open: boolean
}> = (props) => {
  const [contentRef, setContentRef] = createSignal<HTMLElement | null>(null)
  const [initialFocusRef, setInitialFocusRef] =
    createSignal<HTMLElement | null>(null)

  createFocusTrap({
    element: contentRef,
    enabled: () => props.open,
    initialFocusElement: initialFocusRef,
  })

  return (
    <Show when={props.open}>
      <div ref={setContentRef}>Dialog</div>
      <button>Close</button>
      <input ref={setInitialFocusRef} />
    </Show>
  )
}

API reference

createFocusTrap

Function

Traps focus inside the given element. Is aware of changes being made to the DOM tree inside the focus trap by using a MutationObserver.

Props

element

MaybeAccessor<'null' | HTMLElement>

Element to trap focus in.

enabled

MaybeAccessor<boolean>

If the focus trap is enabled. *Default = true*

observeChanges

MaybeAccessor<boolean>

Whether to watch for changes being made to the DOM tree inside the focus trap and reload the focus trap accordingly. *Default = true*

initialFocusElement

MaybeAccessor<'null' | HTMLElement>

The element to receive focus when the focus trap is activated. *Default = The first focusable element inside element*

onInitialFocus

(event: Event) => void

Callback fired when focus moves inside the focus trap. Can be prevented by calling event.preventDefault.

restoreFocus

MaybeAccessor<boolean>

If the focus should be restored to the element the focus was on initially when the focus trap is deactivated. *Default = true*

finalFocusElement

MaybeAccessor<'null' | HTMLElement>

The element to receive focus when the focus trap is deactivated (enabled = false). *Default = The element the focus was on initially*

onFinalFocus

(event: Event) => void

Callback fired when focus moves outside the focus trap. Can be prevented by calling event.preventDefault.

corvu@0.2.3

Developed and designed by Jasmin