Skip to content

Commit b23f307

Browse files
docs(Toolbar): add popover inside overflow popover story (#4636)
Co-authored-by: Marcus Notheis <[email protected]>
1 parent 2d8ed88 commit b23f307

File tree

3 files changed

+136
-1
lines changed

3 files changed

+136
-1
lines changed

packages/main/src/components/Toolbar/Toolbar.mdx

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ It is furthermore possible to prevent the popover from opening by using `event.p
8585

8686
<Canvas of={ComponentStories.CustomOverflowButton} />
8787

88-
### Close overflow popover on interaction
88+
## Close overflow popover on interaction
8989

9090
The overflow popover can be closed programmatically by using the `overflowPopoverRef`.
9191

@@ -110,6 +110,103 @@ const ToolbarComponent = () => {
110110
};
111111
```
112112

113+
## Open Popovers by ID inside the overflow popover
114+
115+
To prevent duplicate child `id`s in the DOM, all child `id`s get an `-overflow` suffix. If an ID is used to open the popover (e.g. via the `opener` prop), you have to make sure to use the correct id.
116+
You can achieve that either by leveraging the `onOverflowChange` event and retrieve the current ID there, or by updating it inside the `click` handler of the respective opener component.
117+
118+
<Canvas of={ComponentStories.PopoverInOverflowPopover} sourceState="none" />
119+
120+
<details>
121+
122+
<summary>Set opener ID via click handler</summary>
123+
124+
```jsx
125+
const ToolbarComponent = () => {
126+
const [popoverIsOpen, setPopoverIsOpen] = useState(false);
127+
const [opener, setOpener] = useState('openMenuBtn');
128+
const handlePopoverOpenerClick = (e) => {
129+
setOpener(e.target.id);
130+
setPopoverIsOpen(true);
131+
};
132+
return (
133+
<>
134+
<Toolbar style={{ width: '400px' }}>
135+
<Text>Toolbar</Text>
136+
<Button>Button One</Button>
137+
<Button>Button Two</Button>
138+
<Button id="openMenuBtn" onClick={handlePopoverOpenerClick}>
139+
Open Popover (Menu)
140+
</Button>
141+
</Toolbar>
142+
<Menu
143+
opener={opener}
144+
open={popoverIsOpen}
145+
onAfterClose={() => {
146+
setPopoverIsOpen(false);
147+
}}
148+
>
149+
<MenuItem text="New File" />
150+
<MenuItem text="New Folder" />
151+
</Menu>
152+
</>
153+
);
154+
};
155+
```
156+
157+
</details>
158+
159+
<details>
160+
161+
<summary>Set opener ID via onOverflowChange handler</summary>
162+
163+
```jsx
164+
const ToolbarComponent = () => {
165+
const [popoverIsOpen, setPopoverIsOpen] = useState(false);
166+
const initialOpenerId = 'openMenuBtn';
167+
const [opener, setOpener] = useState(initialOpenerId);
168+
const handlePopoverOpenerClick = () => {
169+
setPopoverIsOpen(true);
170+
};
171+
const handleOverflowChange = (e) => {
172+
if (e.overflowElements?.length) {
173+
const overflowId = [...e.overflowElements].find((item) => item.dataset.opener)?.id;
174+
if (overflowId) {
175+
setOpener(overflowId);
176+
} else {
177+
setOpener(initialOpenerId);
178+
}
179+
} else {
180+
setOpener(initialOpenerId);
181+
}
182+
};
183+
return (
184+
<>
185+
<Toolbar style={{ width: '400px' }} onOverflowChange={handleOverflowChange}>
186+
<Text>Toolbar</Text>
187+
<Button>Button One</Button>
188+
<Button>Button Two</Button>
189+
<Button id="openMenuBtn" onClick={handlePopoverOpenerClick} data-opener>
190+
Open Popover (Menu)
191+
</Button>
192+
</Toolbar>
193+
<Menu
194+
opener={opener}
195+
open={popoverIsOpen}
196+
onAfterClose={() => {
197+
setPopoverIsOpen(false);
198+
}}
199+
>
200+
<MenuItem text="New File" />
201+
<MenuItem text="New Folder" />
202+
</Menu>
203+
</>
204+
);
205+
};
206+
```
207+
208+
</details>
209+
113210
<Markdown>{SubcomponentsSection}</Markdown>
114211
115212
## OverflowToolbarButton

packages/main/src/components/Toolbar/Toolbar.stories.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import { Button } from '../../webComponents/Button/index.js';
99
import { DatePicker } from '../../webComponents/DatePicker/index.js';
1010
import { Icon } from '../../webComponents/Icon/index.js';
1111
import { Input } from '../../webComponents/Input/index.js';
12+
import { Menu } from '../../webComponents/Menu/index.js';
13+
import { MenuItem } from '../../webComponents/MenuItem/index.js';
1214
import { Select } from '../../webComponents/Select/index.js';
1315
import { Slider } from '../../webComponents/Slider/index.js';
1416
import { Switch } from '../../webComponents/Switch/index.js';
@@ -103,6 +105,40 @@ export const WithSeparator: Story = {
103105
}
104106
};
105107

108+
export const PopoverInOverflowPopover: Story = {
109+
name: 'Popover in Overflow Popover',
110+
render(args) {
111+
const [popoverIsOpen, setPopoverIsOpen] = useState(false);
112+
const [opener, setOpener] = useState('openMenuBtn');
113+
const handlePopoverOpenerClick = (e) => {
114+
setOpener(e.target.id);
115+
setPopoverIsOpen(true);
116+
};
117+
return (
118+
<>
119+
<Toolbar {...args} style={{ width: '400px' }}>
120+
<Text>Toolbar</Text>
121+
<Button>Button One</Button>
122+
<Button>Button Two</Button>
123+
<Button id="openMenuBtn" onClick={handlePopoverOpenerClick}>
124+
Open Popover (Menu)
125+
</Button>
126+
</Toolbar>
127+
<Menu
128+
opener={opener}
129+
open={popoverIsOpen}
130+
onAfterClose={() => {
131+
setPopoverIsOpen(false);
132+
}}
133+
>
134+
<MenuItem text="New File" />
135+
<MenuItem text="New Folder" />
136+
</Menu>
137+
</>
138+
);
139+
}
140+
};
141+
106142
export const WithOverflowButton: Story = {
107143
name: 'with overflow button',
108144
render(args) {

packages/main/src/components/Toolbar/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ const OVERFLOW_BUTTON_WIDTH = 36 + 8 + 8; // width + padding end + spacing start
110110
* It can be accessed by the user through the overflow button that opens it in a popover.
111111
*
112112
* __Note:__ The overflow popover is mounted only when the overflow button is displayed, i.e., any child component of the popover will be remounted, when moved into it.
113+
*
114+
* __Note:__ To prevent duplicate child `id`s in the DOM, all child `id`s get an `-overflow` suffix. This is especially important when popovers are opened by id.
113115
*/
114116
const Toolbar = forwardRef<HTMLDivElement, ToolbarPropTypes>((props, ref) => {
115117
const {

0 commit comments

Comments
 (0)