|
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