FocusTrap

Trap focus within a container. Useful for modals and dropdowns.

Import

import { FocusTrap } from '@tidbcloud/uikit'

Usage

FocusTrap is a component that traps focus inside a container. Tab key press moves focus from one focusable element to another within the container, and when focus leaves the container, it cycles back to the first focusable element.

import { useDisclosure } from '@mantine/hooks'
import { FocusTrap, TextInput, Button, Box } from '@tidbcloud/uikit'
 
function Demo() {
  const [active, { toggle }] = useDisclosure(false)
 
  return (
    <Box maw={400} mx="auto">
      <Button onClick={toggle}>{active ? 'Deactivate' : 'Activate'} focus trap</Button>
 
      <FocusTrap active={active}>
        <div>
          <TextInput mt="sm" label="First input" placeholder="First input" />
          <TextInput mt="sm" label="Second input" placeholder="Second input" />
          <TextInput mt="sm" label="Third input" placeholder="Third input" />
        </div>
      </FocusTrap>
    </Box>
  )
}

Initial focus

By default, FocusTrap focuses the first focusable element. To focus a specific element, set data-autofocus attribute:

import { useDisclosure } from '@mantine/hooks'
import { FocusTrap, TextInput, Button, Box } from '@tidbcloud/uikit'
 
function Demo() {
  const [active, { toggle }] = useDisclosure(false)
 
  return (
    <Box maw={400} mx="auto">
      <Button onClick={toggle}>{active ? 'Deactivate' : 'Activate'} focus trap</Button>
 
      <FocusTrap active={active}>
        <div>
          <TextInput mt="sm" label="First input" placeholder="First input" />
          <TextInput mt="sm" label="Second input" placeholder="Second input" data-autofocus />
          <TextInput mt="sm" label="Third input" placeholder="Third input" />
        </div>
      </FocusTrap>
    </Box>
  )
}

FocusTrap.InitialFocus

Use FocusTrap.InitialFocus component when you need to define an initial focus element that is not a text input (e.g., a button):

import { useDisclosure } from '@mantine/hooks'
import { FocusTrap, TextInput, Button, Box } from '@tidbcloud/uikit'
 
function Demo() {
  const [active, { toggle }] = useDisclosure(false)
 
  return (
    <Box maw={400} mx="auto">
      <Button onClick={toggle}>{active ? 'Deactivate' : 'Activate'} focus trap</Button>
 
      <FocusTrap active={active}>
        <div>
          <FocusTrap.InitialFocus />
          <TextInput mt="sm" label="First input" placeholder="First input" />
          <TextInput mt="sm" label="Second input" placeholder="Second input" />
          <TextInput mt="sm" label="Third input" placeholder="Third input" />
        </div>
      </FocusTrap>
    </Box>
  )
}

useFocusTrap hook

useFocusTrap hook can be used to implement custom focus trap components:

import { useFocusTrap } from '@mantine/hooks'
import { TextInput, Button, Box } from '@tidbcloud/uikit'
 
function Demo() {
  const focusTrapRef = useFocusTrap()
 
  return (
    <Box maw={400} mx="auto" ref={focusTrapRef}>
      <TextInput mt="sm" label="First input" placeholder="First input" />
      <TextInput mt="sm" label="Second input" placeholder="Second input" data-autofocus />
      <TextInput mt="sm" label="Third input" placeholder="Third input" />
    </Box>
  )
}

Props

PropTypeDefaultDescription
activebooleantrueWhether focus trap is active
childrenReactNode-Content to trap focus within
refPropstring’ref’Prop name to pass ref to child