Skip to content

Commit d0961b1

Browse files
authored
feat: Add custom option renderer for autosuggest (#4153)
1 parent 42e0017 commit d0961b1

File tree

12 files changed

+727
-4
lines changed

12 files changed

+727
-4
lines changed
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React, { useRef, useState } from 'react';
4+
5+
import { Autosuggest, AutosuggestProps, Toggle } from '~components';
6+
7+
import AppContext, { AppContextType } from '../app/app-context';
8+
import { SimplePage } from '../app/templates';
9+
10+
const empty = <span>Nothing found</span>;
11+
const options = [
12+
{ value: 'Option 0', tags: ['tag1', 'tag2'], filteringTags: ['bla', 'opt', 'blauer'], description: 'description1' },
13+
{ value: 'Option 1', labelTag: 'This is a label tag' },
14+
{ value: 'Option 2' },
15+
{
16+
value: 'Option Group',
17+
description: 'description2',
18+
options: [
19+
{
20+
value: 'value1',
21+
label: 'label1',
22+
},
23+
{
24+
value: 'value1repeated',
25+
label: 'label1repeated',
26+
},
27+
],
28+
},
29+
];
30+
type PageContext = React.Context<
31+
AppContextType<{
32+
virtualScroll?: boolean;
33+
}>
34+
>;
35+
36+
export default function AutosuggestPage() {
37+
const [value, setValue] = useState('');
38+
const ref = useRef<AutosuggestProps.Ref>(null);
39+
40+
const renderOption: AutosuggestProps.ItemRenderer = ({ item }) => {
41+
if (item.type === 'entered-text') {
42+
return <div>Entereted Text: {item.option.value}</div>;
43+
} else if (item.type === 'group') {
44+
return <div>Group: {item.option.value}</div>;
45+
} else if (item.type === 'item') {
46+
return <div>Item: {item.option.value}</div>;
47+
}
48+
return null;
49+
};
50+
const { urlParams, setUrlParams } = React.useContext(AppContext as PageContext);
51+
const virtualScroll = urlParams.virtualScroll ?? false;
52+
53+
return (
54+
<SimplePage
55+
title="Autosuggest with custom item renderer"
56+
settings={
57+
<Toggle
58+
checked={!!urlParams.virtualScroll}
59+
onChange={({ detail }) => setUrlParams({ virtualScroll: detail.checked })}
60+
>
61+
Virtual Scroll
62+
</Toggle>
63+
}
64+
screenshotArea={{
65+
style: {
66+
padding: 10,
67+
},
68+
}}
69+
>
70+
<div style={{ maxInlineSize: '400px', blockSize: '650px' }}>
71+
<Autosuggest
72+
virtualScroll={virtualScroll}
73+
renderOption={renderOption}
74+
ref={ref}
75+
value={value}
76+
options={options}
77+
onChange={event => setValue(event.detail.value)}
78+
placeholder={`Type... ${virtualScroll ? '(virtual)' : ''}`}
79+
ariaLabel={'simple autosuggest'}
80+
selectedAriaLabel="Selected"
81+
empty={empty}
82+
/>
83+
</div>
84+
</SimplePage>
85+
);
86+
}

src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3556,6 +3556,56 @@ For more information, see the
35563556
"optional": true,
35573557
"type": "AutosuggestProps.ContainingOptionAndGroupString",
35583558
},
3559+
{
3560+
"description": "Specifies a render function to render custom options in the dropdown menu.
3561+
3562+
The item inside the props has a different shape depending on its type:
3563+
3564+
3565+
### item
3566+
3567+
- \`type\` ('item') - The item type.
3568+
- \`index\` (number) - The item's absolute position in the dropdown.
3569+
- \`option\` (Option) - The original option configuration.
3570+
- \`disabled\` (boolean) - Whether the item is disabled.
3571+
- \`highlighted\` (boolean) - Whether the item is currently highlighted.
3572+
- \`selected\` (boolean) - Whether the item is selected.
3573+
- \`parent\` (OptionGroupRenderItem | null) - The parent group item, if any.
3574+
3575+
### group
3576+
3577+
- \`type\` ('group') - The item type.
3578+
- \`index\` (number) - The item's absolute position in the dropdown.
3579+
- \`option\` (OptionGroup) - The original option configuration.
3580+
- \`disabled\` (boolean) - Whether the item is disabled.
3581+
3582+
### entered-text
3583+
3584+
- \`type\` ('entered-text') - The item type.
3585+
- \`option\` (Option) - The entered-text option configuration.
3586+
3587+
When providing a custom \`renderOption\` implementation, it fully replaces the default visual rendering and content for that item.
3588+
The component still manages focus, keyboard interactions, and selection state, but it no longer applies its default item layout or typography.
3589+
3590+
When returning \`null\`, the default rendering will be applied for that item.",
3591+
"inlineType": {
3592+
"name": "AutosuggestProps.ItemRenderer",
3593+
"parameters": [
3594+
{
3595+
"name": "props",
3596+
"type": "{ item: AutosuggestProps.RenderItem; filterText?: string | undefined; }",
3597+
},
3598+
],
3599+
"returnType": "React.ReactNode",
3600+
"type": "function",
3601+
},
3602+
"name": "renderOption",
3603+
"optional": true,
3604+
"systemTags": [
3605+
"core",
3606+
],
3607+
"type": "AutosuggestProps.ItemRenderer",
3608+
},
35593609
{
35603610
"description": "Specifies the localized string that describes an option as being selected.
35613611
This is required to provide a good screen reader experience. For more information, see the

0 commit comments

Comments
 (0)