akeneo-design-system 0.1.226 → 0.1.228

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. package/example/src/__snapshots__/App.test.js.snap +1 -1
  2. package/jest-puppeteer.config.js +1 -0
  3. package/lib/components/Avatar/Avatar.d.ts +5 -0
  4. package/lib/components/Avatar/Avatar.js +89 -0
  5. package/lib/components/Avatar/Avatar.js.map +1 -0
  6. package/lib/components/Avatar/Avatars.d.ts +9 -0
  7. package/lib/components/Avatar/Avatars.js +87 -0
  8. package/lib/components/Avatar/Avatars.js.map +1 -0
  9. package/lib/components/Avatar/types.d.ts +11 -0
  10. package/lib/components/Avatar/types.js +3 -0
  11. package/lib/components/Avatar/types.js.map +1 -0
  12. package/lib/components/Dropdown/Dropdown.d.ts +2 -1
  13. package/lib/components/Dropdown/Surtitle/Surtitle.d.ts +1 -0
  14. package/lib/components/Input/BooleanInput/BooleanInput.d.ts +1 -1
  15. package/lib/components/Input/BooleanInput/BooleanInput.js +1 -1
  16. package/lib/components/Input/BooleanInput/BooleanInput.js.map +1 -1
  17. package/lib/components/Input/MultiSelectInput/MultiSelectInput.d.ts +8 -2
  18. package/lib/components/Input/MultiSelectInput/MultiSelectInput.js +11 -9
  19. package/lib/components/Input/MultiSelectInput/MultiSelectInput.js.map +1 -1
  20. package/lib/components/Input/SelectInput/SelectInput.d.ts +8 -2
  21. package/lib/components/Input/SelectInput/SelectInput.js +13 -11
  22. package/lib/components/Input/SelectInput/SelectInput.js.map +1 -1
  23. package/lib/components/Input/TableInput/TableInput.d.ts +1 -1
  24. package/lib/components/Input/TableInput/TableInputRow/TableInputRow.js +1 -1
  25. package/lib/components/Input/TableInput/TableInputRow/TableInputRow.js.map +1 -1
  26. package/lib/components/Input/TagInput/TagInput.js +5 -2
  27. package/lib/components/Input/TagInput/TagInput.js.map +1 -1
  28. package/lib/components/Navigation/SubNavigationPanel/SubNavigationPanel.d.ts +2 -0
  29. package/lib/components/Navigation/SubNavigationPanel/SubNavigationPanel.js +28 -40
  30. package/lib/components/Navigation/SubNavigationPanel/SubNavigationPanel.js.map +1 -1
  31. package/lib/components/ProgressIndicator/ProgressIndicator.d.ts +1 -1
  32. package/lib/components/index.d.ts +2 -0
  33. package/lib/components/index.js +2 -0
  34. package/lib/components/index.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-avatar-avatar-list-correctly-1-snap.png +0 -0
  37. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-avatar-avatar-size-correctly-1-snap.png +0 -0
  38. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-avatar-background-colors-correctly-1-snap.png +0 -0
  39. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-avatar-standard-correctly-1-snap.png +0 -0
  40. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-avatar-with-image-correctly-1-snap.png +0 -0
  41. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-navigation-sub-navigation-panel-content-with-collapse-component-correctly-1-snap.png +0 -0
  42. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-navigation-sub-navigation-panel-content-without-padding-correctly-1-snap.png +0 -0
  43. package/src/__image_snapshots__/all-visual-tsx-visual-tests-renders-components-navigation-sub-navigation-panel-scrollable-content-correctly-1-snap.png +0 -0
  44. package/src/components/Avatar/Avatar.stories.mdx +147 -0
  45. package/src/components/Avatar/Avatar.tsx +72 -0
  46. package/src/components/Avatar/Avatar.unit.tsx +79 -0
  47. package/src/components/Avatar/Avatars.tsx +72 -0
  48. package/src/components/Avatar/Avatars.unit.tsx +61 -0
  49. package/src/components/Avatar/types.ts +34 -0
  50. package/src/components/Dropdown/Surtitle/Surtitle.tsx +1 -1
  51. package/src/components/Input/BooleanInput/BooleanInput.tsx +2 -2
  52. package/src/components/Input/MultiSelectInput/MultiSelectInput.tsx +26 -16
  53. package/src/components/Input/MultiSelectInput/MultiSelectInput.unit.tsx +45 -0
  54. package/src/components/Input/SelectInput/SelectInput.tsx +28 -18
  55. package/src/components/Input/SelectInput/SelectInput.unit.tsx +52 -0
  56. package/src/components/Input/TableInput/TableInputRow/TableInputRow.tsx +2 -7
  57. package/src/components/Input/TagInput/TagInput.tsx +3 -3
  58. package/src/components/Navigation/SubNavigationPanel/SubNavigationPanel.stories.mdx +97 -25
  59. package/src/components/Navigation/SubNavigationPanel/SubNavigationPanel.tsx +58 -66
  60. package/src/components/Navigation/SubNavigationPanel/SubNavigationPanel.unit.tsx +3 -3
  61. package/src/components/index.ts +2 -0
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import {fireEvent, render, screen} from '../../storybook/test-util';
3
+ import {Avatar} from './Avatar';
4
+ import {Avatars} from './Avatars';
5
+
6
+ test('renders multiple avatars', () => {
7
+ render(
8
+ <Avatars max={2}>
9
+ <Avatar username="john" firstName="John" lastName="Doe" />
10
+ <Avatar username="leonard" firstName="Leonard" lastName="Doe" />
11
+ </Avatars>
12
+ );
13
+
14
+ expect(screen.getByTitle('John Doe')).toBeInTheDocument();
15
+ expect(screen.getByTitle('Leonard Doe')).toBeInTheDocument();
16
+ });
17
+
18
+ test('renders a maximum number of avatars', () => {
19
+ render(
20
+ <Avatars max={1}>
21
+ <Avatar username="john" firstName="John" lastName="Doe" />
22
+ <Avatar username="leonard" firstName="Leonard" lastName="Doe" />
23
+ </Avatars>
24
+ );
25
+
26
+ expect(screen.getByTitle('John Doe')).toBeInTheDocument();
27
+ expect(screen.queryByText('LD')).not.toBeInTheDocument();
28
+ expect(screen.getByText('+1')).toBeInTheDocument();
29
+ });
30
+
31
+ test('renders no avatar', () => {
32
+ render(<Avatars max={1}></Avatars>);
33
+
34
+ expect(screen.queryByTitle('+1')).not.toBeInTheDocument();
35
+ });
36
+
37
+ test('supports ...rest props', () => {
38
+ render(<Avatars max={1} data-testid="my_value" />);
39
+
40
+ expect(screen.getByTestId('my_value')).toBeInTheDocument();
41
+ });
42
+
43
+ test('displays remaining users names on plus hover', () => {
44
+ const invalidChild = 'I should not be in the title';
45
+ render(
46
+ <Avatars max={1} maxTitle={1}>
47
+ <Avatar username="dSchrute" firstName="Dwight" lastName="Schrute" />
48
+ <Avatar username="mscott" firstName=" " lastName=" " />
49
+ <Avatar username="kMalone" firstName="Kevin" lastName="Malone" />
50
+ {invalidChild}
51
+ </Avatars>
52
+ );
53
+
54
+ expect(screen.getByText('DS')).toBeInTheDocument();
55
+ expect(screen.getByText('+3')).toBeInTheDocument();
56
+ // Kevin Malone should not be visible as it should be part of the +1
57
+ expect(screen.queryByText('mscott')).not.toBeInTheDocument();
58
+
59
+ fireEvent.mouseOver(screen.getByText('+3'));
60
+ expect(screen.getByTitle('mscott ...')).toBeInTheDocument();
61
+ });
@@ -0,0 +1,34 @@
1
+ import {Override} from '../../shared';
2
+ import React from 'react';
3
+
4
+ export type User = {
5
+ /**
6
+ * Username to use as fallback if the avatar is not provided and the Firstname and Lastname are empty.
7
+ */
8
+ username: string;
9
+
10
+ /**
11
+ * Firstname to use as fallback with the Lastname if the avatar is not provided.
12
+ */
13
+ firstName: string;
14
+
15
+ /**
16
+ * Lastname to use as fallback with the Firstname if the avatar is not provided.
17
+ */
18
+ lastName: string;
19
+
20
+ /**
21
+ * Url of the avatar image.
22
+ */
23
+ avatarUrl?: string;
24
+ };
25
+
26
+ export type AvatarProps = Override<
27
+ React.HTMLAttributes<HTMLSpanElement>,
28
+ User & {
29
+ /**
30
+ * Size of the avatar.
31
+ */
32
+ size?: 'default' | 'big';
33
+ }
34
+ >;
@@ -19,7 +19,7 @@ const Title = styled.span`
19
19
  text-overflow: ellipsis;
20
20
  `;
21
21
 
22
- type SurtitleProps = {label: string};
22
+ type SurtitleProps = {label: string; children?: React.ReactNode};
23
23
 
24
24
  const Surtitle: React.FC<SurtitleProps> = ({label, children, ...rest}) => (
25
25
  <SurtitleContainer {...rest}>
@@ -149,7 +149,7 @@ type BooleanInputProps = Override<
149
149
  clearLabel?: string;
150
150
  }
151
151
  ) & {
152
- readOnly: boolean;
152
+ readOnly?: boolean;
153
153
  yesLabel: string;
154
154
  noLabel: string;
155
155
  invalid?: boolean;
@@ -165,7 +165,7 @@ const BooleanInput = React.forwardRef<HTMLDivElement, BooleanInputProps>(
165
165
  (
166
166
  {
167
167
  value,
168
- readOnly,
168
+ readOnly = false,
169
169
  onChange,
170
170
  clearable = false,
171
171
  yesLabel,
@@ -150,17 +150,24 @@ type MultiMultiSelectInputProps = Override<
150
150
  * Callback called when the user hit enter on the field.
151
151
  */
152
152
  onSubmit?: () => void;
153
-
154
- /**
155
- * Handler called when the next page is almost reached.
156
- */
157
- onNextPage?: () => void;
158
-
159
- /**
160
- * Handler called when the search value changed
161
- */
162
- onSearchChange?: (searchValue: string) => void;
163
- }
153
+ } & (
154
+ | {
155
+ /**
156
+ * Handler called when the next page is almost reached.
157
+ */
158
+ onNextPage?: () => void;
159
+ /**
160
+ * Handler called when the search value changed
161
+ */
162
+ onSearchChange?: (searchValue: string) => void;
163
+ disableInternalSearch?: false;
164
+ }
165
+ | {
166
+ onNextPage: () => void;
167
+ onSearchChange: (searchValue: string) => void;
168
+ disableInternalSearch: true;
169
+ }
170
+ )
164
171
  >;
165
172
 
166
173
  /**
@@ -183,6 +190,7 @@ const MultiSelectInput = ({
183
190
  verticalPosition,
184
191
  onNextPage,
185
192
  onSearchChange,
193
+ disableInternalSearch = false,
186
194
  'aria-labelledby': ariaLabelledby,
187
195
  ...rest
188
196
  }: MultiMultiSelectInputProps) => {
@@ -211,12 +219,14 @@ const MultiSelectInput = ({
211
219
  return indexedChips;
212
220
  }, {});
213
221
 
214
- const filteredChildren = validChildren.filter(({props}) => {
215
- const childValue = props.value;
216
- const optionValue = childValue + props.children;
222
+ const filteredChildren = disableInternalSearch
223
+ ? validChildren
224
+ : validChildren.filter(({props}) => {
225
+ const childValue = props.value;
226
+ const optionValue = childValue + props.children;
217
227
 
218
- return !value.includes(childValue) && optionValue.toLowerCase().includes(searchValue.toLowerCase());
219
- });
228
+ return !value.includes(childValue) && optionValue.toLowerCase().includes(searchValue.toLowerCase());
229
+ });
220
230
 
221
231
  const handleEnter = () => {
222
232
  if (filteredChildren.length > 0 && dropdownIsOpen) {
@@ -77,6 +77,51 @@ test('it handles search', () => {
77
77
  expect(onChange).toHaveBeenCalledTimes(2);
78
78
  });
79
79
 
80
+ test('it handles external search', () => {
81
+ const onChange = jest.fn();
82
+ const onNextPage = jest.fn();
83
+ const onSearchChange = jest.fn();
84
+
85
+ const observe = jest.fn();
86
+ const unobserve = jest.fn();
87
+ window.IntersectionObserver = jest.fn(() => ({
88
+ observe,
89
+ unobserve,
90
+ })) as unknown as jest.Mock<IntersectionObserver>;
91
+
92
+ render(
93
+ <MultiSelectInput
94
+ openLabel="Open"
95
+ value={[]}
96
+ onChange={onChange}
97
+ placeholder="Placeholder"
98
+ emptyResultLabel="Empty result"
99
+ onNextPage={onNextPage}
100
+ onSearchChange={onSearchChange}
101
+ disableInternalSearch={true}
102
+ removeLabel="Remove"
103
+ >
104
+ <MultiSelectInput.Option value="en_US">English</MultiSelectInput.Option>
105
+ <MultiSelectInput.Option value="fr_FR">French</MultiSelectInput.Option>
106
+ <MultiSelectInput.Option value="de_DE">German</MultiSelectInput.Option>
107
+ <MultiSelectInput.Option value="es_ES">Spanish</MultiSelectInput.Option>
108
+ </MultiSelectInput>
109
+ );
110
+
111
+ const input = screen.getByRole('textbox');
112
+ fireEvent.click(input);
113
+ fireEvent.change(input, {target: {value: 'Fr'}});
114
+
115
+ const germanOption = screen.queryByText('German');
116
+ expect(germanOption).toBeInTheDocument();
117
+ const usOption = screen.queryByText('English');
118
+ expect(usOption).toBeInTheDocument();
119
+ const spanishOption = screen.queryByText('Spanish');
120
+ expect(spanishOption).toBeInTheDocument();
121
+ const frenchOption = screen.getByText('French');
122
+ expect(frenchOption).toBeInTheDocument();
123
+ });
124
+
80
125
  test('it handles empty cases', () => {
81
126
  const onChange = jest.fn();
82
127
  render(
@@ -178,17 +178,24 @@ type SelectInputProps = Override<
178
178
  * Force the vertical position of the overlay.
179
179
  */
180
180
  verticalPosition?: VerticalPosition;
181
-
182
- /**
183
- * Handler called when the next page is almost reached.
184
- */
185
- onNextPage?: () => void;
186
-
187
- /**
188
- * Handler called when the search value changed
189
- */
190
- onSearchChange?: (searchValue: string) => void;
191
- }
181
+ } & (
182
+ | {
183
+ /**
184
+ * Handler called when the next page is almost reached.
185
+ */
186
+ onNextPage?: () => void;
187
+ /**
188
+ * Handler called when the search value changed
189
+ */
190
+ onSearchChange?: (searchValue: string) => void;
191
+ disableInternalSearch?: false;
192
+ }
193
+ | {
194
+ onNextPage: () => void;
195
+ onSearchChange: (searchValue: string) => void;
196
+ disableInternalSearch: true;
197
+ }
198
+ )
192
199
  >;
193
200
 
194
201
  /**
@@ -209,6 +216,7 @@ const SelectInput = ({
209
216
  verticalPosition,
210
217
  onNextPage,
211
218
  onSearchChange,
219
+ disableInternalSearch = false,
212
220
  'aria-labelledby': ariaLabelledby,
213
221
  ...rest
214
222
  }: SelectInputProps) => {
@@ -235,14 +243,16 @@ const SelectInput = ({
235
243
  return optionCodes;
236
244
  }, []);
237
245
 
238
- const filteredChildren = validChildren.filter(child => {
239
- const content = typeof child.props.children === 'string' ? child.props.children : '';
240
- const title = child.props.title ?? '';
241
- const value = child.props.value;
242
- const optionValue = value + content + title;
246
+ const filteredChildren = disableInternalSearch
247
+ ? validChildren
248
+ : validChildren.filter(child => {
249
+ const content = typeof child.props.children === 'string' ? child.props.children : '';
250
+ const title = child.props.title ?? '';
251
+ const value = child.props.value;
252
+ const optionValue = value + content + title;
243
253
 
244
- return optionValue.toLowerCase().includes(searchValue.toLowerCase());
245
- });
254
+ return optionValue.toLowerCase().includes(searchValue.toLowerCase());
255
+ });
246
256
 
247
257
  const currentValueElement =
248
258
  validChildren.find(child => {
@@ -95,6 +95,58 @@ test('it handles search', () => {
95
95
  expect(onChange).toHaveBeenCalledWith('es_ES');
96
96
  });
97
97
 
98
+ test('it handles external search', () => {
99
+ const onChange = jest.fn();
100
+ const onNextPage = jest.fn();
101
+ const onSearchChange = jest.fn();
102
+
103
+ const observe = jest.fn();
104
+ const unobserve = jest.fn();
105
+ window.IntersectionObserver = jest.fn(() => ({
106
+ observe,
107
+ unobserve,
108
+ })) as unknown as jest.Mock<IntersectionObserver>;
109
+
110
+ render(
111
+ <SelectInput
112
+ openLabel="Open"
113
+ value="en_US"
114
+ onChange={onChange}
115
+ placeholder="Placeholder"
116
+ emptyResultLabel="Empty result"
117
+ onNextPage={onNextPage}
118
+ onSearchChange={onSearchChange}
119
+ disableInternalSearch={true}
120
+ >
121
+ <SelectInput.Option value="en_US" title="English (United States)">
122
+ <Locale code="en_US" languageLabel="English" />
123
+ </SelectInput.Option>
124
+ <SelectInput.Option value="fr_FR" title="French (France)">
125
+ Français
126
+ </SelectInput.Option>
127
+ <SelectInput.Option value="de_DE">
128
+ <Locale code="de_DE" languageLabel="German" />
129
+ </SelectInput.Option>
130
+ <SelectInput.Option value="es_ES" title="Spanish (Spain)">
131
+ <Locale code="es_ES" languageLabel="Spanish" />
132
+ </SelectInput.Option>
133
+ </SelectInput>
134
+ );
135
+
136
+ const input = screen.getByRole('textbox');
137
+ fireEvent.click(input);
138
+ fireEvent.change(input, {target: {value: 'Français'}});
139
+
140
+ const germanOption = screen.queryByText('German');
141
+ expect(germanOption).toBeInTheDocument();
142
+ const usOption = screen.queryByText('English');
143
+ expect(usOption).toBeInTheDocument();
144
+ const spanishOption = screen.queryByText('Spanish');
145
+ expect(spanishOption).toBeInTheDocument();
146
+ const frenchOption = screen.getByText('Français');
147
+ expect(frenchOption).toBeInTheDocument();
148
+ });
149
+
98
150
  test('it handles empty cases', () => {
99
151
  const onChange = jest.fn();
100
152
  render(
@@ -96,15 +96,10 @@ const TableInputTr = styled.tr<
96
96
  height: 0;
97
97
  margin-top: -1px;
98
98
  }
99
- &:has(div) {
100
- background: red !important;
101
- }
102
99
  border-bottom-color: ${getColor('blue', 100)};
103
- &:first-child {
104
- border-left: 1px solid ${getColor('blue', 100)};
105
- }
100
+ border-left-color: ${getColor('blue', 100)};
106
101
  &:last-child {
107
- border-right: 1px solid ${getColor('blue', 100)};
102
+ border-right-color: ${getColor('blue', 100)};
108
103
  }
109
104
  }
110
105
  `}
@@ -55,12 +55,12 @@ const TagText = styled.span`
55
55
  white-space: nowrap;
56
56
  `;
57
57
 
58
- const InputContainer = styled.li<AkeneoThemedProps>`
58
+ const InputContainer = styled.li<AkeneoThemedProps & {hasTags: boolean}>`
59
59
  list-style-type: none;
60
60
  color: ${getColor('grey', 120)};
61
61
  border: 0;
62
62
  flex: 1;
63
- padding: 0;
63
+ padding: ${({hasTags}) => (hasTags ? '0' : '0 11px')};
64
64
  align-items: center;
65
65
  display: flex;
66
66
 
@@ -255,7 +255,7 @@ const TagInput: FC<TagInputProps> = ({
255
255
  </Tag>
256
256
  );
257
257
  })}
258
- <InputContainer ref={inputContainerRef} onClick={focusOnInputField}>
258
+ <InputContainer ref={inputContainerRef} onClick={focusOnInputField} hasTags={value.length > 0}>
259
259
  <input
260
260
  type="text"
261
261
  data-testid="tag-input"
@@ -1,10 +1,12 @@
1
- import { Meta, Story, ArgsTable, Canvas } from '@storybook/addon-docs';
2
- import { SubNavigationPanel } from './SubNavigationPanel.tsx';
3
- import { SpaceContainer } from '../../../storybook/PreviewGallery';
4
- import { useBooleanState } from '../../../hooks';
5
- import { MoreVerticalIcon } from "../../../icons";
6
- import { Dropdown } from "../../Dropdown/Dropdown";
7
- import { Link } from "../../Link/Link";
1
+ import {Meta, Story, ArgsTable, Canvas} from '@storybook/addon-docs';
2
+ import {SubNavigationPanel} from './SubNavigationPanel.tsx';
3
+ import {SpaceContainer} from '../../../storybook/PreviewGallery';
4
+ import {useBooleanState} from '../../../hooks';
5
+ import {MoreVerticalIcon} from '../../../icons';
6
+ import {Dropdown} from '../../Dropdown/Dropdown';
7
+ import {Link} from '../../Link/Link';
8
+ import {useState} from 'react';
9
+ import {Collapse} from '../../Collapse/Collapse';
8
10
 
9
11
  <Meta
10
12
  title="Components/Navigation/SubNavigationPanel"
@@ -12,7 +14,7 @@ import { Link } from "../../Link/Link";
12
14
  SubNavigationPanel: SubNavigationPanel,
13
15
  'SubNavigationPanel.Collapsed': SubNavigationPanel.Collapsed,
14
16
  }}
15
- args={{ children: 'Some content', isOpen: true, closeTitle: 'Close', openTitle: 'Open' }}
17
+ args={{children: 'Some content', isOpen: true, closeTitle: 'Close', openTitle: 'Open'}}
16
18
  />
17
19
 
18
20
  # SubNavigationPanel
@@ -33,9 +35,10 @@ When the panel is collapsed the content is hidden.
33
35
  <Canvas>
34
36
  <Story name="Standard">
35
37
  {args => {
38
+ const [isOpen, open, close] = useBooleanState(true);
36
39
  return (
37
40
  <SpaceContainer height={200}>
38
- <SubNavigationPanel {...args} />
41
+ <SubNavigationPanel {...args} isOpen={isOpen} open={open} close={close} />
39
42
  </SpaceContainer>
40
43
  );
41
44
  }}
@@ -44,34 +47,44 @@ When the panel is collapsed the content is hidden.
44
47
 
45
48
  <ArgsTable story="Standard" />
46
49
 
47
- ## Panel is collapsed
50
+ ## Panel with scrollable content
48
51
 
49
52
  <Canvas>
50
- <Story name="Collapsed">
53
+ <Story name="ScrollableContent">
51
54
  {args => {
55
+ const [isOpen, open, close] = useBooleanState(true);
52
56
  return (
53
57
  <SpaceContainer height={200}>
54
- <SubNavigationPanel {...args} isOpen={false} />
58
+ <SubNavigationPanel {...args} isOpen={isOpen} open={open} close={close}>
59
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
60
+ <br />
61
+ Fusce sed quam pharetra, lacinia nisl at, luctus ex.
62
+ <br />
63
+ Donec pretium est a augue dapibus, at semper ipsum vestibulum.
64
+ <br />
65
+ Aenean blandit metus a nibh blandit porta.
66
+ <br />
67
+ Phasellus placerat ligula sit amet vestibulum tristique.
68
+ </SubNavigationPanel>
55
69
  </SpaceContainer>
56
70
  );
57
71
  }}
58
72
  </Story>
59
73
  </Canvas>
60
74
 
61
-
62
- ## Panel with collapsed and expanded content
75
+ ## Panel with collapsed content using Dropdown component
63
76
 
64
77
  <Canvas>
65
78
  <Story name="CollapsedExpandedContent">
66
79
  {args => {
67
- const [isOpen, open, close] = useBooleanState(true);
80
+ const [isOpen, open, close] = useBooleanState(false);
68
81
  const [isDropdownOpen, openDropDown, closeDropDown] = useBooleanState(false);
69
82
  return (
70
83
  <SpaceContainer height={200}>
71
84
  <SubNavigationPanel {...args} isOpen={isOpen} open={open} close={close}>
72
85
  <SubNavigationPanel.Collapsed>
73
86
  <Dropdown>
74
- <MoreVerticalIcon title="Collapsed Content" onClick={openDropDown} />
87
+ <MoreVerticalIcon title="More" onClick={openDropDown} />
75
88
  {isDropdownOpen && (
76
89
  <Dropdown.Overlay onClose={closeDropDown}>
77
90
  <Dropdown.ItemCollection>
@@ -81,15 +94,74 @@ When the panel is collapsed the content is hidden.
81
94
  )}
82
95
  </Dropdown>
83
96
  </SubNavigationPanel.Collapsed>
84
- <Link>Expanded Content</Link>
85
- <div>Expanded Content</div>
86
- <div>Expanded Content</div>
87
- <div>Expanded Content</div>
88
- <div>Expanded Content</div>
89
- <div>Expanded Content</div>
90
- <div>Expanded Content</div>
91
- <div>Expanded Content</div>
92
- <div>Expanded Content</div>
97
+ Some content
98
+ </SubNavigationPanel>
99
+ </SpaceContainer>
100
+ );
101
+ }}
102
+ </Story>
103
+ </Canvas>
104
+
105
+ ## Panel without padding
106
+
107
+ <Canvas>
108
+ <Story name="ContentWithoutPadding">
109
+ {args => {
110
+ const [isOpen, open, close] = useBooleanState(true);
111
+ const [collapse, setCollapse] = useState(1);
112
+ return (
113
+ <SpaceContainer height={200}>
114
+ <SubNavigationPanel {...args} isOpen={isOpen} open={open} close={close} noPadding>
115
+ Some content
116
+ </SubNavigationPanel>
117
+ </SpaceContainer>
118
+ );
119
+ }}
120
+ </Story>
121
+ </Canvas>
122
+
123
+ ## Panel using Collapse components
124
+
125
+ <Canvas>
126
+ <Story name="ContentWithCollapseComponent">
127
+ {args => {
128
+ const [isOpen, open, close] = useBooleanState(true);
129
+ const [collapse, setCollapse] = useState(1);
130
+ return (
131
+ <SpaceContainer height={200}>
132
+ <SubNavigationPanel {...args} isOpen={isOpen} open={open} close={close} noPadding>
133
+ <Collapse
134
+ label="First Collapse"
135
+ collapseButtonLabel="Collapse"
136
+ isOpen={collapse === 1}
137
+ onCollapse={() => setCollapse(1)}
138
+ >
139
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
140
+ <br />
141
+ Fusce sed quam pharetra, lacinia nisl at, luctus ex.
142
+ <br />
143
+ Donec pretium est a augue dapibus, at semper ipsum vestibulum.
144
+ <br />
145
+ Aenean blandit metus a nibh blandit porta.
146
+ <br />
147
+ Phasellus placerat ligula sit amet vestibulum tristique.
148
+ </Collapse>
149
+ <Collapse
150
+ label="Second Collapse"
151
+ collapseButtonLabel="Collapse"
152
+ isOpen={collapse === 2}
153
+ onCollapse={() => setCollapse(2)}
154
+ >
155
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit.
156
+ <br />
157
+ Fusce sed quam pharetra, lacinia nisl at, luctus ex.
158
+ <br />
159
+ Donec pretium est a augue dapibus, at semper ipsum vestibulum.
160
+ <br />
161
+ Aenean blandit metus a nibh blandit porta.
162
+ <br />
163
+ Phasellus placerat ligula sit amet vestibulum tristique.
164
+ </Collapse>
93
165
  </SubNavigationPanel>
94
166
  </SpaceContainer>
95
167
  );