uikit-react-public 0.50.0 → 0.50.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/Button/Button.d.ts +8 -4
- package/dist/components/Button/Button.stories.d.ts +11 -2
- package/dist/components/Button/style/buttonPrimarySubtleStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonSecondaryStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonSecondarySubtleStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.d.ts +4 -0
- package/dist/components/Button/style/buttonTertiaryDestructiveStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryNoPaddingStyle.d.ts +1 -1
- package/dist/components/Button/style/buttonTertiaryStyle.d.ts +1 -1
- package/dist/index.js +4695 -4630
- package/lib/components/Button/Button.mdx +12 -0
- package/lib/components/Button/Button.stories.tsx +46 -0
- package/lib/components/Button/Button.tsx +48 -25
- package/lib/components/Button/__tests__/Button.test.tsx +120 -1
- package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +11 -11
- package/lib/components/Button/style/buttonAccentStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimaryDestructiveStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimaryStyle.ts +2 -0
- package/lib/components/Button/style/buttonPrimarySubtleStyle.ts +10 -11
- package/lib/components/Button/style/buttonPrimaryWarningStyle.ts +2 -0
- package/lib/components/Button/style/buttonSecondaryDestructiveStyle.ts +13 -7
- package/lib/components/Button/style/buttonSecondaryStyle.ts +49 -16
- package/lib/components/Button/style/buttonSecondarySubtleStyle.ts +15 -13
- package/lib/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.ts +34 -0
- package/lib/components/Button/style/buttonTertiaryDestructiveStyle.ts +9 -8
- package/lib/components/Button/style/buttonTertiaryNoPaddingStyle.ts +13 -15
- package/lib/components/Button/style/buttonTertiaryStyle.ts +10 -9
- package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,8 @@ export const usage = {
|
|
|
13
13
|
default: `<Button>Default Button</Button>`,
|
|
14
14
|
secondary: `<Button variant='secondary'>Secondary Button</Button>`,
|
|
15
15
|
destructive: `<Button variant='primary-destructive'>Destructive Button</Button>`,
|
|
16
|
+
destructiveNoPadding: `<Button variant='tertiary-destructive-no-padding'>Destructive Action</Button>`,
|
|
17
|
+
onDark: `<Button variant='secondary' onLight={false}>Secondary Button</Button>`,
|
|
16
18
|
withIcon: `<Button icon={<Icon.AlertTriangle />}>Button</Button>`,
|
|
17
19
|
loading: `<Button loading>Loading Button</Button>`,
|
|
18
20
|
link: `<Button as='a' href='https://www.ucl.ac.uk' target='_blank'>Go to UCL's website</Button>`,
|
|
@@ -41,6 +43,16 @@ Use `variant` to control hierarchy and emphasis.
|
|
|
41
43
|
<Canvas of={ButtonStories.Accent} />
|
|
42
44
|
<Canvas of={ButtonStories.PrimarySubtle} />
|
|
43
45
|
<Canvas of={ButtonStories.Destructive} source={{ code: usage.destructive }} />
|
|
46
|
+
<Canvas
|
|
47
|
+
of={ButtonStories.DestructiveTertiaryNoPadding}
|
|
48
|
+
source={{ code: usage.destructiveNoPadding }}
|
|
49
|
+
/>
|
|
50
|
+
|
|
51
|
+
## Dark backgrounds
|
|
52
|
+
|
|
53
|
+
Set `onLight={false}` when a supported inverse variant is placed directly on a dark background.
|
|
54
|
+
|
|
55
|
+
<Canvas of={ButtonStories.OnDark} source={{ code: usage.onDark }} />
|
|
44
56
|
|
|
45
57
|
## Sizes
|
|
46
58
|
|
|
@@ -33,6 +33,7 @@ const variants = [
|
|
|
33
33
|
'primary-destructive',
|
|
34
34
|
'secondary-destructive',
|
|
35
35
|
'tertiary-destructive',
|
|
36
|
+
'tertiary-destructive-no-padding',
|
|
36
37
|
'primary-warning',
|
|
37
38
|
] as const;
|
|
38
39
|
|
|
@@ -80,6 +81,12 @@ const meta = {
|
|
|
80
81
|
control: { type: 'boolean' },
|
|
81
82
|
type: 'boolean',
|
|
82
83
|
},
|
|
84
|
+
onLight: {
|
|
85
|
+
control: { type: 'boolean' },
|
|
86
|
+
type: 'boolean',
|
|
87
|
+
description:
|
|
88
|
+
'Set to false for supported inverse variants rendered on a dark background.',
|
|
89
|
+
},
|
|
83
90
|
disabled: {
|
|
84
91
|
control: { type: 'boolean' },
|
|
85
92
|
type: 'boolean',
|
|
@@ -193,6 +200,45 @@ export const Destructive: Story = {
|
|
|
193
200
|
},
|
|
194
201
|
};
|
|
195
202
|
|
|
203
|
+
export const DestructiveTertiaryNoPadding: Story = {
|
|
204
|
+
name: 'Destructive tertiary without padding',
|
|
205
|
+
args: {
|
|
206
|
+
variant: 'tertiary-destructive-no-padding',
|
|
207
|
+
children: 'Destructive action',
|
|
208
|
+
},
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
export const OnDark: Story = {
|
|
212
|
+
name: 'Inverse variants on dark',
|
|
213
|
+
args: {
|
|
214
|
+
onLight: false,
|
|
215
|
+
},
|
|
216
|
+
render: () => (
|
|
217
|
+
<div
|
|
218
|
+
style={{
|
|
219
|
+
alignItems: 'center',
|
|
220
|
+
background: theme.colour.bg.inversePrimary,
|
|
221
|
+
display: 'flex',
|
|
222
|
+
gap: theme.padding.p24,
|
|
223
|
+
padding: theme.padding.p32,
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
226
|
+
<Button
|
|
227
|
+
onLight={false}
|
|
228
|
+
variant='secondary'
|
|
229
|
+
>
|
|
230
|
+
Secondary action
|
|
231
|
+
</Button>
|
|
232
|
+
<Button
|
|
233
|
+
onLight={false}
|
|
234
|
+
variant='tertiary-no-padding'
|
|
235
|
+
>
|
|
236
|
+
Tertiary action
|
|
237
|
+
</Button>
|
|
238
|
+
</div>
|
|
239
|
+
),
|
|
240
|
+
};
|
|
241
|
+
|
|
196
242
|
export const PrimarySubtle: Story = {
|
|
197
243
|
args: {
|
|
198
244
|
variant: 'primary-subtle',
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
ReactElement,
|
|
5
5
|
ElementType,
|
|
6
6
|
ComponentPropsWithRef,
|
|
7
|
+
cloneElement,
|
|
7
8
|
memo,
|
|
8
9
|
} from 'react';
|
|
9
10
|
import { css, cx } from '@emotion/css';
|
|
@@ -19,6 +20,7 @@ import buttonTertiaryStyle from './style/buttonTertiaryStyle';
|
|
|
19
20
|
import buttonPrimaryDestructiveStyle from './style/buttonPrimaryDestructiveStyle';
|
|
20
21
|
import buttonSecondaryDestructiveStyle from './style/buttonSecondaryDestructiveStyle';
|
|
21
22
|
import buttonTertiaryDestructiveStyle from './style/buttonTertiaryDestructiveStyle';
|
|
23
|
+
import buttonTertiaryDestructiveNoPaddingStyle from './style/buttonTertiaryDestructiveNoPaddingStyle';
|
|
22
24
|
import buttonPrimaryWarningStyle from './style/buttonPrimaryWarningStyle';
|
|
23
25
|
import buttonPrimarySubtleStyle from './style/buttonPrimarySubtleStyle';
|
|
24
26
|
import buttonSecondarySubtleStyle from './style/buttonSecondarySubtleStyle';
|
|
@@ -39,12 +41,14 @@ export type ButtonVariant =
|
|
|
39
41
|
| 'primary-destructive'
|
|
40
42
|
| 'secondary-destructive'
|
|
41
43
|
| 'tertiary-destructive'
|
|
44
|
+
| 'tertiary-destructive-no-padding'
|
|
42
45
|
| 'primary-warning';
|
|
43
46
|
|
|
44
47
|
const DESTRUCTIVE_VARIANT_MAP: Partial<Record<ButtonVariant, ButtonVariant>> = {
|
|
45
48
|
primary: 'primary-destructive',
|
|
46
49
|
secondary: 'secondary-destructive',
|
|
47
50
|
tertiary: 'tertiary-destructive',
|
|
51
|
+
'tertiary-no-padding': 'tertiary-destructive-no-padding',
|
|
48
52
|
};
|
|
49
53
|
|
|
50
54
|
// Legacy size values from the old Button API
|
|
@@ -52,12 +56,14 @@ type LegacySize = 'default';
|
|
|
52
56
|
|
|
53
57
|
export interface ButtonBaseProps {
|
|
54
58
|
variant?: ButtonVariant;
|
|
55
|
-
/** @deprecated Use
|
|
59
|
+
/** @deprecated Use a destructive variant directly */
|
|
56
60
|
destructive?: boolean;
|
|
57
61
|
size?: 'xsmall' | 'small' | 'medium' | 'large' | LegacySize;
|
|
62
|
+
/** Whether the button is rendered on a light background */
|
|
63
|
+
onLight?: boolean;
|
|
58
64
|
selected?: boolean;
|
|
59
65
|
disabled?: boolean;
|
|
60
|
-
icon?: ReactElement
|
|
66
|
+
icon?: ReactElement<{ className?: string }>;
|
|
61
67
|
iconPosition?: 'left' | 'right';
|
|
62
68
|
tooltip?: string;
|
|
63
69
|
loading?: boolean;
|
|
@@ -92,7 +98,7 @@ const normalizeVariantProp = (
|
|
|
92
98
|
|
|
93
99
|
if (!destructiveVariant) {
|
|
94
100
|
console.warn(
|
|
95
|
-
`Button variant '${variant}' does not support the destructive prop. Use a destructive variant explicitly, or use one of: primary, secondary, tertiary.`
|
|
101
|
+
`Button variant '${variant}' does not support the destructive prop. Use a destructive variant explicitly, or use one of: primary, secondary, tertiary, tertiary-no-padding.`
|
|
96
102
|
);
|
|
97
103
|
return variant;
|
|
98
104
|
}
|
|
@@ -102,9 +108,10 @@ const normalizeVariantProp = (
|
|
|
102
108
|
|
|
103
109
|
const Button = <C extends ElementType = 'button'>({
|
|
104
110
|
as,
|
|
105
|
-
variant
|
|
111
|
+
variant,
|
|
106
112
|
destructive = false,
|
|
107
113
|
size = 'medium',
|
|
114
|
+
onLight = true,
|
|
108
115
|
selected = false,
|
|
109
116
|
disabled = false,
|
|
110
117
|
icon,
|
|
@@ -125,7 +132,10 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
125
132
|
const [isHovered, setIsHovered] = useState(false);
|
|
126
133
|
const [theme] = useTheme();
|
|
127
134
|
|
|
128
|
-
const resolvedVariant = normalizeVariantProp(
|
|
135
|
+
const resolvedVariant = normalizeVariantProp(
|
|
136
|
+
variant ?? (destructive ? 'primary' : 'accent'),
|
|
137
|
+
destructive
|
|
138
|
+
);
|
|
129
139
|
const resolvedSize = normalizeSizeprop(size);
|
|
130
140
|
const buttonTypography = {
|
|
131
141
|
xsmall: theme.typography.body.smMedium,
|
|
@@ -136,7 +146,7 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
136
146
|
|
|
137
147
|
const baseStyle = css`
|
|
138
148
|
all: unset;
|
|
139
|
-
border:
|
|
149
|
+
border: 0;
|
|
140
150
|
display: inline-flex;
|
|
141
151
|
align-items: center;
|
|
142
152
|
justify-content: center;
|
|
@@ -160,14 +170,26 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
160
170
|
}
|
|
161
171
|
`;
|
|
162
172
|
|
|
163
|
-
const
|
|
173
|
+
const contentIconSize = {
|
|
174
|
+
xsmall: 16,
|
|
175
|
+
small: 20,
|
|
176
|
+
medium: 24,
|
|
177
|
+
large: 24,
|
|
178
|
+
}[resolvedSize];
|
|
179
|
+
const iconOnlySize = resolvedSize === 'xsmall' ? 20 : 24;
|
|
180
|
+
const spinnerSize = resolvedSize === 'xsmall' ? 20 : 24;
|
|
164
181
|
const paddingPx = resolvedSize === 'xsmall' ? 8 : 16;
|
|
165
182
|
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
183
|
+
const iconStyle = css`
|
|
184
|
+
color: var(--ucl-uikit-button-icon-colour, currentColor);
|
|
185
|
+
width: ${children ? contentIconSize : iconOnlySize}px;
|
|
186
|
+
height: ${children ? contentIconSize : iconOnlySize}px;
|
|
170
187
|
`;
|
|
188
|
+
const styledIcon = icon
|
|
189
|
+
? cloneElement(icon, {
|
|
190
|
+
className: cx(icon.props.className, iconStyle),
|
|
191
|
+
})
|
|
192
|
+
: undefined;
|
|
171
193
|
|
|
172
194
|
const sizeExtraSmallStyle = css`
|
|
173
195
|
height: 32px;
|
|
@@ -196,33 +218,31 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
196
218
|
const variantStyle = {
|
|
197
219
|
accent: buttonAccentStyle(theme, selected, disabled, loading),
|
|
198
220
|
primary: buttonPrimaryStyle(theme, selected, disabled, loading),
|
|
199
|
-
secondary: buttonSecondaryStyle(
|
|
200
|
-
tertiary: buttonTertiaryStyle(
|
|
221
|
+
secondary: buttonSecondaryStyle(
|
|
201
222
|
theme,
|
|
202
223
|
selected,
|
|
203
224
|
disabled,
|
|
204
225
|
loading,
|
|
205
|
-
|
|
226
|
+
onLight
|
|
206
227
|
),
|
|
228
|
+
tertiary: buttonTertiaryStyle(theme, selected, disabled, loading),
|
|
207
229
|
'primary-subtle': buttonPrimarySubtleStyle(
|
|
208
230
|
theme,
|
|
209
231
|
selected,
|
|
210
232
|
disabled,
|
|
211
|
-
loading
|
|
212
|
-
paddingPx
|
|
233
|
+
loading
|
|
213
234
|
),
|
|
214
235
|
'secondary-subtle': buttonSecondarySubtleStyle(
|
|
215
236
|
theme,
|
|
216
237
|
selected,
|
|
217
238
|
disabled,
|
|
218
|
-
loading
|
|
219
|
-
paddingPx
|
|
239
|
+
loading
|
|
220
240
|
),
|
|
221
241
|
'tertiary-no-padding': buttonTertiaryNoPaddingStyle(
|
|
222
242
|
theme,
|
|
223
243
|
disabled,
|
|
224
244
|
loading,
|
|
225
|
-
|
|
245
|
+
onLight
|
|
226
246
|
),
|
|
227
247
|
'primary-destructive': buttonPrimaryDestructiveStyle(
|
|
228
248
|
theme,
|
|
@@ -240,8 +260,12 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
240
260
|
theme,
|
|
241
261
|
selected,
|
|
242
262
|
disabled,
|
|
243
|
-
loading
|
|
244
|
-
|
|
263
|
+
loading
|
|
264
|
+
),
|
|
265
|
+
'tertiary-destructive-no-padding': buttonTertiaryDestructiveNoPaddingStyle(
|
|
266
|
+
theme,
|
|
267
|
+
disabled,
|
|
268
|
+
loading
|
|
245
269
|
),
|
|
246
270
|
'primary-warning': buttonPrimaryWarningStyle(
|
|
247
271
|
theme,
|
|
@@ -271,7 +295,6 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
271
295
|
variantStyle,
|
|
272
296
|
disabled && commonDisabledStyle,
|
|
273
297
|
loading && loadingStyle,
|
|
274
|
-
!children && iconOnlyStyle,
|
|
275
298
|
className
|
|
276
299
|
);
|
|
277
300
|
|
|
@@ -294,15 +317,15 @@ const Button = <C extends ElementType = 'button'>({
|
|
|
294
317
|
>
|
|
295
318
|
{loading ? (
|
|
296
319
|
<Spinner
|
|
297
|
-
size={
|
|
320
|
+
size={spinnerSize}
|
|
298
321
|
strokeWidth={8}
|
|
299
322
|
inheritColour
|
|
300
323
|
/>
|
|
301
324
|
) : (
|
|
302
325
|
<>
|
|
303
|
-
{
|
|
326
|
+
{styledIcon && iconPosition === 'left' && styledIcon}
|
|
304
327
|
{children}
|
|
305
|
-
{
|
|
328
|
+
{styledIcon && iconPosition === 'right' && styledIcon}
|
|
306
329
|
</>
|
|
307
330
|
)}
|
|
308
331
|
</Component>
|
|
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
|
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
4
|
import Button from '../Button';
|
|
5
5
|
import Icon from '../../Icon';
|
|
6
|
-
import { darkTheme, ThemeContextProvider } from '../../../theme';
|
|
6
|
+
import { darkTheme, theme, ThemeContextProvider } from '../../../theme';
|
|
7
7
|
|
|
8
8
|
const hexToRgb = (hex: string) => {
|
|
9
9
|
const value = hex.replace('#', '');
|
|
@@ -255,6 +255,26 @@ describe('Button', () => {
|
|
|
255
255
|
);
|
|
256
256
|
|
|
257
257
|
expect(renderResult.container.firstChild).toMatchSnapshot();
|
|
258
|
+
expect(getComputedStyle(screen.getByRole('button')).backgroundColor).toBe(
|
|
259
|
+
hexToRgb(theme.colour.fill.critical)
|
|
260
|
+
);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test('maps legacy destructive prop for the no-padding variant', () => {
|
|
264
|
+
render(
|
|
265
|
+
<ThemeContextProvider>
|
|
266
|
+
<Button
|
|
267
|
+
variant='tertiary-no-padding'
|
|
268
|
+
destructive
|
|
269
|
+
>
|
|
270
|
+
Delete
|
|
271
|
+
</Button>
|
|
272
|
+
</ThemeContextProvider>
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
expect(getComputedStyle(screen.getByRole('button')).color).toBe(
|
|
276
|
+
hexToRgb(theme.colour.text.critical)
|
|
277
|
+
);
|
|
258
278
|
});
|
|
259
279
|
|
|
260
280
|
test('warns when destructive prop is used with unsupported variant', () => {
|
|
@@ -320,4 +340,103 @@ describe('Button', () => {
|
|
|
320
340
|
`box-shadow:${expectedFocusShadow.replace(/\s/g, '')}`
|
|
321
341
|
);
|
|
322
342
|
});
|
|
343
|
+
|
|
344
|
+
test.each([
|
|
345
|
+
['xsmall', '32px', '16px'],
|
|
346
|
+
['small', '40px', '20px'],
|
|
347
|
+
['medium', '48px', '24px'],
|
|
348
|
+
['large', '56px', '24px'],
|
|
349
|
+
] as const)(
|
|
350
|
+
'matches the Figma dimensions for the %s size',
|
|
351
|
+
(size, expectedHeight, expectedIconSize) => {
|
|
352
|
+
render(
|
|
353
|
+
<ThemeContextProvider>
|
|
354
|
+
<Button
|
|
355
|
+
icon={<Icon.ChevronRight />}
|
|
356
|
+
size={size}
|
|
357
|
+
>
|
|
358
|
+
Action
|
|
359
|
+
</Button>
|
|
360
|
+
</ThemeContextProvider>
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
expect(getComputedStyle(screen.getByRole('button')).height).toBe(
|
|
364
|
+
expectedHeight
|
|
365
|
+
);
|
|
366
|
+
expect(getComputedStyle(screen.getByTestId('ucl-uikit-icon')).width).toBe(
|
|
367
|
+
expectedIconSize
|
|
368
|
+
);
|
|
369
|
+
}
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
test('uses the larger extra-small icon when the button is icon-only', () => {
|
|
373
|
+
render(
|
|
374
|
+
<ThemeContextProvider>
|
|
375
|
+
<Button
|
|
376
|
+
aria-label='Next'
|
|
377
|
+
icon={<Icon.ChevronRight />}
|
|
378
|
+
size='xsmall'
|
|
379
|
+
/>
|
|
380
|
+
</ThemeContextProvider>
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
expect(getComputedStyle(screen.getByTestId('ucl-uikit-icon')).width).toBe(
|
|
384
|
+
'20px'
|
|
385
|
+
);
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
test('styles a non-SVG icon through its className contract', () => {
|
|
389
|
+
render(
|
|
390
|
+
<ThemeContextProvider>
|
|
391
|
+
<Button
|
|
392
|
+
icon={
|
|
393
|
+
<span
|
|
394
|
+
className='custom-icon'
|
|
395
|
+
data-testid='custom-icon'
|
|
396
|
+
/>
|
|
397
|
+
}
|
|
398
|
+
size='xsmall'
|
|
399
|
+
>
|
|
400
|
+
Action
|
|
401
|
+
</Button>
|
|
402
|
+
</ThemeContextProvider>
|
|
403
|
+
);
|
|
404
|
+
|
|
405
|
+
const icon = screen.getByTestId('custom-icon');
|
|
406
|
+
expect(icon).toHaveClass('custom-icon');
|
|
407
|
+
expect(getComputedStyle(icon).width).toBe('16px');
|
|
408
|
+
expect(getComputedStyle(icon).height).toBe('16px');
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
test.each([
|
|
412
|
+
'tertiary-no-padding',
|
|
413
|
+
'tertiary-destructive-no-padding',
|
|
414
|
+
] as const)('removes padding from the %s variant', (variant) => {
|
|
415
|
+
render(
|
|
416
|
+
<ThemeContextProvider>
|
|
417
|
+
<Button variant={variant}>Action</Button>
|
|
418
|
+
</ThemeContextProvider>
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
expect(getComputedStyle(screen.getByRole('button')).padding).toBe('0px');
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
test('uses inverse secondary tokens on a dark background', () => {
|
|
425
|
+
render(
|
|
426
|
+
<ThemeContextProvider>
|
|
427
|
+
<Button
|
|
428
|
+
onLight={false}
|
|
429
|
+
variant='secondary'
|
|
430
|
+
>
|
|
431
|
+
Action
|
|
432
|
+
</Button>
|
|
433
|
+
</ThemeContextProvider>
|
|
434
|
+
);
|
|
435
|
+
|
|
436
|
+
const style = getComputedStyle(screen.getByRole('button'));
|
|
437
|
+
expect(style.color).toBe(hexToRgb(theme.colour.text.brandInverse));
|
|
438
|
+
expect(document.head.textContent?.replace(/\s/g, '')).toContain(
|
|
439
|
+
`outline:${theme.border.b2}solid${theme.colour.border.brandInverse}`
|
|
440
|
+
);
|
|
441
|
+
});
|
|
323
442
|
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
exports[`Button > maps legacy destructive prop to destructive variants 1`] = `
|
|
4
4
|
<button
|
|
5
5
|
aria-disabled="false"
|
|
6
|
-
class="ucl-uikit-button css-
|
|
6
|
+
class="ucl-uikit-button css-usvl64"
|
|
7
7
|
data-testid="ucl-uikit-button"
|
|
8
8
|
>
|
|
9
9
|
Delete
|
|
@@ -13,7 +13,7 @@ exports[`Button > maps legacy destructive prop to destructive variants 1`] = `
|
|
|
13
13
|
exports[`Button > maps legacy size default to medium 1`] = `
|
|
14
14
|
<button
|
|
15
15
|
aria-disabled="false"
|
|
16
|
-
class="ucl-uikit-button css-
|
|
16
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
17
17
|
data-testid="ucl-uikit-button"
|
|
18
18
|
>
|
|
19
19
|
Legacy default size
|
|
@@ -23,7 +23,7 @@ exports[`Button > maps legacy size default to medium 1`] = `
|
|
|
23
23
|
exports[`Button > snapshot: 'as' prop with 'a' 1`] = `
|
|
24
24
|
<a
|
|
25
25
|
aria-disabled="false"
|
|
26
|
-
class="ucl-uikit-button css-
|
|
26
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
27
27
|
data-testid="ucl-uikit-button"
|
|
28
28
|
href="https://ucl.ac.uk"
|
|
29
29
|
>
|
|
@@ -34,7 +34,7 @@ exports[`Button > snapshot: 'as' prop with 'a' 1`] = `
|
|
|
34
34
|
exports[`Button > snapshot: loading 1`] = `
|
|
35
35
|
<button
|
|
36
36
|
aria-disabled="false"
|
|
37
|
-
class="ucl-uikit-button css-
|
|
37
|
+
class="ucl-uikit-button css-gbx8ga"
|
|
38
38
|
data-testid="ucl-uikit-button"
|
|
39
39
|
disabled=""
|
|
40
40
|
>
|
|
@@ -67,7 +67,7 @@ exports[`Button > snapshot: loading 1`] = `
|
|
|
67
67
|
exports[`Button > snapshot: no props 1`] = `
|
|
68
68
|
<button
|
|
69
69
|
aria-disabled="false"
|
|
70
|
-
class="ucl-uikit-button css-
|
|
70
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
71
71
|
data-testid="ucl-uikit-button"
|
|
72
72
|
/>
|
|
73
73
|
`;
|
|
@@ -75,7 +75,7 @@ exports[`Button > snapshot: no props 1`] = `
|
|
|
75
75
|
exports[`Button > snapshot: testId prop 1`] = `
|
|
76
76
|
<button
|
|
77
77
|
aria-disabled="false"
|
|
78
|
-
class="ucl-uikit-button css-
|
|
78
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
79
79
|
data-testid="test123"
|
|
80
80
|
/>
|
|
81
81
|
`;
|
|
@@ -83,7 +83,7 @@ exports[`Button > snapshot: testId prop 1`] = `
|
|
|
83
83
|
exports[`Button > snapshot: variant prop 1`] = `
|
|
84
84
|
<button
|
|
85
85
|
aria-disabled="false"
|
|
86
|
-
class="ucl-uikit-button css-
|
|
86
|
+
class="ucl-uikit-button css-1wqhdg8"
|
|
87
87
|
data-testid="ucl-uikit-button"
|
|
88
88
|
/>
|
|
89
89
|
`;
|
|
@@ -91,11 +91,11 @@ exports[`Button > snapshot: variant prop 1`] = `
|
|
|
91
91
|
exports[`Button > snapshot: with icon 1`] = `
|
|
92
92
|
<button
|
|
93
93
|
aria-disabled="false"
|
|
94
|
-
class="ucl-uikit-button css-
|
|
94
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
95
95
|
data-testid="ucl-uikit-button"
|
|
96
96
|
>
|
|
97
97
|
<svg
|
|
98
|
-
class="ucl-uikit-icon css-
|
|
98
|
+
class="ucl-uikit-icon css-qo09cr"
|
|
99
99
|
data-testid="ucl-uikit-icon"
|
|
100
100
|
fill="none"
|
|
101
101
|
focusable="false"
|
|
@@ -119,12 +119,12 @@ exports[`Button > snapshot: with icon 1`] = `
|
|
|
119
119
|
exports[`Button > snapshot: with icon and iconPosition right 1`] = `
|
|
120
120
|
<button
|
|
121
121
|
aria-disabled="false"
|
|
122
|
-
class="ucl-uikit-button css-
|
|
122
|
+
class="ucl-uikit-button css-1wtmaoy"
|
|
123
123
|
data-testid="ucl-uikit-button"
|
|
124
124
|
>
|
|
125
125
|
Download
|
|
126
126
|
<svg
|
|
127
|
-
class="ucl-uikit-icon css-
|
|
127
|
+
class="ucl-uikit-icon css-qo09cr"
|
|
128
128
|
data-testid="ucl-uikit-icon"
|
|
129
129
|
fill="none"
|
|
130
130
|
focusable="false"
|
|
@@ -17,6 +17,7 @@ const buttonAccentStyle = (
|
|
|
17
17
|
const bgActiveColour = fill.brandPressed;
|
|
18
18
|
|
|
19
19
|
const baseStyle = css`
|
|
20
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.inverse};
|
|
20
21
|
background-color: ${bgColour};
|
|
21
22
|
color: ${theme.colour.text.inverse};
|
|
22
23
|
`;
|
|
@@ -38,6 +39,7 @@ const buttonAccentStyle = (
|
|
|
38
39
|
`;
|
|
39
40
|
|
|
40
41
|
const disabledStyle = css`
|
|
42
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.disabledOnBgFill};
|
|
41
43
|
background-color: ${theme.colour.fill.disabled};
|
|
42
44
|
color: ${theme.colour.text.onBgFillDisabled};
|
|
43
45
|
`;
|
|
@@ -18,6 +18,7 @@ const buttonPrimaryDestructiveStyle = (
|
|
|
18
18
|
const bgSelectedColour = fill.criticalHover;
|
|
19
19
|
|
|
20
20
|
const baseStyle = css`
|
|
21
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.inverse};
|
|
21
22
|
background-color: ${bgColour};
|
|
22
23
|
color: ${theme.colour.text.inverse};
|
|
23
24
|
`;
|
|
@@ -39,6 +40,7 @@ const buttonPrimaryDestructiveStyle = (
|
|
|
39
40
|
`;
|
|
40
41
|
|
|
41
42
|
const disabledStyle = css`
|
|
43
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.disabledOnBgFill};
|
|
42
44
|
border-color: ${theme.colour.fill.disabled};
|
|
43
45
|
background-color: ${theme.colour.fill.disabled};
|
|
44
46
|
color: ${theme.colour.text.onBgFillDisabled};
|
|
@@ -17,6 +17,7 @@ const buttonPrimaryStyle = (
|
|
|
17
17
|
const bgActiveColour = fill.brandPressed;
|
|
18
18
|
|
|
19
19
|
const baseStyle = css`
|
|
20
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.brandInverse};
|
|
20
21
|
background-color: ${bgColour};
|
|
21
22
|
color: ${theme.colour.text.brandInverse};
|
|
22
23
|
`;
|
|
@@ -38,6 +39,7 @@ const buttonPrimaryStyle = (
|
|
|
38
39
|
`;
|
|
39
40
|
|
|
40
41
|
const disabledStyle = css`
|
|
42
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.disabledOnBgFill};
|
|
41
43
|
background-color: ${theme.colour.fill.disabled};
|
|
42
44
|
color: ${theme.colour.text.onBgFillDisabled};
|
|
43
45
|
`;
|
|
@@ -6,14 +6,12 @@ const buttonPrimarySubtleStyle = (
|
|
|
6
6
|
theme: ThemeType,
|
|
7
7
|
selected: ButtonBaseProps['selected'],
|
|
8
8
|
disabled: ButtonBaseProps['disabled'],
|
|
9
|
-
loading: ButtonBaseProps['loading']
|
|
10
|
-
paddingPx: number
|
|
9
|
+
loading: ButtonBaseProps['loading']
|
|
11
10
|
) => {
|
|
12
11
|
const {
|
|
13
|
-
colour: { border, fill, text },
|
|
12
|
+
colour: { border, fill, icon, text },
|
|
14
13
|
} = theme;
|
|
15
14
|
|
|
16
|
-
const bgColour = fill.inverse;
|
|
17
15
|
const borderColour = border.subtle;
|
|
18
16
|
const bgHoverColour = fill.brandSubtleHover;
|
|
19
17
|
const bgActiveColour = fill.brandSubtleSelected;
|
|
@@ -21,18 +19,18 @@ const buttonPrimarySubtleStyle = (
|
|
|
21
19
|
const selectedBorderColour = border.brand;
|
|
22
20
|
const selectedTextColour = text.brandHover;
|
|
23
21
|
|
|
24
|
-
const adjustedPaddingPx = paddingPx + 1;
|
|
25
|
-
|
|
26
22
|
const baseStyle = css`
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
--ucl-uikit-button-icon-colour: ${icon.default};
|
|
24
|
+
background-color: transparent;
|
|
25
|
+
outline: ${theme.border.b1} solid ${borderColour};
|
|
26
|
+
outline-offset: -${theme.border.b1};
|
|
29
27
|
color: ${theme.colour.text.default};
|
|
30
|
-
padding: 0 ${adjustedPaddingPx}px;
|
|
31
28
|
`;
|
|
32
29
|
|
|
33
30
|
const selectedStyle = css`
|
|
31
|
+
--ucl-uikit-button-icon-colour: ${icon.brandSelectedOnBgFill};
|
|
34
32
|
background-color: ${selectedFillColour};
|
|
35
|
-
|
|
33
|
+
outline-color: ${selectedBorderColour};
|
|
36
34
|
color: ${selectedTextColour};
|
|
37
35
|
`;
|
|
38
36
|
|
|
@@ -49,7 +47,8 @@ const buttonPrimarySubtleStyle = (
|
|
|
49
47
|
`;
|
|
50
48
|
|
|
51
49
|
const disabledStyle = css`
|
|
52
|
-
|
|
50
|
+
--ucl-uikit-button-icon-colour: ${icon.disabled};
|
|
51
|
+
outline-color: ${border.disabled};
|
|
53
52
|
color: ${text.disabled};
|
|
54
53
|
`;
|
|
55
54
|
|
|
@@ -19,6 +19,7 @@ const buttonPrimaryWarningStyle = (
|
|
|
19
19
|
const selectedBgColour = fill.cautionSelected;
|
|
20
20
|
|
|
21
21
|
const baseStyle = css`
|
|
22
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.caution};
|
|
22
23
|
background-color: ${bgColour};
|
|
23
24
|
color: ${textColour};
|
|
24
25
|
`;
|
|
@@ -40,6 +41,7 @@ const buttonPrimaryWarningStyle = (
|
|
|
40
41
|
`;
|
|
41
42
|
|
|
42
43
|
const disabledStyle = css`
|
|
44
|
+
--ucl-uikit-button-icon-colour: ${theme.colour.icon.disabledOnBgFill};
|
|
43
45
|
border-color: ${theme.colour.fill.disabled};
|
|
44
46
|
background-color: ${theme.colour.fill.disabled};
|
|
45
47
|
color: ${theme.colour.text.onBgFillDisabled};
|