Skip to content

Commit 9697b43

Browse files
authored
feat(Toolbar): accept react fragments as children (#723)
1 parent 2fb9924 commit 9697b43

File tree

6 files changed

+309
-88
lines changed

6 files changed

+309
-88
lines changed
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs/blocks';
2+
import { Toolbar } from '@ui5/webcomponents-react/lib/Toolbar';
3+
import { Button } from '@ui5/webcomponents-react/lib/Button';
4+
import { ToolbarSpacer } from '@ui5/webcomponents-react/lib/ToolbarSpacer';
5+
import { Text } from '@ui5/webcomponents-react/lib/Text';
6+
import { Icon } from '@ui5/webcomponents-react/lib/Icon';
7+
import { Switch } from '@ui5/webcomponents-react/lib/Switch';
8+
import { Select } from '@ui5/webcomponents-react/lib/Select';
9+
import { ToolbarDesign } from '@ui5/webcomponents-react/lib/ToolbarDesign';
10+
import { ToolbarSeparator } from '@ui5/webcomponents-react/lib/ToolbarSeparator';
11+
import { ToolbarStyle } from '@ui5/webcomponents-react/lib/ToolbarStyle';
12+
import '@ui5/webcomponents-icons/dist/icons/employee.js';
13+
import { CSSProperties } from 'react';
14+
import { createSelectArgTypes } from '@shared/stories/createSelectArgTypes';
15+
import { DocsHeader } from '@shared/stories/DocsHeader';
16+
import '@ui5/webcomponents-icons/dist/icons/settings.js';
17+
import '@ui5/webcomponents-icons/dist/icons/download.js';
18+
19+
<Meta
20+
title="Components / Toolbar"
21+
component={Toolbar}
22+
argTypes={{
23+
...createSelectArgTypes({ toolbarStyle: ToolbarStyle, design: ToolbarDesign }),
24+
children: { control: { disable: true } },
25+
slot: { control: { disable: true } },
26+
ref: { control: { disable: true } },
27+
style: {
28+
type: CSSProperties,
29+
description:
30+
'Element style which will be appended to the most outer element of a component. Use this prop carefully, some css properties might break the component.'
31+
},
32+
className: {
33+
type: 'string',
34+
description:
35+
'CSS Class Name which will be appended to the most outer element of a component. Use this prop carefully, overwriting CSS rules might break the component.'
36+
},
37+
tooltip: { type: 'string', description: 'A tooltip which will be shown on hover' }
38+
}}
39+
args={{
40+
design: ToolbarDesign.Auto,
41+
toolbarStyle: ToolbarStyle.Standard,
42+
active: false,
43+
style: {},
44+
className: '',
45+
tooltip: '',
46+
slot: '',
47+
ref: null
48+
}}
49+
/>
50+
51+
<DocsHeader />
52+
53+
<Canvas>
54+
<Story name="Default">
55+
{(args) => {
56+
return (
57+
<Toolbar {...args}>
58+
<Text>Toolbar</Text>
59+
<Button>Button One</Button>
60+
<Button>Button Two</Button>
61+
</Toolbar>
62+
);
63+
}}
64+
</Story>
65+
</Canvas>
66+
67+
<ArgsTable story="Default" />
68+
69+
### Prevent event bubbling of Toolbar items
70+
71+
Per default, if the `active` prop is "true" and an actionable element like a button is clicked, the `onToolbarClick` event is also fired.
72+
To prevent this you can add `e.stopPropagation()` to your event handler.
73+
74+
```jsx
75+
<Toolbar>
76+
<Button
77+
onClick={(e) => {
78+
//use e.stopPropagation() to prevent event bubbling
79+
e.stopPropagation();
80+
}}
81+
>
82+
Toolbar Item
83+
</Button>
84+
</Toolbar>
85+
```
86+
87+
<br />
88+
<br />
89+
90+
# Stories
91+
92+
<br />
93+
94+
## Toolbar with overflow button
95+
96+
If the horizontally available space isn't enough to fit all items in it, an overflow button is displayed.<br />
97+
**Note:** You can change the width of the toolbar by dragging the `width` slider in the table below.
98+
99+
<ArgsTable story="With overflow button" />
100+
101+
<Canvas>
102+
<Story
103+
name="With overflow button"
104+
args={{ width: 200 }}
105+
argTypes={{
106+
width: {
107+
control: { type: 'range', min: 0, max: 1100, step: 10 },
108+
description: 'Drag the slider to change the width of the toolbar.'
109+
},
110+
children: { table: { disable: true } },
111+
toolbarStyle: { table: { disable: true } },
112+
design: { table: { disable: true } },
113+
slot: { table: { disable: true } },
114+
ref: { table: { disable: true } },
115+
style: { table: { disable: true } },
116+
className: { table: { disable: true } },
117+
tooltip: { table: { disable: true } },
118+
active: { table: { disable: true } },
119+
onToolbarClick: { table: { disable: true } }
120+
}}
121+
>
122+
{(args) => {
123+
return (
124+
<Toolbar style={{ width: `${args.width}px` }}>
125+
<Text>Toolbar</Text>
126+
<Button>Button One</Button>
127+
<Button>Button Two</Button>
128+
<Select />
129+
<Switch />
130+
<Button>Button Three</Button>
131+
<Button>Button Four</Button>
132+
<Button>Button Five</Button>
133+
<Button>Button Six</Button>
134+
</Toolbar>
135+
);
136+
}}
137+
</Story>
138+
</Canvas>
139+
140+
<br />
141+
<br />
142+
143+
## Align elements inside of the Toolbar
144+
145+
To align items inside of the `Toolbar` you can use the `ToolbarSpacer` component.<br />
146+
This will cover the remaining horizontal space between the `Toolbar` items and for example pushes one item to the edge of the `Toolbar`.
147+
148+
### Right aligned items
149+
150+
<Canvas>
151+
<Story name="Right aligned items">
152+
{(args) => {
153+
return (
154+
<Toolbar {...args}>
155+
<ToolbarSpacer />
156+
<Button>Button</Button>
157+
<Icon name="settings" />
158+
<Icon name="download" />
159+
</Toolbar>
160+
);
161+
}}
162+
</Story>
163+
</Canvas>
164+
165+
### Evenly aligned items
166+
167+
<Canvas>
168+
<Story name="Evenly aligned items">
169+
{(args) => {
170+
return (
171+
<Toolbar {...args}>
172+
<Text>Left</Text>
173+
<ToolbarSpacer />
174+
<Button>Center</Button>
175+
<ToolbarSpacer />
176+
<Text>Right</Text>
177+
<Icon name="settings" />
178+
<Icon name="download" />
179+
</Toolbar>
180+
);
181+
}}
182+
</Story>
183+
</Canvas>
184+
185+
<br />
186+
<br />
187+
188+
## Toolbar Separator
189+
190+
You can add a visual separator between the preceding and succeeding `Toolbar` item with the use of the `ToolbarSeparator`.<br />
191+
**Note:** In the overflow popover the `ToolbarSeparator` is represented by a horizontal line, in the `Toolbar` by a vertical line.
192+
193+
<Canvas>
194+
<Story name="With separator">
195+
{(args) => {
196+
return (
197+
<Toolbar {...args}>
198+
<Button>Item1</Button>
199+
<Button>Item2</Button>
200+
<Button>Item3</Button>
201+
<ToolbarSeparator />
202+
<Button>Item4</Button>
203+
<Button>Item5</Button>
204+
<ToolbarSeparator />
205+
<Button>Item6</Button>
206+
<ToolbarSeparator />
207+
<Button>Item7</Button>
208+
</Toolbar>
209+
);
210+
}}
211+
</Story>
212+
</Canvas>

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

Lines changed: 0 additions & 82 deletions
This file was deleted.

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ describe('Toolbar', () => {
2525
expect(screen.getByTestId('toolbar')).toHaveClass('Toolbar-active');
2626
});
2727

28+
test('Renders with children as react fragments', () => {
29+
expect(
30+
render(
31+
<Toolbar active data-testid="toolbar">
32+
<>
33+
<Text>Item1</Text>
34+
<Text>Item2</Text>
35+
<Text>Item3</Text>
36+
</>
37+
</Toolbar>
38+
).asFragment()
39+
).toMatchSnapshot();
40+
expect(screen.getByText('Item1').textContent).toEqual('Item1');
41+
expect(screen.getByTestId('toolbar')).toHaveClass('Toolbar-active');
42+
});
43+
2844
// test('Renders overflowButton', async () => {
2945
// let utils;
3046
//

packages/main/src/components/Toolbar/__snapshots__/Toolbar.test.tsx.snap

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,41 @@ exports[`Toolbar Renders with children 1`] = `
3535
</DocumentFragment>
3636
`;
3737

38+
exports[`Toolbar Renders with children as react fragments 1`] = `
39+
<DocumentFragment>
40+
<div
41+
class="Toolbar-outerContainer Toolbar-active"
42+
data-testid="toolbar"
43+
>
44+
<div
45+
class="Toolbar-toolbar"
46+
>
47+
<div>
48+
<span
49+
class="Text-text"
50+
>
51+
Item1
52+
</span>
53+
</div>
54+
<div>
55+
<span
56+
class="Text-text"
57+
>
58+
Item2
59+
</span>
60+
</div>
61+
<div>
62+
<span
63+
class="Text-text"
64+
>
65+
Item3
66+
</span>
67+
</div>
68+
</div>
69+
</div>
70+
</DocumentFragment>
71+
`;
72+
3873
exports[`Toolbar Renders with default Props 1`] = `
3974
<DocumentFragment>
4075
<div

0 commit comments

Comments
 (0)