|
1 | 1 | import { useCallback } from 'react'; |
2 | 2 | import { Meta, Canvas, Story } from '@storybook/addon-docs'; |
3 | 3 | import { useArgs } from '@storybook/client-api'; |
4 | | -import { Combobox } from '@zendeskgarden/react-dropdowns'; |
5 | | -import { ListboxStory } from './stories/ListboxStory'; |
6 | | -import { MenuAppendStory } from './stories/MenuAppendStory'; |
7 | | -import { MenuButtonStory } from './stories/MenuButtonStory'; |
8 | | -import { MenuNestedStory } from './stories/MenuNestedStory'; |
9 | | -import { BASE_ITEMS, NESTED_ITEMS } from './stories/data'; |
| 4 | +import { NestedStory } from './stories/NestedStory'; |
| 5 | +import { PortalStory } from './stories/PortalStory'; |
10 | 6 |
|
11 | 7 | <Meta title="Packages/Dropdowns/[patterns]" /> |
12 | 8 |
|
13 | 9 | # Patterns |
14 | 10 |
|
15 | | -## Render listbox in a root level React portal |
| 11 | +## Nested |
16 | 12 |
|
17 | | -The `listboxAppendToNode` property can be used to render the listbox in a |
18 | | -different DOM location than inline with the Combobox component. This is done via |
19 | | -React portals under the hood. |
| 13 | +### Listbox |
20 | 14 |
|
21 | | -You typically will need to set this property if you are using the `Combobox` |
22 | | -inside an element with `overflow: hidden` / `auto` / `scroll` CSS styles. |
| 15 | +A `Combobox` with `<Option type="next">` can be controlled to enable nested |
| 16 | +listbox behavior. The nested listbox will then need an `<Option |
| 17 | +type="previous">` to allow backwards navigation to the previous listbox. Use |
| 18 | +`<Option type="next" hasSelection>` to indicate that the nested listbox contains |
| 19 | +one or more selected options. |
23 | 20 |
|
24 | | -See in this example, that the listbox is currently getting cropped. Enable the |
25 | | -`listboxAppendToNode` property to see the full listbox. |
| 21 | +### Menu |
26 | 22 |
|
27 | | -<Canvas> |
28 | | - <Story |
29 | | - name="Listbox" |
30 | | - args={{ listboxAppendToNode: false }} |
31 | | - argTypes={{ listboxAppendToNode: { control: 'boolean' } }} |
32 | | - > |
33 | | - {args => <ListboxStory {...args} />} |
34 | | - </Story> |
35 | | -</Canvas> |
36 | | - |
37 | | -## Render menu in a root level React portal |
38 | | - |
39 | | -The `appendToNode` property can be used to render the menu popover in a |
40 | | -different DOM location than inline with the menu button. This is done via |
41 | | -React portals under the hood. |
42 | | - |
43 | | -You typically will need to set this property if you are using `Menu` inside an |
44 | | -element with `overflow: hidden` / `auto` / `scroll` CSS styles. |
45 | | - |
46 | | -See in this example that the menu will attempt to reposition, however it's |
47 | | -ultimately still cropped. Enable the `appendToNode` property to see the full menu. |
| 23 | +Adding an `Item` with `type="next"` will enable nested menu behavior. It can be |
| 24 | +implemented with or without controlled focus. The subsequent nested menu will |
| 25 | +then need an `Item` with `type="previous"` to allow backwards navigation to the |
| 26 | +previous menu. |
48 | 27 |
|
49 | 28 | <Canvas> |
50 | | - <Story |
51 | | - name="Menu portal" |
52 | | - args={{ appendToNode: false }} |
53 | | - argTypes={{ appendToNode: { control: 'boolean' } }} |
54 | | - > |
55 | | - {args => <MenuAppendStory {...args} />} |
56 | | - </Story> |
| 29 | + <Story name="Nested">{args => <NestedStory {...args} />}</Story> |
57 | 30 | </Canvas> |
58 | 31 |
|
59 | | -## Render menu with custom button |
60 | | - |
61 | | -The `button` property can alternatively be set as a callback function that returns |
62 | | -custom button JSX. By default, `Menu` will use a Garden `Button` internally. |
| 32 | +## Portal |
63 | 33 |
|
64 | | -This is an option for things like icon buttons. |
| 34 | +Dropdowns can be rendered in a different DOM location than inline with their |
| 35 | +associated trigger component. This is done via React portals under the hood. |
| 36 | +You typically will need to portal if you are using dropdown components inside an |
| 37 | +element with `overflow: hidden` / `auto` / `scroll` CSS styles. See in these |
| 38 | +examples that the dropdowns are currently getting cropped. |
65 | 39 |
|
66 | | -<Canvas> |
67 | | - <Story name="Menu button">{args => <MenuButtonStory {...args} />}</Story> |
68 | | -</Canvas> |
| 40 | +### Listbox portal |
69 | 41 |
|
70 | | -## Menu with nested items |
| 42 | +Enable the `listboxAppendToNode` property to see the full listbox. |
71 | 43 |
|
72 | | -Adding an `Item` with `type="next"` will enable nested menu |
73 | | -behavior. It can be implemented with or without controlled focus. |
| 44 | +### Menu portal |
74 | 45 |
|
75 | | -The subsequent nested menu will then need an `Item` with `type="previous"` |
76 | | -to allow backwards navigation to the previous menu. |
| 46 | +Enable the `appendToNode` property to see the full menu. |
77 | 47 |
|
78 | 48 | <Canvas> |
79 | | - <Story name="Menu nested" args={{ items: BASE_ITEMS }}> |
80 | | - {args => { |
81 | | - const [_, updateArgs, resetArgs] = useArgs(); |
82 | | - const onChange = useCallback(({ type, isExpanded }) => { |
83 | | - const isNext = type.includes('next'); |
84 | | - const isPrev = type.includes('previous'); |
85 | | - if (isNext || isPrev) { |
86 | | - updateArgs({ items: isNext ? NESTED_ITEMS : BASE_ITEMS }); |
87 | | - } else if (isExpanded === false) { |
88 | | - resetArgs(['items']); |
89 | | - } |
90 | | - }, []); |
91 | | - return <MenuNestedStory {...args} onChange={onChange} />; |
| 49 | + <Story |
| 50 | + name="Portal" |
| 51 | + args={{ listboxAppendToNode: false, menuAppendToNode: false }} |
| 52 | + argTypes={{ |
| 53 | + listboxAppendToNode: { control: 'boolean', name: 'Combobox listboxAppendToNode' }, |
| 54 | + menuAppendToNode: { control: 'boolean', name: 'Menu appendToNode' } |
92 | 55 | }} |
| 56 | + > |
| 57 | + {args => <PortalStory {...args} />} |
93 | 58 | </Story> |
94 | 59 | </Canvas> |
0 commit comments