Skip to content

Commit b68cb41

Browse files
committed
Add useAutocomplete docs
1 parent f484f9b commit b68cb41

File tree

2 files changed

+117
-126
lines changed

2 files changed

+117
-126
lines changed

packages/@react-aria/autocomplete/docs/useAutocomplete.mdx

+116-125
Original file line numberDiff line numberDiff line change
@@ -64,147 +64,138 @@ The state object should be passed as an option to `useAutocomplete`.
6464

6565
## Example
6666

67-
```tsx example export=true
68-
import {Item} from '@react-stately/collections';
69-
import {useButton} from '@react-aria/button';
70-
import {useAutocompleteState} from '@react-stately/autocomplete'
71-
import {useAutocomplete} from '@react-aria/autocomplete';
72-
import {useFilter} from '@react-aria/i18n';
73-
import {UNSTABLE_useFilteredListState} from '@react-stately/list';
74-
75-
// Reuse the ListBox, Popover, and Button from your component library. See below for details.
76-
import {ListBox} from 'your-component-library';
77-
78-
function Autocomplete(props) {
79-
// Setup filter function and state.
80-
let {contains} = useFilter({sensitivity: 'base'});
81-
let state = useAutocompleteState(props);
67+
```tsx example
68+
import {AriaAutocompleteProps, CollectionOptions, useAutocomplete} from '@react-aria/autocomplete';
69+
import {AutocompleteState, useAutocompleteState} from '@react-stately/autocomplete';
70+
import {mergeProps} from '@react-aria/utils';
71+
import React, {createContext, RefObject, useRef} from 'react';
72+
import {
73+
Label,
74+
Text,
75+
InputContext,
76+
Input,
77+
Provider,
78+
SlotProps,
79+
SlottedContextValue,
80+
useSlottedContext,
81+
SearchFieldContext,
82+
SearchField,
83+
ListBox,
84+
ListBoxItem,
85+
useFilter,
86+
UNSTABLE_InternalAutocompleteContext
87+
} from 'react-aria-components'
88+
89+
interface AutocompleteProps extends AriaAutocompleteProps, SlotProps {}
90+
91+
interface InternalAutocompleteContextValue {
92+
filter?: (nodeTextValue: string) => boolean,
93+
collectionProps: CollectionOptions,
94+
collectionRef: RefObject<HTMLElement | null>
95+
}
8296

83-
// Setup refs and get props for child elements.
84-
let ref = React.useRef(null);
85-
let inputRef = React.useRef(null);
86-
87-
let {textFieldProps, collectionProps, collectionRef, filter} = useAutocomplete(
88-
{
89-
...props,
90-
inputRef,
91-
collectionRef: ref,
92-
filter: contains,
93-
},
94-
state
95-
);
97+
const AutocompleteContext = createContext<SlottedContextValue<Partial<AutocompleteProps>>>(null);
98+
const AutocompleteStateContext = createContext<AutocompleteState | null>(null);
99+
100+
function Autocomplete(props: AutocompleteProps) {
101+
let {contains} = useFilter({ sensitivity: 'base' });
102+
let filter = (textValue, inputValue) => contains(textValue, inputValue);
103+
let ctx = useSlottedContext(AutocompleteContext, props.slot);
104+
props = mergeProps(ctx, props);
105+
let {disableAutoFocusFirst} = props;
106+
let state = useAutocompleteState(props);
107+
let inputRef = useRef<HTMLInputElement | null>(null);
108+
let collectionRef = useRef<HTMLElement>(null);
109+
let {
110+
textFieldProps,
111+
collectionProps,
112+
collectionRef: mergedCollectionRef,
113+
filter: filterFn
114+
} = useAutocomplete({
115+
...props,
116+
filter,
117+
disableAutoFocusFirst,
118+
inputRef,
119+
collectionRef
120+
}, state);
96121

97122
return (
98-
<div style={{display: 'inline-flex', flexDirection: 'column'}}>
99-
<label>{props.label}</label>
100-
<div>
101-
<input
102-
{...textFieldProps}
103-
ref={inputRef}
104-
style={{
105-
height: 24,
106-
boxSizing: 'border-box',
107-
marginRight: 0,
108-
fontSize: 16
109-
}} />
110-
<ListBox
111-
{...collectionProps}
112-
filter={filter}
113-
listBoxRef={collectionRef}
114-
state={state}>
115-
{props.children}
116-
</ListBox>
117-
</div>
118-
</div>
123+
<Provider
124+
values={[
125+
[AutocompleteStateContext, state],
126+
[SearchFieldContext, textFieldProps],
127+
[InputContext, {ref: inputRef}],
128+
[UNSTABLE_InternalAutocompleteContext, {
129+
filter: filterFn,
130+
collectionProps,
131+
collectionRef: mergedCollectionRef
132+
}]
133+
]}>
134+
{props.children}
135+
</Provider>
119136
);
120-
}
121-
122-
<Autocomplete label="Favorite Animal">
123-
<Item key="red panda">Red Panda</Item>
124-
<Item key="cat">Cat</Item>
125-
<Item key="dog">Dog</Item>
126-
<Item key="aardvark">Aardvark</Item>
127-
<Item key="kangaroo">Kangaroo</Item>
128-
<Item key="snake">Snake</Item>
129-
</Autocomplete>
137+
};
138+
139+
<div className="autocomplete">
140+
<Autocomplete>
141+
<SearchField>
142+
<Label>Favorite animal</Label>
143+
<Input />
144+
<Text slot="description">Please select a pet below.</Text>
145+
</SearchField>
146+
<ListBox selectionMode="single" aria-label="Possible pets">
147+
<ListBoxItem id="red panda">Red Panda</ListBoxItem>
148+
<ListBoxItem id="cat">Cat</ListBoxItem>
149+
<ListBoxItem id="dog">Dog</ListBoxItem>
150+
<ListBoxItem id="aardvark">Aardvark</ListBoxItem>
151+
<ListBoxItem id="kangaroo">Kangaroo</ListBoxItem>
152+
<ListBoxItem id="snake">Snake</ListBoxItem>
153+
</ListBox>
154+
</Autocomplete>
155+
</div>
130156
```
131157

132-
133-
### ListBox
134-
135-
The `ListBox` and `Option` components are used to show the filtered list of options as the
136-
user types in the ComboBox. They can also be shared with other components like a [Select](useSelect.html). See
137-
[useListBox](useListBox.html) for more examples, including sections and more complex items.
138-
139158
<details>
140-
<summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show code</summary>
141-
142-
```tsx example export=true render=false
143-
import {useListBox, useOption} from '@react-aria/listbox';
144-
145-
function ListBox(props) {
146-
let {listBoxRef, state} = props;
147-
let newState = UNSTABLE_useFilteredListState(state, props.filter);
148-
let {listBoxProps} = useListBox(props, newState, listBoxRef);
159+
<summary style={{fontWeight: 'bold'}}><ChevronRight size="S" /> Show CSS</summary>
160+
```css hidden
161+
@import '../../../react-aria-components/docs/Checkbox.mdx' layer(checkbox);
162+
@import '../../../react-aria-components/docs/SearchField.mdx' layer(searchfield);
163+
@import '../../../react-aria-components/docs/ListBox.mdx' layer(listbox);
164+
```
149165

150-
return (
151-
<ul
152-
{...listBoxProps}
153-
ref={listBoxRef}
154-
style={{
155-
margin: 0,
156-
padding: 0,
157-
listStyle: "none",
158-
maxHeight: 150,
159-
overflow: "auto",
160-
minWidth: 200
161-
}}>
162-
{[...newState.collection].map(item => (
163-
<Option
164-
key={item.key}
165-
item={item}
166-
state={state} />
167-
))}
168-
</ul>
169-
);
170-
}
166+
```css
167+
@import "@react-aria/example-theme";
168+
169+
.autocomplete {
170+
display: flex;
171+
flex-direction: column;
172+
gap: 12px;
173+
max-width: 300px;
174+
height: 180px;
175+
border: 1px solid var(--border-color);
176+
padding: 16px;
177+
border-radius: 10px;
178+
background: var(--overlay-background);
179+
180+
.react-aria-SearchField {
181+
width: 100%;
182+
}
171183

172-
function Option({item, state}) {
173-
let ref = React.useRef(null);
174-
let {optionProps, isSelected, isFocused, isDisabled} = useOption({key: item.key}, state, ref);
175-
176-
let backgroundColor;
177-
let color = 'black';
178-
179-
if (isSelected) {
180-
backgroundColor = 'blueviolet';
181-
color = 'white';
182-
} else if (isFocused) {
183-
backgroundColor = 'gray';
184-
} else if (isDisabled) {
185-
backgroundColor = 'transparent';
186-
color = 'gray';
184+
.react-aria-ListBox {
185+
flex: 1;
186+
overflow: auto;
187187
}
188188

189-
return (
190-
<li
191-
{...optionProps}
192-
ref={ref}
193-
style={{
194-
background: backgroundColor,
195-
color: color,
196-
padding: '2px 5px',
197-
outline: 'none',
198-
cursor: 'pointer'
199-
}}>
200-
{item.rendered}
201-
</li>
202-
);
189+
.react-aria-Label {
190+
margin-bottom: .5em;
191+
}
203192
}
204193
```
205194

206195
</details>
207196

197+
198+
208199
## Internationalization
209200

210201
`useAutocomplete` handles some aspects of internationalization automatically.

packages/react-aria-components/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import 'client-only';
1616

1717
export {CheckboxContext, ColorAreaContext, ColorFieldContext, ColorSliderContext, ColorWheelContext, HeadingContext} from './RSPContexts';
1818

19-
export {Autocomplete, AutocompleteContext, AutocompleteStateContext} from './Autocomplete';
19+
export {Autocomplete, AutocompleteContext, AutocompleteStateContext, UNSTABLE_InternalAutocompleteContext} from './Autocomplete';
2020
export {Breadcrumbs, BreadcrumbsContext, Breadcrumb} from './Breadcrumbs';
2121
export {Button, ButtonContext} from './Button';
2222
export {Calendar, CalendarGrid, CalendarGridHeader, CalendarGridBody, CalendarHeaderCell, CalendarCell, RangeCalendar, CalendarContext, RangeCalendarContext, CalendarStateContext, RangeCalendarStateContext} from './Calendar';

0 commit comments

Comments
 (0)