Skip to content

Commit 98d0610

Browse files
authored
feat(Button): Change icon to boolean and remove iconPlacement (#1413)
1 parent 74a47ab commit 98d0610

File tree

9 files changed

+116
-115
lines changed

9 files changed

+116
-115
lines changed

packages/react/src/components/Button/Button.stories.tsx

+59-61
Original file line numberDiff line numberDiff line change
@@ -25,46 +25,28 @@ const stack = (Story: PartialStoryFn<ReactRenderer>) => (
2525

2626
const icon = <akselIcons.FloppydiskIcon />;
2727

28-
type AkselIcon = (typeof akselIcons)['AirplaneFillIcon'];
29-
type AkselIcons = Record<string, AkselIcon>;
30-
3128
export const Preview: Story = {
32-
render: ({ icon = '', ...args }) => {
33-
// Hack to get dynamic preview of Aksel icons in Storybook
34-
const Icon: AkselIcon | undefined = (akselIcons as AkselIcons)[
35-
icon as string
36-
];
37-
38-
return (
39-
<Button
40-
{...args}
41-
icon={Icon ? <Icon /> : undefined}
42-
></Button>
43-
);
29+
render: ({ ...args }) => {
30+
return <Button {...args} />;
4431
},
4532
args: {
4633
children: 'Knapp',
4734
disabled: false,
4835
variant: 'primary',
4936
color: 'first',
5037
size: 'medium',
51-
},
52-
argTypes: {
53-
icon: {
54-
control: 'select',
55-
options: Object.keys(akselIcons),
56-
},
38+
icon: false,
39+
fullWidth: false,
5740
},
5841
};
5942

6043
export const UsedAsLink: StoryFn<typeof Button> = () => (
6144
<Button
6245
as='a'
63-
icon={<akselIcons.PersonChatIcon />}
64-
iconPlacement='right'
6546
target='_blank'
6647
href='https://www.designsystemet.no'
6748
>
49+
<akselIcons.PersonChatIcon />
6850
Gå til Designsystemet
6951
</Button>
7052
);
@@ -137,74 +119,96 @@ Variants.decorators = [
137119
export const WithIcon: StoryFn<typeof Button> = () => (
138120
<>
139121
<Button
140-
icon={icon}
122+
icon={true}
141123
variant='primary'
142124
aria-label='Primary med ikon'
143-
></Button>
125+
>
126+
{icon}
127+
</Button>
144128
<Button
145-
icon={icon}
129+
icon={true}
146130
variant='secondary'
147131
aria-label=' Secondary med ikon'
148-
></Button>
132+
>
133+
{icon}
134+
</Button>
149135
<Button
150-
icon={icon}
136+
icon={true}
151137
variant='tertiary'
152138
aria-label='Tertiary med ikon'
153-
></Button>
139+
>
140+
{icon}
141+
</Button>
154142
<Button
155-
icon={icon}
143+
icon={true}
156144
color='second'
157145
variant='primary'
158146
aria-label='Primary med ikon'
159-
></Button>
147+
>
148+
{icon}
149+
</Button>
160150
<Button
161-
icon={icon}
151+
icon={true}
162152
color='second'
163153
variant='secondary'
164154
aria-label=' Secondary med ikon'
165-
></Button>
155+
>
156+
{icon}
157+
</Button>
166158
<Button
167-
icon={icon}
159+
icon={true}
168160
color='second'
169161
variant='tertiary'
170162
aria-label='Tertiary med ikon'
171163
></Button>
172164
<Button
173-
icon={<akselIcons.CheckmarkIcon />}
165+
icon={true}
174166
color='success'
175167
variant='primary'
176168
aria-label='Primary med ikon'
177-
></Button>
169+
>
170+
<akselIcons.CheckmarkIcon />
171+
</Button>
178172
<Button
179-
icon={<akselIcons.CheckmarkIcon />}
173+
icon={true}
180174
color='success'
181175
variant='secondary'
182176
aria-label=' Secondary med ikon'
183-
></Button>
177+
>
178+
<akselIcons.CheckmarkIcon />
179+
</Button>
184180
<Button
185-
icon={<akselIcons.CheckmarkIcon />}
181+
icon={true}
186182
color='success'
187183
variant='tertiary'
188184
aria-label='Tertiary med ikon'
189-
></Button>
185+
>
186+
<akselIcons.CheckmarkIcon />
187+
</Button>
190188
<Button
191-
icon={<akselIcons.TrashIcon />}
189+
icon={true}
192190
color='danger'
193191
variant='primary'
194192
aria-label='Primary med ikon'
195-
></Button>
193+
>
194+
<akselIcons.TrashIcon />
195+
</Button>
196196
<Button
197-
icon={<akselIcons.TrashIcon />}
197+
icon={true}
198198
color='danger'
199199
variant='secondary'
200200
aria-label=' Secondary med ikon'
201-
></Button>
201+
>
202+
<akselIcons.TrashIcon />
203+
</Button>
202204
<Button
203-
icon={<akselIcons.TrashIcon />}
205+
icon={true}
204206
color='danger'
205207
variant='tertiary'
206208
aria-label='Tertiary med ikon'
207-
></Button>
209+
>
210+
<akselIcons.TrashIcon />
211+
</Button>
208212
</>
209213
);
210214

@@ -223,22 +227,16 @@ WithIcon.decorators = [
223227

224228
export const WithIconAndText: StoryFn<typeof Button> = () => (
225229
<>
226-
<Button
227-
icon={icon}
228-
variant='primary'
229-
>
230+
<Button variant='primary'>
231+
{icon}
230232
Primary
231233
</Button>
232-
<Button
233-
icon={icon}
234-
variant='secondary'
235-
>
234+
<Button variant='secondary'>
235+
{icon}
236236
Secondary
237237
</Button>
238-
<Button
239-
icon={icon}
240-
variant='tertiary'
241-
>
238+
<Button variant='tertiary'>
239+
{icon}
242240
Tertiary
243241
</Button>
244242
</>
@@ -249,10 +247,10 @@ WithIconAndText.decorators = [stack];
249247
export const WithSpinner: StoryFn<typeof Button> = () => (
250248
<>
251249
<Button
252-
icon={icon}
253250
variant='primary'
254251
aria-disabled
255252
>
253+
{icon}
256254
<Spinner
257255
variant='interaction'
258256
title='loading'
@@ -261,10 +259,10 @@ export const WithSpinner: StoryFn<typeof Button> = () => (
261259
Laster...
262260
</Button>
263261
<Button
264-
icon={icon}
265262
variant='secondary'
266263
aria-disabled
267264
>
265+
{icon}
268266
<Spinner
269267
variant='interaction'
270268
title='loading'
@@ -273,10 +271,10 @@ export const WithSpinner: StoryFn<typeof Button> = () => (
273271
Laster...
274272
</Button>
275273
<Button
276-
icon={icon}
277274
variant='tertiary'
278275
aria-disabled
279276
>
277+
{icon}
280278
<Spinner
281279
variant='interaction'
282280
title='loading'

packages/react/src/components/Button/Button.test.tsx

+14-4
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,14 @@ describe('Button', () => {
6969
);
7070

7171
it('should render an icon on the left side of text when given an existing iconName and no iconPlacement', () => {
72-
render({ icon: <CheckmarkIcon />, children: 'Button text' });
72+
render({
73+
children: (
74+
<>
75+
<CheckmarkIcon />
76+
Button text
77+
</>
78+
),
79+
});
7380
const icon = screen.getByRole('img');
7481
expect(
7582
screen.getByRole('button', {
@@ -80,9 +87,12 @@ describe('Button', () => {
8087

8188
it('should render an icon on the right side of text when given an existing iconName and iconPlacement is right', () => {
8289
render({
83-
icon: <CheckmarkIcon />,
84-
iconPlacement: 'right',
85-
children: 'Button text',
90+
children: (
91+
<>
92+
Button text
93+
<CheckmarkIcon />
94+
</>
95+
),
8696
});
8797
const icon = screen.getByRole('img');
8898
expect(

packages/react/src/components/Button/Button.tsx

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { forwardRef } from 'react';
2-
import type { ReactNode, ButtonHTMLAttributes } from 'react';
2+
import type { ButtonHTMLAttributes } from 'react';
33
import cl from 'clsx';
44

55
import utilityClasses from '../../utilities/utility.module.css';
@@ -16,14 +16,10 @@ export type ButtonProps = {
1616
size?: 'small' | 'medium' | 'large';
1717
/** If `Button` should fill full width of its container */
1818
fullWidth?: boolean;
19-
/** Icon to be rendered in the button. This should be a React component that renders an SVG object.
20-
* @deprecated This will be changed to a `boolean` in the future to toggle icon only styling, icons will be passed as children
19+
/** Toggle icon only styling, pass icon as children
20+
* @default false
2121
*/
22-
icon?: ReactNode;
23-
/** Icon position inside Button
24-
* @deprecated This will be removed as we will use `children` to pass icons
25-
*/
26-
iconPlacement?: 'right' | 'left';
22+
icon?: boolean;
2723
} & ButtonHTMLAttributes<HTMLButtonElement>;
2824

2925
/**
@@ -38,8 +34,7 @@ export const Button: OverridableComponent<ButtonProps, HTMLButtonElement> =
3834
variant = 'primary',
3935
size = 'medium',
4036
fullWidth = false,
41-
iconPlacement = 'left',
42-
icon,
37+
icon = false,
4338
type = 'button',
4439
className,
4540
as: Component = 'button',
@@ -57,14 +52,12 @@ export const Button: OverridableComponent<ButtonProps, HTMLButtonElement> =
5752
classes[variant],
5853
classes[color],
5954
{ [classes.fullWidth]: fullWidth },
60-
{ [classes.onlyIcon]: !children && icon },
55+
{ [classes.onlyIcon]: icon },
6156
className,
6257
)}
6358
{...rest}
6459
>
65-
{iconPlacement === 'left' && icon}
6660
{children}
67-
{iconPlacement === 'right' && icon}
6861
</Component>
6962
),
7063
);

packages/react/src/components/Card/Card.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,8 @@ export const Composed: Story = () => (
334334
variant='secondary'
335335
color='danger'
336336
size='small'
337-
icon={<TrashFillIcon aria-hidden />}
338337
>
338+
<TrashFillIcon aria-hidden />
339339
Fjern
340340
</Button>
341341
</div>

packages/react/src/components/DropdownMenu/DropdownMenu.stories.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,16 @@ export const Icons: StoryFn<typeof DropdownMenu> = (args) => {
105105
as='a'
106106
href='https://github.com/digdir/designsystemet'
107107
target='_blank'
108-
icon={<LinkIcon />}
109108
>
109+
<LinkIcon />
110110
Github
111111
</DropdownMenu.Item>
112112
<DropdownMenu.Item
113113
as='a'
114114
href='https://designsystemet.no'
115115
target='_blank'
116-
icon={<LinkIcon />}
117116
>
117+
<LinkIcon />
118118
Designsystemet.no
119119
</DropdownMenu.Item>
120120
</DropdownMenu.Group>
@@ -155,16 +155,16 @@ export const InPortal: StoryFn<typeof DropdownMenu> = (args) => {
155155
as='a'
156156
href='https://github.com/digdir/designsystemet'
157157
target='_blank'
158-
icon={<LinkIcon />}
159158
>
159+
<LinkIcon />
160160
Github
161161
</DropdownMenu.Item>
162162
<DropdownMenu.Item
163163
as='a'
164164
href='https://designsystemet.no'
165165
target='_blank'
166-
icon={<LinkIcon />}
167166
>
167+
<LinkIcon />
168168
Designsystemet.no
169169
</DropdownMenu.Item>
170170
</DropdownMenu.Group>

packages/react/src/components/Modal/ModalHeader/ModalHeader.tsx

+7-7
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ export const ModalHeader = forwardRef<HTMLDivElement, ModalHeaderProps>(
5454
size='medium'
5555
onClick={context?.closeModal}
5656
autoFocus
57-
icon={
58-
<XMarkIcon
59-
title='close modal'
60-
fontSize='1.5em'
61-
/>
62-
}
63-
/>
57+
icon={true}
58+
>
59+
<XMarkIcon
60+
title='close modal'
61+
fontSize='1.5em'
62+
/>
63+
</Button>
6464
)}
6565
</div>
6666
);

0 commit comments

Comments
 (0)