Skip to content

Commit 023f7bc

Browse files
committed
debug dynamic case and fix context
1 parent 2e47bf2 commit 023f7bc

File tree

2 files changed

+168
-57
lines changed

2 files changed

+168
-57
lines changed

packages/react-aria-components/src/Autocomplete.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const UNSTABLE_Autocomplete = forwardRef(function Autocomplete(props: Aut
6767
collectionProps,
6868
collectionRef: mergedCollectionRef
6969
}],
70-
[RootMenuTriggerStateContext, rootMenuTriggerState ? null : menuState]
70+
[RootMenuTriggerStateContext, rootMenuTriggerState ? rootMenuTriggerState : menuState]
7171
]}>
7272
{props.children}
7373
</Provider>

packages/react-aria-components/stories/Autocomplete.stories.tsx

Lines changed: 167 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,115 @@ export const AutocompleteSearchfield = {
149149
name: 'Autocomplete complex static with searchfield'
150150
};
151151

152-
interface AutocompleteItem {
153-
id: string,
154-
name: string
152+
let dynamicAutocompleteSubdialog = [
153+
{name: 'Section 1', isSection: true, children: [
154+
{name: 'Command Palette'},
155+
{name: 'Open View'}
156+
]},
157+
{name: 'Section 2', isSection: true, children: [
158+
{name: 'Appearance', children: [
159+
{name: 'Sub Section 1', isSection: true, children: [
160+
{name: 'Move Primary Side Bar Right'},
161+
{name: 'Activity Bar Position', children: [
162+
{name: 'Default'},
163+
{name: 'Top'},
164+
{name: 'Bottom'},
165+
{name: 'Hidden'}
166+
]},
167+
{name: 'Panel Position', children: [
168+
{name: 'Top'},
169+
{name: 'Left'},
170+
{name: 'Right'},
171+
{name: 'Bottom'}
172+
]}
173+
]}
174+
]},
175+
{name: 'Editor Layout', children: [
176+
{name: 'Sub Section 1', isSection: true, children: [
177+
{name: 'Split up'},
178+
{name: 'Split down'},
179+
{name: 'Split left'},
180+
{name: 'Split right'}
181+
]},
182+
{name: 'Sub Section 2', isSection: true, children: [
183+
{name: 'Single'},
184+
{name: 'Two columns'},
185+
{name: 'Three columns'},
186+
{name: 'Two rows'},
187+
{name: 'Three rows'}
188+
]}
189+
]}
190+
]}
191+
];
192+
193+
interface ItemNode {
194+
name?: string,
195+
textValue?: string,
196+
isSection?: boolean,
197+
children?: ItemNode[]
155198
}
156199

157-
let items: AutocompleteItem[] = [{id: '1', name: 'Foo'}, {id: '2', name: 'Bar'}, {id: '3', name: 'Baz'}];
200+
let dynamicRenderTrigger = (item: ItemNode) => (
201+
// TODO: not sure why this needs an id...
202+
// @ts-ignore
203+
<SubdialogTrigger id={Math.random()}>
204+
<MyMenuItem id={item.name} textValue={item.name}>
205+
{item.name}
206+
</MyMenuItem>
207+
<Popover
208+
style={{
209+
background: 'Canvas',
210+
color: 'CanvasText',
211+
border: '1px solid gray',
212+
padding: 5
213+
}}>
214+
<Dialog>
215+
<AutocompleteWrapper>
216+
<SearchField autoFocus>
217+
<Label style={{display: 'block'}}>Search</Label>
218+
<Input />
219+
<Text style={{display: 'block'}} slot="description">Please select an option below.</Text>
220+
</SearchField>
221+
<Menu className={styles.menu} items={item.children} onAction={action(`${item.name} onAction`)}>
222+
{(item) => dynamicRenderFuncSections(item)}
223+
</Menu>
224+
</AutocompleteWrapper>
225+
</Dialog>
226+
</Popover>
227+
</SubdialogTrigger>
228+
);
229+
230+
let dynamicRenderItem = (item) => (
231+
<MyMenuItem id={item.name} textValue={item.name}>
232+
{item.name}
233+
</MyMenuItem>
234+
);
235+
236+
let dynamicRenderFuncSections = (item: ItemNode) => {
237+
if (item.children) {
238+
if (item.isSection) {
239+
return (
240+
<MenuSection className={styles.group} id={item.name} items={item.children}>
241+
{item.name != null && <Header style={{fontSize: '1.2em'}}>{item.name}</Header>}
242+
<Collection items={item.children ?? []}>
243+
{(item) => {
244+
if (item.children) {
245+
return dynamicRenderTrigger(item);
246+
} else {
247+
return dynamicRenderItem(item);
248+
}
249+
}}
250+
</Collection>
251+
</MenuSection>
252+
);
253+
} else {
254+
return dynamicRenderTrigger(item);
255+
}
256+
} else {
257+
return dynamicRenderItem(item);
258+
}
259+
};
260+
158261
export const AutocompleteMenuDynamic = {
159262
render: (args) => {
160263
let {onAction, onSelectionChange, selectionMode} = args;
@@ -167,8 +270,8 @@ export const AutocompleteMenuDynamic = {
167270
<Input />
168271
<Text style={{display: 'block'}} slot="description">Please select an option below.</Text>
169272
</SearchField>
170-
<Menu className={styles.menu} items={items} onAction={onAction} onSelectionChange={onSelectionChange} selectionMode={selectionMode}>
171-
{item => <MyMenuItem id={item.id}>{item.name}</MyMenuItem>}
273+
<Menu className={styles.menu} items={dynamicAutocompleteSubdialog} onAction={onAction} onSelectionChange={onSelectionChange} selectionMode={selectionMode}>
274+
{item => dynamicRenderFuncSections(item)}
172275
</Menu>
173276
</div>
174277
</AutocompleteWrapper>
@@ -200,6 +303,13 @@ export const AutocompleteOnActionOnMenuItems = {
200303
name: 'Autocomplete, onAction on menu items'
201304
};
202305

306+
interface AutocompleteItem {
307+
id: string,
308+
name: string
309+
}
310+
311+
let items: AutocompleteItem[] = [{id: '1', name: 'Foo'}, {id: '2', name: 'Bar'}, {id: '3', name: 'Baz'}];
312+
203313
export const AutocompleteDisabledKeys = {
204314
render: (args) => {
205315
let {onAction, onSelectionChange, selectionMode} = args;
@@ -397,61 +507,15 @@ export const AutocompleteWithVirtualizedListbox = {
397507

398508
let lotsOfSections: any[] = [];
399509
for (let i = 0; i < 50; i++) {
400-
let children: {name: string, id: string, children?: any}[] = [];
510+
let children: {name: string, id: string}[] = [];
401511
for (let j = 0; j < 50; j++) {
402-
// if (j === 3) {
403-
// children.push({
404-
// name: `Section ${i}, Item ${j}`,
405-
// id: `item_${i}${j}`,
406-
// children: [
407-
// {id: `lvl2_item_${i}${j}_1`, name: `lvl2_item_${i}${j}_1`},
408-
// {id: `lvl2_item_${i}${j}_2`, name: `lvl2_item_${i}${j}_2`},
409-
// {id: `lvl2_item_${i}${j}_3`, name: `lvl2_item_${i}${j}_3`}
410-
// ]
411-
// });
412-
// } else {
413-
children.push({name: `Section ${i}, Item ${j}`, id: `item_${i}_${j}`});
414-
// }
512+
children.push({name: `Section ${i}, Item ${j}`, id: `item_${i}_${j}`});
415513
}
416514

417515
lotsOfSections.push({name: 'Section ' + i, id: `section_${i}`, children});
418516
}
419517
lotsOfSections = [{name: 'Recently visited', id: 'recent', children: []}].concat(lotsOfSections);
420518

421-
let dynamicRenderFunc = (item, props) => {
422-
if (item.value.children) {
423-
console.log('aweg', item);
424-
return (
425-
<SubdialogTrigger>
426-
<MyListBoxItem id={item.value.id}>{item.value.name}</MyListBoxItem>
427-
<Popover
428-
style={{
429-
background: 'Canvas',
430-
color: 'CanvasText',
431-
border: '1px solid gray',
432-
padding: 5
433-
}}>
434-
<Dialog>
435-
<AutocompleteWrapper>
436-
<TextField autoFocus>
437-
<Label style={{display: 'block'}}>Search</Label>
438-
<Input />
439-
<Text style={{display: 'block'}} slot="description">Please select an option below.</Text>
440-
</TextField>
441-
<ListBox items={item.value.children} className={styles.menu} {...props}>
442-
{/* {(item) => dynamicRenderFunc(item, props)} */}
443-
{item => <MyListBoxItem id={item.value.id}>{item.value.name}</MyListBoxItem>}
444-
</ListBox>
445-
</AutocompleteWrapper>
446-
</Dialog>
447-
</Popover>
448-
</SubdialogTrigger>
449-
);
450-
} else {
451-
return <MyListBoxItem id={item.value.id}>{item.value.name}</MyListBoxItem>;
452-
}
453-
};
454-
455519
function ShellExample() {
456520
let tree = useTreeData<any>({
457521
initialItems: lotsOfSections,
@@ -484,8 +548,7 @@ function ShellExample() {
484548
<ListBoxSection id={section.value.id} className={styles.group}>
485549
{section.value.name != null && <Header style={{fontSize: '1.2em'}}>{section.value.name}</Header>}
486550
<Collection items={section.children ?? []}>
487-
{(item) => dynamicRenderFunc(item, {onSelectionChange, selectionMode: 'single'})}
488-
{/* {item => <MyListBoxItem id={item.value.id}>{item.value.name}</MyListBoxItem>} */}
551+
{item => <MyListBoxItem id={item.value.id}>{item.value.name}</MyListBoxItem>}
489552
</Collection>
490553
</ListBoxSection>
491554
);
@@ -590,3 +653,51 @@ export const AutocompleteInPopoverDialogTrigger = {
590653
}
591654
}
592655
};
656+
657+
// TODO: hitting escape sometimes closes both the root menu and the leaf menu, seems to happen if you arrow key to an option in the submenu's options and then hits escape...
658+
export const AutocompleteMenuInPopoverDialogTrigger = {
659+
render: (args) => {
660+
let {onAction, onSelectionChange, selectionMode} = args;
661+
return (
662+
<DialogTrigger>
663+
<Button>
664+
Open popover
665+
</Button>
666+
<Popover
667+
placement="bottom start"
668+
style={{
669+
background: 'Canvas',
670+
color: 'CanvasText',
671+
border: '1px solid gray',
672+
padding: 20,
673+
height: 250
674+
}}>
675+
<Dialog aria-label="dialog with autocomplete">
676+
{() => (
677+
<AutocompleteWrapper>
678+
<div>
679+
<SearchField autoFocus>
680+
<Label style={{display: 'block'}}>Test</Label>
681+
<Input />
682+
<Text style={{display: 'block'}} slot="description">Please select an option below.</Text>
683+
</SearchField>
684+
<Menu className={styles.menu} items={dynamicAutocompleteSubdialog} onAction={onAction} onSelectionChange={onSelectionChange} selectionMode={selectionMode}>
685+
{item => dynamicRenderFuncSections(item)}
686+
</Menu>
687+
</div>
688+
</AutocompleteWrapper>
689+
)}
690+
</Dialog>
691+
</Popover>
692+
</DialogTrigger>
693+
);
694+
},
695+
name: 'Autocomplete in popover (dialog trigger), rendering dynamic autocomplete menu',
696+
argTypes: {
697+
selectionMode: {
698+
table: {
699+
disable: true
700+
}
701+
}
702+
}
703+
};

0 commit comments

Comments
 (0)