useToolbar
Provides the behavior and accessibility implementation for a toolbar. A toolbar is a container for a set of interactive controls with arrow key navigation.
install | yarn add @react-aria/toolbar |
---|---|
version | 3.0.0-beta.10 |
usage | import {useToolbar} from '@react-aria/toolbar' |
API#
useToolbar(
(props: AriaToolbarProps,
, ref: RefObject<HTMLElement
| | null>
)): ToolbarAria
Features#
There is no native element to implement a toolbar in HTML. useToolbar
helps achieve accessible toolbar components that can be styled as needed.
- Exposed to assistive technology as a
toolbar
element via ARIA - Support for arrow key navigation
- Support for both horizontal and vertical orientations
- Support for interactive children including button, toggle button, menu, checkbox, and link
- Automatic scrolling support during keyboard navigation
Anatomy#
A toolbar consists of a container element for a set of interactive controls.
useToolbar
handles exposing this to assistive technology using ARIA, along with
handling arrow key navigation between children.
useToolbar
returns props that you should spread onto the appropriate element:
Name | Type | Description |
toolbarProps | HTMLAttributes<HTMLElement> | Props for the toolbar container. |
An aria-label
or aria-labelledby
prop must be provided to identify the toolbar to assistive technology.
Example#
Toolbar#
This example uses the useToolbar
hook, spread on a container to handle
navigation of components inside it.
import {useToolbar} from '@react-aria/toolbar';
import {useRef} from 'react';
// Reuse the Button from your component library. See below for details.
import {Button} from 'your-component-library';
function Toolbar(props) {
let ref = useRef<HTMLDivElement | null>(null);
// Get props for the toolbar element
let {toolbarProps} = useToolbar(props, ref);
return (
<div {...toolbarProps} ref={ref}>
{props.children}
</div>
);
}
<Toolbar aria-label="Actions">
<Button>Copy</Button>
<Button>Cut</Button>
<Button>Paste</Button>
</Toolbar>
import {useToolbar} from '@react-aria/toolbar';
import {useRef} from 'react';
// Reuse the Button from your component library. See below for details.
import {Button} from 'your-component-library';
function Toolbar(props) {
let ref = useRef<HTMLDivElement | null>(null);
// Get props for the toolbar element
let { toolbarProps } = useToolbar(props, ref);
return (
<div {...toolbarProps} ref={ref}>
{props.children}
</div>
);
}
<Toolbar aria-label="Actions">
<Button>Copy</Button>
<Button>Cut</Button>
<Button>Paste</Button>
</Toolbar>
import {useToolbar} from '@react-aria/toolbar';
import {useRef} from 'react';
// Reuse the Button from your component library. See below for details.
import {Button} from 'your-component-library';
function Toolbar(props) {
let ref = useRef<
HTMLDivElement | null
>(null);
// Get props for the toolbar element
let { toolbarProps } =
useToolbar(
props,
ref
);
return (
<div
{...toolbarProps}
ref={ref}
>
{props.children}
</div>
);
}
<Toolbar aria-label="Actions">
<Button>Copy</Button>
<Button>Cut</Button>
<Button>
Paste
</Button>
</Toolbar>
Show CSS
[role=toolbar] {
--separator-color: var(--spectrum-global-color-gray-500);
display: flex;
flex-wrap: wrap;
gap: 5px;
}
[role=toolbar] {
--separator-color: var(--spectrum-global-color-gray-500);
display: flex;
flex-wrap: wrap;
gap: 5px;
}
[role=toolbar] {
--separator-color: var(--spectrum-global-color-gray-500);
display: flex;
flex-wrap: wrap;
gap: 5px;
}
Button#
The Button
component is used in the above example as an interactive child. It is built using the useButton hook, and can be shared with many other components.
Show code
import {useButton} from '@react-aria/button';
function Button(props) {
let {children} = props;
let ref = useRef<HTMLButtonElement | null>(null);
let {buttonProps, isPressed} = useButton({
...props,
elementType: 'span'
}, ref);
return (
<span
{...buttonProps}
style={{
background: isPressed ? '#bbb' : '#aaa',
color: 'black',
cursor: 'default',
padding: '5px 10px'
}}
ref={ref}>
{children}
</span>
);
}
import {useButton} from '@react-aria/button';
function Button(props) {
let {children} = props;
let ref = useRef<HTMLButtonElement | null>(null);
let {buttonProps, isPressed} = useButton({
...props,
elementType: 'span'
}, ref);
return (
<span
{...buttonProps}
style={{
background: isPressed ? '#bbb' : '#aaa',
color: 'black',
cursor: 'default',
padding: '5px 10px'
}}
ref={ref}>
{children}
</span>
);
}
import {useButton} from '@react-aria/button';
function Button(props) {
let { children } =
props;
let ref = useRef<
| HTMLButtonElement
| null
>(null);
let {
buttonProps,
isPressed
} = useButton({
...props,
elementType: 'span'
}, ref);
return (
<span
{...buttonProps}
style={{
background:
isPressed
? '#bbb'
: '#aaa',
color: 'black',
cursor:
'default',
padding:
'5px 10px'
}}
ref={ref}
>
{children}
</span>
);
}
Internationalization#
You are responsible for localizing all labels, both for the toolbar itself as well as all the content that is passed into the toolbar.
RTL#
In right-to-left languages, the toolbar should be mirrored both at the toolbar level as well as inside groups as appropriate. Ensure that your CSS accounts for this.