Skip to content

Commit aefa248

Browse files
authored
docs: Add examples for Autocomplete and Select with TagGroup (#9068)
* Update Autocomplete examples * Add Select + TagGroup example
1 parent d169afa commit aefa248

22 files changed

+1418
-213
lines changed

packages/dev/s2-docs/pages/react-aria/Autocomplete.mdx

Lines changed: 1046 additions & 46 deletions
Large diffs are not rendered by default.

packages/dev/s2-docs/pages/react-aria/GridList.mdx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,10 @@ export const tags = ['list view'];
1414
<PageDescription>{docs.exports.GridList.description}</PageDescription>
1515

1616
<ExampleSwitcher>
17-
```tsx render docs={docs.exports.GridList} links={docs.links} props={['layout', 'selectionMode']} initialProps={{'aria-label': 'Favorite pokemon', selectionMode: 'multiple', layout: 'grid'}} type="vanilla" files={["starters/docs/src/GridList.tsx", "starters/docs/src/GridList.css"]}
17+
```tsx render docs={docs.exports.GridList} links={docs.links} props={['layout', 'selectionMode']} initialProps={{'aria-label': 'Photos', selectionMode: 'multiple', layout: 'grid'}} type="vanilla" files={["starters/docs/src/GridList.tsx", "starters/docs/src/GridList.css"]}
1818
"use client";
1919
import {Text} from 'react-aria-components';
2020
import {GridList, GridListItem} from 'vanilla-starter/GridList';
21-
import {Button} from 'vanilla-starter/Button';
2221

2322
<GridList/* PROPS */>
2423
<GridListItem textValue="Desert Sunset">
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.multi-select {
2+
.react-aria-Group {
3+
display: flex;
4+
gap: var(--spacing-2);
5+
align-items: center;
6+
width: 250px;
7+
padding: var(--spacing-2);
8+
padding-inline-start: 8px;
9+
box-sizing: border-box;
10+
border: 0.5px solid var(--border-color);
11+
border-radius: var(--radius);
12+
background: var(--gray-50);
13+
}
14+
15+
.react-aria-Button.react-aria-Button {
16+
width: var(--spacing-6);
17+
height: var(--spacing-6);
18+
}
19+
}

packages/dev/s2-docs/pages/react-aria/Select.mdx

Lines changed: 119 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ function Example() {
114114

115115
return (
116116
<Select>
117-
<Label>Add tag...</Label>
117+
<Label>Category</Label>
118118
<Button>
119119
<SelectValue />
120120
<ChevronDown size={18} />
@@ -142,6 +142,124 @@ function Example() {
142142
}
143143
```
144144

145+
### TagGroup
146+
147+
Use the `SelectValue` render prop function to display the selected items as a [TagGroup](TagGroup.html).
148+
149+
```tsx render files={['packages/dev/s2-docs/pages/react-aria/MultiSelect.css']}
150+
"use client";
151+
import {Autocomplete, Select, SelectValue, Group, useFilter} from 'react-aria-components';
152+
import {Button} from 'vanilla-starter/Button';
153+
import {ListBox, DropdownItem} from 'vanilla-starter/ListBox';
154+
import {Label} from 'vanilla-starter/Form';
155+
import {Popover} from 'vanilla-starter/Popover';
156+
import {Plus} from 'lucide-react';
157+
import {SearchField} from 'vanilla-starter/SearchField';
158+
import {Tag, TagGroup} from 'vanilla-starter/TagGroup';
159+
import {useRef} from 'react';
160+
import './MultiSelect.css';
161+
162+
/*- begin collapse -*/
163+
const states = [
164+
{id: 'AL', name: 'Alabama'},
165+
{id: 'AK', name: 'Alaska'},
166+
{id: 'AZ', name: 'Arizona'},
167+
{id: 'AR', name: 'Arkansas'},
168+
{id: 'CA', name: 'California'},
169+
{id: 'CO', name: 'Colorado'},
170+
{id: 'CT', name: 'Connecticut'},
171+
{id: 'DE', name: 'Delaware'},
172+
{id: 'DC', name: 'District of Columbia'},
173+
{id: 'FL', name: 'Florida'},
174+
{id: 'GA', name: 'Georgia'},
175+
{id: 'HI', name: 'Hawaii'},
176+
{id: 'ID', name: 'Idaho'},
177+
{id: 'IL', name: 'Illinois'},
178+
{id: 'IN', name: 'Indiana'},
179+
{id: 'IA', name: 'Iowa'},
180+
{id: 'KS', name: 'Kansas'},
181+
{id: 'KY', name: 'Kentucky'},
182+
{id: 'LA', name: 'Louisiana'},
183+
{id: 'ME', name: 'Maine'},
184+
{id: 'MD', name: 'Maryland'},
185+
{id: 'MA', name: 'Massachusetts'},
186+
{id: 'MI', name: 'Michigan'},
187+
{id: 'MN', name: 'Minnesota'},
188+
{id: 'MS', name: 'Mississippi'},
189+
{id: 'MO', name: 'Missouri'},
190+
{id: 'MT', name: 'Montana'},
191+
{id: 'NE', name: 'Nebraska'},
192+
{id: 'NV', name: 'Nevada'},
193+
{id: 'NH', name: 'New Hampshire'},
194+
{id: 'NJ', name: 'New Jersey'},
195+
{id: 'NM', name: 'New Mexico'},
196+
{id: 'NY', name: 'New York'},
197+
{id: 'NC', name: 'North Carolina'},
198+
{id: 'ND', name: 'North Dakota'},
199+
{id: 'OH', name: 'Ohio'},
200+
{id: 'OK', name: 'Oklahoma'},
201+
{id: 'OR', name: 'Oregon'},
202+
{id: 'PA', name: 'Pennsylvania'},
203+
{id: 'RI', name: 'Rhode Island'},
204+
{id: 'SC', name: 'South Carolina'},
205+
{id: 'SD', name: 'South Dakota'},
206+
{id: 'TN', name: 'Tennessee'},
207+
{id: 'TX', name: 'Texas'},
208+
{id: 'UT', name: 'Utah'},
209+
{id: 'VT', name: 'Vermont'},
210+
{id: 'VA', name: 'Virginia'},
211+
{id: 'WA', name: 'Washington'},
212+
{id: 'WV', name: 'West Virginia'},
213+
{id: 'WI', name: 'Wisconsin'},
214+
{id: 'WY', name: 'Wyoming'}
215+
];
216+
/*- end collapse -*/
217+
218+
function SelectWithTagGroup() {
219+
let triggerRef = useRef<HTMLDivElement | null>(null);
220+
let {contains} = useFilter({sensitivity: 'base'});
221+
222+
return (
223+
<Select selectionMode="multiple" className="multi-select">
224+
<Label>States</Label>
225+
<Group aria-label="States" ref={triggerRef}>
226+
{/*- begin highlight -*/}
227+
<SelectValue<typeof states[0]> style={{flex: 1}}>
228+
{({selectedItems, state}) => (
229+
<TagGroup
230+
aria-label="Selected states"
231+
items={selectedItems.filter(item => item != null)}
232+
renderEmptyState={() => 'No selected items'}
233+
onRemove={(keys) => {
234+
// Remove keys from Select state.
235+
if (Array.isArray(state.value)) {
236+
state.setValue(state.value.filter(k => !keys.has(k)));
237+
}
238+
}}>
239+
{item => <Tag>{item.name}</Tag>}
240+
</TagGroup>
241+
)}
242+
</SelectValue>
243+
{/*- end highlight -*/}
244+
<Button variant="primary"><Plus /></Button>
245+
</Group>
246+
<Popover
247+
// Position popover relative to the wrapping div instead of the Button
248+
triggerRef={triggerRef}
249+
hideArrow
250+
style={{display: 'flex', flexDirection: 'column', width: 250, padding: 4}}>
251+
<Autocomplete filter={contains}>
252+
<SearchField aria-label="Search states" placeholder="Search states" autoFocus style={{marginBottom: 4}} />
253+
<ListBox items={states}>
254+
{state => <DropdownItem>{state.name}</DropdownItem>}
255+
</ListBox>
256+
</Autocomplete>
257+
</Popover>
258+
</Select>
259+
);
260+
}
261+
```
262+
145263
## Value
146264

147265
Use the `defaultValue` or `value` prop to set the selected item. The value corresponds to the `id` prop of an item. When `selectionMode="multiple"`, `value` and `onChange` accept an array. Items can be disabled with the `isDisabled` prop.

packages/dev/s2-docs/src/CodeBlock.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const example = style({
1414
borderRadius: 'xl',
1515
marginY: {
1616
default: 32,
17-
':is([data-example-switcher] > *)': 0
17+
':is([data-example-switcher] *)': 0
1818
},
1919
padding: {
2020
default: 12,

packages/dev/s2-docs/src/ExampleSwitcher.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ const switcher = style({
3636
justifySelf: {
3737
default: 'center',
3838
lg: 'start'
39-
}
39+
},
40+
overflow: 'auto',
41+
maxWidth: 'full',
42+
padding: 4,
43+
margin: -4
4044
});
4145

4246
const themePicker = style({
@@ -118,9 +122,11 @@ export function ExampleSwitcher({type = 'style', examples = DEFAULT_EXAMPLES, ch
118122

119123
return (
120124
<div className={exampleStyle} data-example-switcher>
121-
<SegmentedControl selectedKey={selected} onSelectionChange={onSelectionChange} styles={switcher}>
122-
{examples.map(example => <SegmentedControlItem key={example} id={example}>{example}</SegmentedControlItem>)}
123-
</SegmentedControl>
125+
<div className={switcher}>
126+
<SegmentedControl selectedKey={selected} onSelectionChange={onSelectionChange}>
127+
{examples.map(example => <SegmentedControlItem key={example} id={example}>{example}</SegmentedControlItem>)}
128+
</SegmentedControl>
129+
</div>
124130
{selected === 'Vanilla CSS' &&
125131
<Picker
126132
label="Theme"

packages/dev/s2-docs/src/VisualExample.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const exampleStyle = style({
1414
},
1515
marginTop: {
1616
default: 20,
17-
':is([data-example-switcher] > *)': 0
17+
':is([data-example-switcher] *)': 0
1818
},
1919
borderRadius: 'xl',
2020
display: 'grid',

starters/docs/src/Autocomplete.css

Lines changed: 0 additions & 17 deletions
This file was deleted.

starters/docs/src/Autocomplete.tsx

Lines changed: 0 additions & 40 deletions
This file was deleted.

starters/docs/src/Button.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,13 @@
3838
--highlight-background: var(--gray-1600);
3939
}
4040
}
41+
42+
kbd {
43+
font: var(--font-size-sm) system-ui;
44+
background: var(--highlight-hover);
45+
border: 0.5px solid var(--tint-500);
46+
padding: 0 var(--spacing-1);
47+
border-radius: var(--radius-sm);
48+
margin-inline-start: var(--spacing-3);
49+
}
4150
}

0 commit comments

Comments
 (0)