# useRovingFocus

Arrow-key navigation between the items of a toolbar, menu, tab list, listbox, or radio group, with a single Tab stop (a "roving tabindex"). Returns a callback ref for the container.

Tab enters the group at the last focused item (or the selected one, else the first) and Tab again leaves it. Arrow keys move between items, Home and End jump to the ends, and typing letters jumps to the item whose text starts with them. Left and Right swap in right-to-left content. Disabled and hidden items are skipped. Items added later are included.

## Import

```ts
import { useRovingFocus } from '@vincent.ri/react-tils'
// or only this hook
import { useRovingFocus } from '@vincent.ri/react-tils/useRovingFocus'
```

## Usage

```ts
const ref = useRovingFocus<HTMLDivElement>({ orientation: 'horizontal' })
return (
  <div ref={ref} role="toolbar" aria-label="Formatting">
    <button>Bold</button>
    <button>Italic</button>
    <button>Underline</button>
  </div>
)
```

## When to use it

A custom toolbar, menu, tab list, listbox, or segmented control.

## When not to

Native elements do it: radio buttons with the same `name`, and `<select>`. Don't set `tabIndex` on the items yourself; the hook manages it. Still add the ARIA roles (`role="toolbar"`, `role="tab"`, …) for screen readers. Two-dimensional grids need more than this.

## API

```ts
function useRovingFocus<T extends HTMLElement = HTMLElement>(options?: RovingFocusOptions): (element: T | null) => void
```

| Parameter | Description |
| --- | --- |
| `options` | `orientation`, `loop`, `typeahead`, `selector`. Optional. |

**Returns** A callback ref. Pass it to the container's `ref` prop.

### Types

```ts
export type RovingFocusOptions = {
  /** Which arrow keys move focus. Default `'vertical'` (Up/Down). */
  orientation?: "vertical" | "horizontal" | "both";
  /** Wrap from the last item to the first and back. Default `true`. */
  loop?: boolean;
  /** Typing letters moves to the next item whose text starts with them; repeating one letter cycles through matches. Default `true`. */
  typeahead?: boolean;
  /** Which elements inside the container are items. Default: buttons, links, and elements with an item role (`menuitem`, `option`, `tab`, `radio`, `treeitem`). */
  selector?: string;
};
```

## Browser support

Works in all modern browsers.

## Coming from another library?

Other libraries call this `useRovingTabIndex`.

---

838 B minified and brotlied
Source: https://github.com/vincentri/react-tils/blob/main/src/useRovingFocus.ts
Docs page: https://vincentri.github.io/react-tils/hooks/useRovingFocus/
Previous: [useTextSelection](https://vincentri.github.io/react-tils/hooks/useTextSelection.md)
Next: [useFocusTrap](https://vincentri.github.io/react-tils/hooks/useFocusTrap.md)
