-
Notifications
You must be signed in to change notification settings - Fork 1.5k
docs: add new React Aria hooks docs #10153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
reidbarber
wants to merge
59
commits into
main
Choose a base branch
from
new-hook-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
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 4d94c43
ts docs fix
reidbarber acfa1d2
fix links
reidbarber 3b692b6
update useSelect example to use Button, Popover, and Listbox componen…
reidbarber 658342e
add useComboBox docs
reidbarber 2c02c66
add useMenu docs
reidbarber 6cb6d52
add useDatePicker docs
reidbarber 4167b75
add useDateRangePicker docs
reidbarber d106bf9
add usePopover docs
reidbarber 4189ee1
add useModalOverlay docs
reidbarber 39657ec
add useDIalog docs
reidbarber a4caa5d
add useTooltipTrigger docs
reidbarber b1e0915
add useCalendar docs
reidbarber 2da1139
add useRangeCalendar docs
reidbarber bf9d337
add useDisclosure docs
reidbarber ad0d654
add useToolbar docs
reidbarber b77774d
add useToast docs
reidbarber 27ad863
add useNumberField docs
reidbarber fe4dc45
add useSeparator docs
reidbarber 6d098d7
add useLink docs
reidbarber e9ee7ac
add useBreadcrumbs docs
reidbarber d8a0ef7
add useMeter docs
reidbarber d104b44
add useProgressBar docs
reidbarber 5c9782b
add useCheckbox docs
reidbarber 1be2931
add useSwitch docs
reidbarber 0e10bdf
add useToggleButton docs
reidbarber 19cd14f
add useRadioGroup docs
reidbarber 22ba183
add useCheckboxGroup docs
reidbarber aee45f1
add useToggleButtonGroup docs
reidbarber cc49fa3
add useTextField docs
reidbarber 27d97c1
add useDateField docs
reidbarber 8ae7262
add useTimeField docs
reidbarber 351d380
add useSearchField docs
reidbarber 5d5a566
add useSlider docs
reidbarber f3f11ed
add useColorSwatch docs
reidbarber a0e87b3
add useColorField docs
reidbarber 976fd21
add useColorArea docs
reidbarber 8d698c5
add useColorSlider docs
reidbarber bcad762
add useColorWheel docs
reidbarber 331c413
add useTagGroup docs
reidbarber c4405ba
add useGridList docs
reidbarber 6c35971
add useTable docs
reidbarber 745b08c
add useDraggableCollection docs
reidbarber 9b89a81
add useDroppableCollection docs
reidbarber 95ff49d
Merge remote-tracking branch 'origin/main' into new-hook-docs
reidbarber 2c4fd28
add <br /> between adjacent FunctionAPIs
reidbarber 7de8271
add useTabList docs
reidbarber 4a3e2f3
add useListFormatter docs
reidbarber 3dc0411
add docs for composeRenderProps and useRenderProps to Customization page
reidbarber db48c7d
document focus containment behavior in useModalOverlay
reidbarber 4d12892
add tags to Customization page
reidbarber af143c2
map hooks to component illustrations
reidbarber a3714da
Fix FunctionAPI, remove Features sections, add anatomy diagrams
reidbarber e47c3b1
update examples to use Typescript
reidbarber abbfafd
add hooks starter
reidbarber 4dfeba7
clean up hooks starter
reidbarber b61199a
clean up hook docs
reidbarber caa94cb
Merge branch 'main' into new-hook-docs
reidbarber 845d535
Merge branch 'main' into new-hook-docs
reidbarber File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
packages/dev/s2-docs/pages/react-aria/Breadcrumbs/useBreadcrumbs.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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} /> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
packages/dev/s2-docs/pages/react-aria/Button/useButton.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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={{ | ||
| 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 | ||
|
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} /> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
166 changes: 166 additions & 0 deletions
166
packages/dev/s2-docs/pages/react-aria/Calendar/useCalendar.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
|
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) { | ||
|
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 | ||
|
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} /> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.