uikit-react-public 0.50.0 → 0.50.2

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.
Files changed (37) hide show
  1. package/dist/components/Alert/Alert.d.ts +4 -2
  2. package/dist/components/Alert/Alert.stories.d.ts +10 -1
  3. package/dist/components/Button/Button.d.ts +14 -4
  4. package/dist/components/Button/Button.stories.d.ts +29 -2
  5. package/dist/components/Button/style/buttonPrimarySubtleStyle.d.ts +1 -1
  6. package/dist/components/Button/style/buttonPrimarySuccessStyle.d.ts +4 -0
  7. package/dist/components/Button/style/buttonSecondaryStyle.d.ts +1 -1
  8. package/dist/components/Button/style/buttonSecondarySubtleStyle.d.ts +1 -1
  9. package/dist/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.d.ts +4 -0
  10. package/dist/components/Button/style/buttonTertiaryDestructiveStyle.d.ts +1 -1
  11. package/dist/components/Button/style/buttonTertiaryNoPaddingStyle.d.ts +1 -1
  12. package/dist/components/Button/style/buttonTertiaryStyle.d.ts +1 -1
  13. package/dist/index.js +4485 -4373
  14. package/lib/components/Alert/Alert.mdx +13 -1
  15. package/lib/components/Alert/Alert.stories.tsx +29 -0
  16. package/lib/components/Alert/Alert.tsx +32 -1
  17. package/lib/components/Alert/__tests__/Alert.test.tsx +78 -24
  18. package/lib/components/Button/Button.mdx +57 -9
  19. package/lib/components/Button/Button.stories.tsx +72 -0
  20. package/lib/components/Button/Button.tsx +68 -26
  21. package/lib/components/Button/__tests__/Button.test.tsx +159 -1
  22. package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +11 -11
  23. package/lib/components/Button/style/buttonAccentStyle.ts +2 -0
  24. package/lib/components/Button/style/buttonPrimaryDestructiveStyle.ts +2 -0
  25. package/lib/components/Button/style/buttonPrimaryStyle.ts +2 -0
  26. package/lib/components/Button/style/buttonPrimarySubtleStyle.ts +10 -11
  27. package/lib/components/Button/style/buttonPrimarySuccessStyle.ts +39 -0
  28. package/lib/components/Button/style/buttonPrimaryWarningStyle.ts +2 -0
  29. package/lib/components/Button/style/buttonSecondaryDestructiveStyle.ts +13 -7
  30. package/lib/components/Button/style/buttonSecondaryStyle.ts +49 -16
  31. package/lib/components/Button/style/buttonSecondarySubtleStyle.ts +15 -13
  32. package/lib/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.ts +34 -0
  33. package/lib/components/Button/style/buttonTertiaryDestructiveStyle.ts +9 -8
  34. package/lib/components/Button/style/buttonTertiaryNoPaddingStyle.ts +13 -15
  35. package/lib/components/Button/style/buttonTertiaryStyle.ts +10 -9
  36. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +1 -1
  37. package/package.json +1 -1
@@ -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,7 +20,9 @@ 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';
25
+ import buttonPrimarySuccessStyle from './style/buttonPrimarySuccessStyle';
23
26
  import buttonPrimarySubtleStyle from './style/buttonPrimarySubtleStyle';
24
27
  import buttonSecondarySubtleStyle from './style/buttonSecondarySubtleStyle';
25
28
  import buttonTertiaryNoPaddingStyle from './style/buttonTertiaryNoPaddingStyle';
@@ -39,12 +42,15 @@ export type ButtonVariant =
39
42
  | 'primary-destructive'
40
43
  | 'secondary-destructive'
41
44
  | 'tertiary-destructive'
42
- | 'primary-warning';
45
+ | 'tertiary-destructive-no-padding'
46
+ | 'primary-warning'
47
+ | 'primary-success';
43
48
 
44
49
  const DESTRUCTIVE_VARIANT_MAP: Partial<Record<ButtonVariant, ButtonVariant>> = {
45
50
  primary: 'primary-destructive',
46
51
  secondary: 'secondary-destructive',
47
52
  tertiary: 'tertiary-destructive',
53
+ 'tertiary-no-padding': 'tertiary-destructive-no-padding',
48
54
  };
49
55
 
50
56
  // Legacy size values from the old Button API
@@ -52,13 +58,17 @@ type LegacySize = 'default';
52
58
 
53
59
  export interface ButtonBaseProps {
54
60
  variant?: ButtonVariant;
55
- /** @deprecated Use variant="primary-destructive" / "secondary-destructive" instead */
61
+ /** @deprecated Use a destructive variant directly */
56
62
  destructive?: boolean;
57
63
  size?: 'xsmall' | 'small' | 'medium' | 'large' | LegacySize;
64
+ /** Whether the button is rendered on a light background */
65
+ onLight?: boolean;
58
66
  selected?: boolean;
59
67
  disabled?: boolean;
60
- icon?: ReactElement;
68
+ icon?: ReactElement<{ className?: string }>;
61
69
  iconPosition?: 'left' | 'right';
70
+ leftIcon?: ReactElement<{ className?: string }>;
71
+ rightIcon?: ReactElement<{ className?: string }>;
62
72
  tooltip?: string;
63
73
  loading?: boolean;
64
74
  fullWidth?: boolean;
@@ -92,7 +102,7 @@ const normalizeVariantProp = (
92
102
 
93
103
  if (!destructiveVariant) {
94
104
  console.warn(
95
- `Button variant '${variant}' does not support the destructive prop. Use a destructive variant explicitly, or use one of: primary, secondary, tertiary.`
105
+ `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
106
  );
97
107
  return variant;
98
108
  }
@@ -102,13 +112,16 @@ const normalizeVariantProp = (
102
112
 
103
113
  const Button = <C extends ElementType = 'button'>({
104
114
  as,
105
- variant = 'accent',
115
+ variant,
106
116
  destructive = false,
107
117
  size = 'medium',
118
+ onLight = true,
108
119
  selected = false,
109
120
  disabled = false,
110
121
  icon,
111
122
  iconPosition = 'left',
123
+ leftIcon,
124
+ rightIcon,
112
125
  tooltip,
113
126
  loading = false,
114
127
  fullWidth = false,
@@ -125,7 +138,10 @@ const Button = <C extends ElementType = 'button'>({
125
138
  const [isHovered, setIsHovered] = useState(false);
126
139
  const [theme] = useTheme();
127
140
 
128
- const resolvedVariant = normalizeVariantProp(variant, destructive);
141
+ const resolvedVariant = normalizeVariantProp(
142
+ variant ?? (destructive ? 'primary' : 'accent'),
143
+ destructive
144
+ );
129
145
  const resolvedSize = normalizeSizeprop(size);
130
146
  const buttonTypography = {
131
147
  xsmall: theme.typography.body.smMedium,
@@ -136,7 +152,7 @@ const Button = <C extends ElementType = 'button'>({
136
152
 
137
153
  const baseStyle = css`
138
154
  all: unset;
139
- border: 2px solid transparent;
155
+ border: 0;
140
156
  display: inline-flex;
141
157
  align-items: center;
142
158
  justify-content: center;
@@ -160,14 +176,33 @@ const Button = <C extends ElementType = 'button'>({
160
176
  }
161
177
  `;
162
178
 
163
- const iconSize = resolvedSize === 'xsmall' ? 20 : 24;
179
+ const contentIconSize = {
180
+ xsmall: 16,
181
+ small: 20,
182
+ medium: 24,
183
+ large: 24,
184
+ }[resolvedSize];
185
+ const iconOnlySize = resolvedSize === 'xsmall' ? 20 : 24;
186
+ const spinnerSize = resolvedSize === 'xsmall' ? 20 : 24;
164
187
  const paddingPx = resolvedSize === 'xsmall' ? 8 : 16;
165
188
 
166
- const iconOnlyStyle = css`
167
- width: 48px;
168
- padding: 0;
169
- justify-content: center;
189
+ const iconStyle = css`
190
+ color: var(--ucl-uikit-button-icon-colour, currentColor);
191
+ width: ${children ? contentIconSize : iconOnlySize}px;
192
+ height: ${children ? contentIconSize : iconOnlySize}px;
170
193
  `;
194
+ const styleIcon = (iconElement?: ReactElement<{ className?: string }>) =>
195
+ iconElement
196
+ ? cloneElement(iconElement, {
197
+ className: cx(iconElement.props.className, iconStyle),
198
+ })
199
+ : undefined;
200
+ const styledLeftIcon = styleIcon(
201
+ leftIcon ?? (iconPosition === 'left' ? icon : undefined)
202
+ );
203
+ const styledRightIcon = styleIcon(
204
+ rightIcon ?? (iconPosition === 'right' ? icon : undefined)
205
+ );
171
206
 
172
207
  const sizeExtraSmallStyle = css`
173
208
  height: 32px;
@@ -196,33 +231,31 @@ const Button = <C extends ElementType = 'button'>({
196
231
  const variantStyle = {
197
232
  accent: buttonAccentStyle(theme, selected, disabled, loading),
198
233
  primary: buttonPrimaryStyle(theme, selected, disabled, loading),
199
- secondary: buttonSecondaryStyle(theme, selected, disabled, loading),
200
- tertiary: buttonTertiaryStyle(
234
+ secondary: buttonSecondaryStyle(
201
235
  theme,
202
236
  selected,
203
237
  disabled,
204
238
  loading,
205
- paddingPx
239
+ onLight
206
240
  ),
241
+ tertiary: buttonTertiaryStyle(theme, selected, disabled, loading),
207
242
  'primary-subtle': buttonPrimarySubtleStyle(
208
243
  theme,
209
244
  selected,
210
245
  disabled,
211
- loading,
212
- paddingPx
246
+ loading
213
247
  ),
214
248
  'secondary-subtle': buttonSecondarySubtleStyle(
215
249
  theme,
216
250
  selected,
217
251
  disabled,
218
- loading,
219
- paddingPx
252
+ loading
220
253
  ),
221
254
  'tertiary-no-padding': buttonTertiaryNoPaddingStyle(
222
255
  theme,
223
256
  disabled,
224
257
  loading,
225
- paddingPx
258
+ onLight
226
259
  ),
227
260
  'primary-destructive': buttonPrimaryDestructiveStyle(
228
261
  theme,
@@ -240,8 +273,12 @@ const Button = <C extends ElementType = 'button'>({
240
273
  theme,
241
274
  selected,
242
275
  disabled,
243
- loading,
244
- paddingPx
276
+ loading
277
+ ),
278
+ 'tertiary-destructive-no-padding': buttonTertiaryDestructiveNoPaddingStyle(
279
+ theme,
280
+ disabled,
281
+ loading
245
282
  ),
246
283
  'primary-warning': buttonPrimaryWarningStyle(
247
284
  theme,
@@ -249,6 +286,12 @@ const Button = <C extends ElementType = 'button'>({
249
286
  disabled,
250
287
  loading
251
288
  ),
289
+ 'primary-success': buttonPrimarySuccessStyle(
290
+ theme,
291
+ selected,
292
+ disabled,
293
+ loading
294
+ ),
252
295
  }[resolvedVariant];
253
296
 
254
297
  const commonDisabledStyle = css`
@@ -271,7 +314,6 @@ const Button = <C extends ElementType = 'button'>({
271
314
  variantStyle,
272
315
  disabled && commonDisabledStyle,
273
316
  loading && loadingStyle,
274
- !children && iconOnlyStyle,
275
317
  className
276
318
  );
277
319
 
@@ -294,15 +336,15 @@ const Button = <C extends ElementType = 'button'>({
294
336
  >
295
337
  {loading ? (
296
338
  <Spinner
297
- size={iconSize}
339
+ size={spinnerSize}
298
340
  strokeWidth={8}
299
341
  inheritColour
300
342
  />
301
343
  ) : (
302
344
  <>
303
- {icon && iconPosition === 'left' && icon}
345
+ {styledLeftIcon}
304
346
  {children}
305
- {icon && iconPosition === 'right' && icon}
347
+ {styledRightIcon}
306
348
  </>
307
349
  )}
308
350
  </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('#', '');
@@ -79,6 +79,25 @@ describe('Button', () => {
79
79
  expect(renderResult.container.firstChild).toMatchSnapshot();
80
80
  });
81
81
 
82
+ test('renders icons on both sides of the label', () => {
83
+ render(
84
+ <ThemeContextProvider>
85
+ <Button
86
+ leftIcon={<Icon.ChevronRight />}
87
+ rightIcon={<Icon.ChevronRight />}
88
+ size='xsmall'
89
+ >
90
+ Action
91
+ </Button>
92
+ </ThemeContextProvider>
93
+ );
94
+
95
+ const icons = screen.getAllByTestId('ucl-uikit-icon');
96
+ expect(icons).toHaveLength(2);
97
+ expect(icons[0]).toHaveStyle({ width: '16px', height: '16px' });
98
+ expect(icons[1]).toHaveStyle({ width: '16px', height: '16px' });
99
+ });
100
+
82
101
  test('snapshot: loading', () => {
83
102
  const renderResult = render(
84
103
  <ThemeContextProvider>
@@ -255,6 +274,26 @@ describe('Button', () => {
255
274
  );
256
275
 
257
276
  expect(renderResult.container.firstChild).toMatchSnapshot();
277
+ expect(getComputedStyle(screen.getByRole('button')).backgroundColor).toBe(
278
+ hexToRgb(theme.colour.fill.critical)
279
+ );
280
+ });
281
+
282
+ test('maps legacy destructive prop for the no-padding variant', () => {
283
+ render(
284
+ <ThemeContextProvider>
285
+ <Button
286
+ variant='tertiary-no-padding'
287
+ destructive
288
+ >
289
+ Delete
290
+ </Button>
291
+ </ThemeContextProvider>
292
+ );
293
+
294
+ expect(getComputedStyle(screen.getByRole('button')).color).toBe(
295
+ hexToRgb(theme.colour.text.critical)
296
+ );
258
297
  });
259
298
 
260
299
  test('warns when destructive prop is used with unsupported variant', () => {
@@ -289,6 +328,7 @@ describe('Button', () => {
289
328
  ['accent', darkTheme.colour.text.inverse],
290
329
  ['primary-destructive', darkTheme.colour.text.inverse],
291
330
  ['primary-warning', darkTheme.colour.text.caution],
331
+ ['primary-success', darkTheme.colour.text.inverse],
292
332
  ] as const)(
293
333
  'uses readable semantic text colour for dark %s variant',
294
334
  (variant, expectedColour) => {
@@ -320,4 +360,122 @@ describe('Button', () => {
320
360
  `box-shadow:${expectedFocusShadow.replace(/\s/g, '')}`
321
361
  );
322
362
  });
363
+
364
+ test('uses the inverse icon colour for the success variant', () => {
365
+ render(
366
+ <ThemeContextProvider>
367
+ <Button
368
+ variant='primary-success'
369
+ icon={<Icon.ChevronRight />}
370
+ >
371
+ Success
372
+ </Button>
373
+ </ThemeContextProvider>
374
+ );
375
+
376
+ expect(
377
+ getComputedStyle(screen.getByRole('button'))
378
+ .getPropertyValue('--ucl-uikit-button-icon-colour')
379
+ .trim()
380
+ ).toBe(theme.colour.icon.inverse);
381
+ });
382
+
383
+ test.each([
384
+ ['xsmall', '32px', '16px'],
385
+ ['small', '40px', '20px'],
386
+ ['medium', '48px', '24px'],
387
+ ['large', '56px', '24px'],
388
+ ] as const)(
389
+ 'matches the Figma dimensions for the %s size',
390
+ (size, expectedHeight, expectedIconSize) => {
391
+ render(
392
+ <ThemeContextProvider>
393
+ <Button
394
+ icon={<Icon.ChevronRight />}
395
+ size={size}
396
+ >
397
+ Action
398
+ </Button>
399
+ </ThemeContextProvider>
400
+ );
401
+
402
+ expect(getComputedStyle(screen.getByRole('button')).height).toBe(
403
+ expectedHeight
404
+ );
405
+ expect(getComputedStyle(screen.getByTestId('ucl-uikit-icon')).width).toBe(
406
+ expectedIconSize
407
+ );
408
+ }
409
+ );
410
+
411
+ test('uses the larger extra-small icon when the button is icon-only', () => {
412
+ render(
413
+ <ThemeContextProvider>
414
+ <Button
415
+ aria-label='Next'
416
+ icon={<Icon.ChevronRight />}
417
+ size='xsmall'
418
+ />
419
+ </ThemeContextProvider>
420
+ );
421
+
422
+ expect(getComputedStyle(screen.getByTestId('ucl-uikit-icon')).width).toBe(
423
+ '20px'
424
+ );
425
+ });
426
+
427
+ test('styles a non-SVG icon through its className contract', () => {
428
+ render(
429
+ <ThemeContextProvider>
430
+ <Button
431
+ icon={
432
+ <span
433
+ className='custom-icon'
434
+ data-testid='custom-icon'
435
+ />
436
+ }
437
+ size='xsmall'
438
+ >
439
+ Action
440
+ </Button>
441
+ </ThemeContextProvider>
442
+ );
443
+
444
+ const icon = screen.getByTestId('custom-icon');
445
+ expect(icon).toHaveClass('custom-icon');
446
+ expect(getComputedStyle(icon).width).toBe('16px');
447
+ expect(getComputedStyle(icon).height).toBe('16px');
448
+ });
449
+
450
+ test.each([
451
+ 'tertiary-no-padding',
452
+ 'tertiary-destructive-no-padding',
453
+ ] as const)('removes padding from the %s variant', (variant) => {
454
+ render(
455
+ <ThemeContextProvider>
456
+ <Button variant={variant}>Action</Button>
457
+ </ThemeContextProvider>
458
+ );
459
+
460
+ expect(getComputedStyle(screen.getByRole('button')).padding).toBe('0px');
461
+ });
462
+
463
+ test('uses inverse secondary tokens on a dark background', () => {
464
+ render(
465
+ <ThemeContextProvider>
466
+ <Button
467
+ onLight={false}
468
+ variant='secondary'
469
+ >
470
+ Action
471
+ </Button>
472
+ </ThemeContextProvider>
473
+ );
474
+
475
+ const style = getComputedStyle(screen.getByRole('button'));
476
+ expect(style.color).toBe(hexToRgb(theme.colour.text.brandInverse));
477
+ expect(document.head.textContent?.replace(/\s/g, '')).toContain(
478
+ `outline:${theme.border.b2}solid${theme.colour.border.brandInverse}`
479
+ );
480
+ });
323
481
  });
@@ -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-ijdex1"
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-ijdex1"
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-ijdex1"
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-1ram5ew"
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-1v2bqw7"
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-1v2bqw7"
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-25bhrl"
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-ijdex1"
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-f962ig"
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-ijdex1"
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-f962ig"
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
- background-color: ${bgColour};
28
- border: 1px solid ${borderColour};
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
- border-color: ${selectedBorderColour};
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
- border-color: ${border.disabled};
50
+ --ucl-uikit-button-icon-colour: ${icon.disabled};
51
+ outline-color: ${border.disabled};
53
52
  color: ${text.disabled};
54
53
  `;
55
54
 
@@ -0,0 +1,39 @@
1
+ import { css, cx } from '@emotion/css';
2
+ import { ThemeType } from '../../../theme';
3
+ import { ButtonBaseProps } from '../Button';
4
+
5
+ const buttonPrimarySuccessStyle = (
6
+ theme: ThemeType,
7
+ selected: ButtonBaseProps['selected'],
8
+ disabled: ButtonBaseProps['disabled'],
9
+ loading: ButtonBaseProps['loading']
10
+ ) => {
11
+ const baseStyle = css`
12
+ --ucl-uikit-button-icon-colour: ${theme.colour.icon.inverse};
13
+ background-color: ${theme.colour.fill.success};
14
+ color: ${theme.colour.text.inverse};
15
+ `;
16
+
17
+ const interactiveStyle = css`
18
+ cursor: pointer;
19
+ `;
20
+
21
+ const selectedStyle = css`
22
+ background-color: ${theme.colour.fill.success};
23
+ `;
24
+
25
+ const disabledStyle = css`
26
+ --ucl-uikit-button-icon-colour: ${theme.colour.icon.disabledOnBgFill};
27
+ background-color: ${theme.colour.fill.disabled};
28
+ color: ${theme.colour.text.onBgFillDisabled};
29
+ `;
30
+
31
+ return cx(
32
+ baseStyle,
33
+ selected && selectedStyle,
34
+ !disabled && !loading && interactiveStyle,
35
+ disabled && disabledStyle
36
+ );
37
+ };
38
+
39
+ export default buttonPrimarySuccessStyle;
@@ -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};