Skip to content
Open
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
6df5cb8
init new hooks docs: useButton, useListBox, useSelect
reidbarber Jun 2, 2026
4d94c43
ts docs fix
reidbarber Jun 2, 2026
acfa1d2
fix links
reidbarber Jun 2, 2026
3b692b6
update useSelect example to use Button, Popover, and Listbox componen…
reidbarber Jun 3, 2026
658342e
add useComboBox docs
reidbarber Jun 8, 2026
2c02c66
add useMenu docs
reidbarber Jun 8, 2026
6cb6d52
add useDatePicker docs
reidbarber Jun 8, 2026
4167b75
add useDateRangePicker docs
reidbarber Jun 8, 2026
d106bf9
add usePopover docs
reidbarber Jun 8, 2026
4189ee1
add useModalOverlay docs
reidbarber Jun 8, 2026
39657ec
add useDIalog docs
reidbarber Jun 8, 2026
a4caa5d
add useTooltipTrigger docs
reidbarber Jun 8, 2026
b1e0915
add useCalendar docs
reidbarber Jun 8, 2026
2da1139
add useRangeCalendar docs
reidbarber Jun 8, 2026
bf9d337
add useDisclosure docs
reidbarber Jun 8, 2026
ad0d654
add useToolbar docs
reidbarber Jun 8, 2026
b77774d
add useToast docs
reidbarber Jun 8, 2026
27ad863
add useNumberField docs
reidbarber Jun 8, 2026
fe4dc45
add useSeparator docs
reidbarber Jun 8, 2026
6d098d7
add useLink docs
reidbarber Jun 8, 2026
e9ee7ac
add useBreadcrumbs docs
reidbarber Jun 8, 2026
d8a0ef7
add useMeter docs
reidbarber Jun 8, 2026
d104b44
add useProgressBar docs
reidbarber Jun 8, 2026
5c9782b
add useCheckbox docs
reidbarber Jun 8, 2026
1be2931
add useSwitch docs
reidbarber Jun 8, 2026
0e10bdf
add useToggleButton docs
reidbarber Jun 8, 2026
19cd14f
add useRadioGroup docs
reidbarber Jun 8, 2026
22ba183
add useCheckboxGroup docs
reidbarber Jun 8, 2026
aee45f1
add useToggleButtonGroup docs
reidbarber Jun 8, 2026
cc49fa3
add useTextField docs
reidbarber Jun 8, 2026
27d97c1
add useDateField docs
reidbarber Jun 8, 2026
8ae7262
add useTimeField docs
reidbarber Jun 8, 2026
351d380
add useSearchField docs
reidbarber Jun 8, 2026
5d5a566
add useSlider docs
reidbarber Jun 8, 2026
f3f11ed
add useColorSwatch docs
reidbarber Jun 8, 2026
a0e87b3
add useColorField docs
reidbarber Jun 8, 2026
976fd21
add useColorArea docs
reidbarber Jun 8, 2026
8d698c5
add useColorSlider docs
reidbarber Jun 8, 2026
bcad762
add useColorWheel docs
reidbarber Jun 8, 2026
331c413
add useTagGroup docs
reidbarber Jun 8, 2026
c4405ba
add useGridList docs
reidbarber Jun 8, 2026
6c35971
add useTable docs
reidbarber Jun 8, 2026
745b08c
add useDraggableCollection docs
reidbarber Jun 8, 2026
9b89a81
add useDroppableCollection docs
reidbarber Jun 8, 2026
95ff49d
Merge remote-tracking branch 'origin/main' into new-hook-docs
reidbarber Jun 8, 2026
2c4fd28
add <br /> between adjacent FunctionAPIs
reidbarber Jun 9, 2026
7de8271
add useTabList docs
reidbarber Jun 9, 2026
4a3e2f3
add useListFormatter docs
reidbarber Jun 9, 2026
3dc0411
add docs for composeRenderProps and useRenderProps to Customization page
reidbarber Jun 9, 2026
db48c7d
document focus containment behavior in useModalOverlay
reidbarber Jun 9, 2026
4d12892
add tags to Customization page
reidbarber Jun 9, 2026
af143c2
map hooks to component illustrations
reidbarber Jun 9, 2026
a3714da
Fix FunctionAPI, remove Features sections, add anatomy diagrams
reidbarber Jun 9, 2026
e47c3b1
update examples to use Typescript
reidbarber Jun 9, 2026
abbfafd
add hooks starter
reidbarber Jun 10, 2026
4dfeba7
clean up hooks starter
reidbarber Jun 11, 2026
b61199a
clean up hook docs
reidbarber Jun 11, 2026
caa94cb
Merge branch 'main' into new-hook-docs
reidbarber Jun 11, 2026
845d535
Merge branch 'main' into new-hook-docs
reidbarber Jun 22, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Breadcrumbs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Anatomy from '/packages/react-aria/docs/breadcrumbs/anatomy.svg';
import {InlineAlert, Heading, Content} from '@react-spectrum/s2';

export const tags = ['navigation'];
export const relatedPages = [{'title': 'useBreadcrumbs', 'url': 'Breadcrumbs/useBreadcrumbs.html'}];
export const relatedPages = [{'title': 'useBreadcrumbs', 'url': './Breadcrumbs/useBreadcrumbs'}];
export const description = 'Displays a hierarchy of links to the current page or resource in an application.';

# Breadcrumbs
Expand Down
111 changes: 111 additions & 0 deletions packages/dev/s2-docs/pages/react-aria/Breadcrumbs/useBreadcrumbs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{/* Copyright 2026 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '../../../src/Layout';
export default Layout;
import {FunctionAPI} from '../../../src/FunctionAPI';
import {InterfaceType} from '../../../src/types';
import docs from 'docs:@react-aria/breadcrumbs';

export const section = 'Hooks';
export const description = 'Provides the behavior and accessibility implementation for a breadcrumbs component.';
export const isSubpage = true;

# useBreadcrumbs

<PageDescription>{docs.exports.useBreadcrumbs.description}</PageDescription>

This example uses `useBreadcrumbs` for the navigation landmark and `useBreadcrumbItem` for each item, marking the last item as the current page.

```tsx render
"use client";
import React from 'react';
import {useBreadcrumbs, useBreadcrumbItem} from 'react-aria/useBreadcrumbs';
import {useFocusRing} from 'react-aria/useFocusRing';
import {mergeProps} from 'react-aria/mergeProps';
import 'vanilla-starter/theme.css';

function Breadcrumbs(props) {
let {navProps} = useBreadcrumbs(props);
let childCount = React.Children.count(props.children);

return (
<nav {...navProps}>
<ol style={{display: 'flex', listStyle: 'none', margin: 0, padding: 0, color: 'var(--text-color)'}}>
{React.Children.map(props.children, (child, i) =>
React.cloneElement(child, {isCurrent: i === childCount - 1})
)}
</ol>
</nav>
);
}

function BreadcrumbItem(props) {
let ref = React.useRef(null);
let {itemProps} = useBreadcrumbItem({...props, elementType: 'span'}, ref);
let {isFocusVisible, focusProps} = useFocusRing();

return (
<li>
<span
{...mergeProps(itemProps, focusProps)}
ref={ref}
style={{
color: props.isCurrent ? 'var(--text-color)' : 'var(--link-color)',
textDecoration: props.isCurrent ? 'none' : 'underline',
fontWeight: props.isCurrent ? 'bold' : 'normal',
cursor: props.isCurrent ? 'default' : 'pointer',
borderRadius: 4,
outline: isFocusVisible ? '2px solid var(--focus-ring-color)' : 'none',
outlineOffset: 2
}}>
{props.children}
</span>
{!props.isCurrent &&
<span aria-hidden="true" style={{padding: '0 8px'}}>{'›'}</span>}
</li>
);
}

<Breadcrumbs>
<BreadcrumbItem onPress={() => alert('Pressed Folder 1')}>Folder 1</BreadcrumbItem>
<BreadcrumbItem onPress={() => alert('Pressed Folder 2')}>Folder 2</BreadcrumbItem>
<BreadcrumbItem>Folder 3</BreadcrumbItem>
</Breadcrumbs>
```

## Features

Breadcrumbs provide a list of links to parent pages of the current page in hierarchical order. `useBreadcrumbs` and `useBreadcrumbItem` help implement these in an accessible way.

* Exposed to assistive technology as a navigation landmark region via ARIA
* The last item is automatically marked as the current page with `aria-current`
* Each item can be a link or a JavaScript handled press, with full keyboard, mouse, and touch support
* Support for disabled items

## API

<FunctionAPI function={docs.exports.useBreadcrumbs} links={docs.links} />
<FunctionAPI function={docs.exports.useBreadcrumbItem} links={docs.links} />

### AriaBreadcrumbsProps

<InterfaceType {...docs.exports.AriaBreadcrumbsProps} />

### BreadcrumbsAria

<InterfaceType {...docs.exports.BreadcrumbsAria} />

### AriaBreadcrumbItemProps

<InterfaceType {...docs.exports.AriaBreadcrumbItemProps} />

### BreadcrumbItemAria

<InterfaceType {...docs.exports.BreadcrumbItemAria} />
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import '../../tailwind/tailwind.css';
import typesDocs from 'docs:@react-types/shared/src/events.d.ts';

export const tags = ['btn'];
export const relatedPages = [{'title': 'useButton', 'url': 'Button/useButton.html'}];
export const relatedPages = [{'title': 'useButton', 'url': './Button/useButton'}];
export const description = 'Allows a user to perform an action, with mouse, touch, and keyboard interactions.';

# Button
Expand Down
76 changes: 76 additions & 0 deletions packages/dev/s2-docs/pages/react-aria/Button/useButton.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{/* Copyright 2026 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '../../../src/Layout';
export default Layout;
import {FunctionAPI} from '../../../src/FunctionAPI';
import {InterfaceType} from '../../../src/types';
import docs from 'docs:@react-aria/button';

export const section = 'Hooks';
export const description = 'Provides the behavior and accessibility implementation for a button.';
export const isSubpage = true;

# useButton

<PageDescription>{docs.exports.useButton.description}</PageDescription>

```tsx render
"use client";
import React from 'react';
import {useButton} from 'react-aria/useButton';

function Button(props) {
let ref = React.useRef(null);
let {buttonProps, isPressed} = useButton(props, ref);

return (
<button
{...buttonProps}
ref={ref}
style={{
Comment thread
reidbarber marked this conversation as resolved.
Outdated
background: isPressed ? 'darkgreen' : 'green',
color: 'white',
border: 'none',
padding: '8px 12px',
borderRadius: 8,
fontSize: 14,
cursor: 'pointer'
}}>
{props.children}
</button>
);
}

<Button onPress={() => alert('Button pressed!')}>Press me</Button>
```

## Features
Comment thread
reidbarber marked this conversation as resolved.
Outdated

On the surface, building a custom styled button seems simple. However, there are many cross browser inconsistencies in interactions and accessibility features to consider. `useButton` handles all of these interactions for you, so you can focus on the styling. It follows the [ARIA button pattern](https://www.w3.org/WAI/ARIA/apg/patterns/button/).

* Native HTML `<button>` support
* `<a>` and custom element type support via ARIA
* Mouse and touch event handling, and press state management
* Keyboard focus management and cross browser normalization
* Keyboard event support for <Keyboard>Space</Keyboard> and <Keyboard>Enter</Keyboard> keys

Read our [blog post](../blog/building-a-button-part-1) about the complexities of building buttons that work well across devices and interaction methods.

## API

<FunctionAPI function={docs.exports.useButton} links={docs.links} />

### AriaButtonProps

<InterfaceType {...docs.exports.AriaButtonProps} />

### ButtonAria

<InterfaceType {...docs.exports.ButtonAria} />
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Calendar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import '../../tailwind/tailwind.css';
import Anatomy from '/packages/react-aria/docs/calendar/calendar-anatomy.svg';

export const tags = ['date'];
export const relatedPages = [{'title': 'useCalendar', 'url': 'Calendar/useCalendar.html'}];
export const relatedPages = [{'title': 'useCalendar', 'url': './Calendar/useCalendar'}];
export const description = 'Displays one or more date grids and allows users to select a single date.';

# Calendar
Expand Down
166 changes: 166 additions & 0 deletions packages/dev/s2-docs/pages/react-aria/Calendar/useCalendar.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
{/* Copyright 2026 Adobe. All rights reserved.
This file is licensed to you under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. You may obtain a copy
of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License. */}

import {Layout} from '../../../src/Layout';
export default Layout;
import {FunctionAPI} from '../../../src/FunctionAPI';
import {InterfaceType} from '../../../src/types';
import docs from 'docs:@react-aria/calendar';

export const section = 'Hooks';
export const description = 'Provides the behavior and accessibility implementation for a calendar component.';
export const isSubpage = true;

# useCalendar

<PageDescription>{docs.exports.useCalendar.description}</PageDescription>

A calendar is built from scratch with `useCalendar`, `useCalendarGrid`, and `useCalendarCell`, since those hooks are the calendar primitives. The previous and next navigation buttons reuse the [Button](../Button) component from React Aria Components.

```tsx render
Comment thread
reidbarber marked this conversation as resolved.
Outdated
"use client";
import React from 'react';
import {useCalendar, useCalendarGrid, useCalendarCell} from 'react-aria/useCalendar';
import {useCalendarState} from 'react-stately/useCalendarState';
import {useLocale} from 'react-aria/I18nProvider';
import {useFocusRing} from 'react-aria/useFocusRing';
import {mergeProps} from 'react-aria/mergeProps';
import {createCalendar} from '@internationalized/date';
import {Button} from 'vanilla-starter/Button';
import {ChevronLeft, ChevronRight} from 'lucide-react';
import 'vanilla-starter/Button.css';

function Calendar(props) {
Comment thread
reidbarber marked this conversation as resolved.
Outdated
// useCalendarState handles date manipulation across calendar systems.
let {locale} = useLocale();
let state = useCalendarState({...props, locale, createCalendar});
let {calendarProps, prevButtonProps, nextButtonProps, title} = useCalendar(props, state);

return (
<div {...calendarProps} style={{width: 280}}>
<div style={{display: 'flex', alignItems: 'center', gap: 8, marginBottom: 8}}>
<Button {...prevButtonProps} variant="quiet"><ChevronLeft /></Button>
<h2 style={{flex: 1, margin: 0, textAlign: 'center', fontSize: 'var(--font-size-lg)'}}>{title}</h2>
<Button {...nextButtonProps} variant="quiet"><ChevronRight /></Button>
</div>
<CalendarGrid state={state} />
</div>
);
}

function CalendarGrid({state, ...props}) {
// useCalendarGrid renders the table of dates for a single month.
let {gridProps, headerProps, weekDays, weeksInMonth} = useCalendarGrid(props, state);

return (
<table {...gridProps} style={{width: '100%', borderCollapse: 'collapse'}}>
<thead {...headerProps}>
<tr>
{weekDays.map((day, i) => (
<th key={i} style={{fontWeight: 'normal', fontSize: 'var(--font-size-sm)', color: 'var(--text-color-placeholder)'}}>{day}</th>
))}
</tr>
</thead>
<tbody>
{[...new Array(weeksInMonth).keys()].map(weekIndex => (
<tr key={weekIndex}>
{state.getDatesInWeek(weekIndex).map((date, i) => (
date
? <CalendarCell key={i} state={state} date={date} />
: <td key={i} />
))}
</tr>
))}
</tbody>
</table>
);
}

function CalendarCell({state, date}) {
// useCalendarCell provides the props and state for an individual date cell.
let ref = React.useRef(null);
let {cellProps, buttonProps, isSelected, isOutsideVisibleRange, isDisabled, formattedDate} =
useCalendarCell({date}, state, ref);

// Show a focus ring when the cell is focused via the keyboard.
let {focusProps, isFocusVisible} = useFocusRing();

return (
<td {...cellProps} style={{textAlign: 'center', padding: 0}}>
<div
{...mergeProps(buttonProps, focusProps)}
ref={ref}
hidden={isOutsideVisibleRange}
style={{
width: 32,
height: 32,
lineHeight: '32px',
margin: '2px auto',
borderRadius: '50%',
cursor: 'default',
outline: isFocusVisible ? '2px solid var(--focus-ring-color)' : 'none',
outlineOffset: 2,
background: isSelected ? 'var(--highlight-background)' : 'transparent',
color: isSelected ? 'var(--highlight-foreground)' : isDisabled ? 'var(--text-color-disabled)' : 'var(--text-color)'
}}>
{formattedDate}
</div>
</td>
);
}

<Calendar aria-label="Event date" />
```

## Features

There is no standalone calendar element in HTML. `useCalendar` helps achieve accessible calendar and date picker components that can be styled as needed.

* Support for selecting a single date
* Support for 13 calendar systems used around the world, including Gregorian, Buddhist, Islamic, Persian, and more
* Locale-specific formatting, number systems, and right-to-left support
* Date values are provided using objects from the [@internationalized/date](../internationalized/date/) library
* Support for minimum and maximum values, disabled and unavailable dates
* Localized screen reader messages announce the selected and visible date ranges
* Keyboard navigation between dates with arrow keys, including wrapping and validation
* Full keyboard and screen reader accessibility following the [ARIA grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/)

## State management
Comment thread
reidbarber marked this conversation as resolved.
Outdated

`useCalendar` requires a `state` object created with the `useCalendarState` hook from `react-stately`, which holds the selected date and visible date range, and exposes methods to navigate between months. `useCalendarState` requires a `createCalendar` function from [@internationalized/date](../internationalized/date/), which implements date manipulation across calendar systems.

## API

<FunctionAPI function={docs.exports.useCalendar} links={docs.links} />
<FunctionAPI function={docs.exports.useCalendarGrid} links={docs.links} />
<FunctionAPI function={docs.exports.useCalendarCell} links={docs.links} />

### AriaCalendarProps

<InterfaceType {...docs.exports.AriaCalendarProps} />

### CalendarAria

<InterfaceType {...docs.exports.CalendarAria} />

### AriaCalendarGridProps

<InterfaceType {...docs.exports.AriaCalendarGridProps} />

### CalendarGridAria

<InterfaceType {...docs.exports.CalendarGridAria} />

### AriaCalendarCellProps

<InterfaceType {...docs.exports.AriaCalendarCellProps} />

### CalendarCellAria

<InterfaceType {...docs.exports.CalendarCellAria} />
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Checkbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import '../../tailwind/tailwind.css';
import Anatomy from '/packages/react-aria/docs/checkbox/checkbox-anatomy.svg';

export const tags = ['input'];
export const relatedPages = [{'title': 'useCheckbox', 'url': 'Checkbox/useCheckbox.html'}];
export const relatedPages = [{'title': 'useCheckbox', 'url': './Checkbox/useCheckbox'}];
export const description = 'Allows a user to select multiple items from a list of individual items, or to mark one individual item as selected.';

# Checkbox
Expand Down
Loading