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.
Files changed (29) hide show
  1. package/dist/components/Button/Button.d.ts +8 -4
  2. package/dist/components/Button/Button.stories.d.ts +11 -2
  3. package/dist/components/Button/style/buttonPrimarySubtleStyle.d.ts +1 -1
  4. package/dist/components/Button/style/buttonSecondaryStyle.d.ts +1 -1
  5. package/dist/components/Button/style/buttonSecondarySubtleStyle.d.ts +1 -1
  6. package/dist/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.d.ts +4 -0
  7. package/dist/components/Button/style/buttonTertiaryDestructiveStyle.d.ts +1 -1
  8. package/dist/components/Button/style/buttonTertiaryNoPaddingStyle.d.ts +1 -1
  9. package/dist/components/Button/style/buttonTertiaryStyle.d.ts +1 -1
  10. package/dist/index.js +4695 -4630
  11. package/lib/components/Button/Button.mdx +12 -0
  12. package/lib/components/Button/Button.stories.tsx +46 -0
  13. package/lib/components/Button/Button.tsx +48 -25
  14. package/lib/components/Button/__tests__/Button.test.tsx +120 -1
  15. package/lib/components/Button/__tests__/__snapshots__/Button.test.tsx.snap +11 -11
  16. package/lib/components/Button/style/buttonAccentStyle.ts +2 -0
  17. package/lib/components/Button/style/buttonPrimaryDestructiveStyle.ts +2 -0
  18. package/lib/components/Button/style/buttonPrimaryStyle.ts +2 -0
  19. package/lib/components/Button/style/buttonPrimarySubtleStyle.ts +10 -11
  20. package/lib/components/Button/style/buttonPrimaryWarningStyle.ts +2 -0
  21. package/lib/components/Button/style/buttonSecondaryDestructiveStyle.ts +13 -7
  22. package/lib/components/Button/style/buttonSecondaryStyle.ts +49 -16
  23. package/lib/components/Button/style/buttonSecondarySubtleStyle.ts +15 -13
  24. package/lib/components/Button/style/buttonTertiaryDestructiveNoPaddingStyle.ts +34 -0
  25. package/lib/components/Button/style/buttonTertiaryDestructiveStyle.ts +9 -8
  26. package/lib/components/Button/style/buttonTertiaryNoPaddingStyle.ts +13 -15
  27. package/lib/components/Button/style/buttonTertiaryStyle.ts +10 -9
  28. package/lib/components/Table/subcomponents/Cell/__tests__/__snapshots__/Cell.test.tsx.snap +1 -1
  29. 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&#39;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 variant="primary-destructive" / "secondary-destructive" instead */
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 = 'accent',
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(variant, destructive);
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: 2px solid transparent;
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 iconSize = resolvedSize === 'xsmall' ? 20 : 24;
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 iconOnlyStyle = css`
167
- width: 48px;
168
- padding: 0;
169
- justify-content: center;
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(theme, selected, disabled, loading),
200
- tertiary: buttonTertiaryStyle(
221
+ secondary: buttonSecondaryStyle(
201
222
  theme,
202
223
  selected,
203
224
  disabled,
204
225
  loading,
205
- paddingPx
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
- paddingPx
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
- paddingPx
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={iconSize}
320
+ size={spinnerSize}
298
321
  strokeWidth={8}
299
322
  inheritColour
300
323
  />
301
324
  ) : (
302
325
  <>
303
- {icon && iconPosition === 'left' && icon}
326
+ {styledIcon && iconPosition === 'left' && styledIcon}
304
327
  {children}
305
- {icon && iconPosition === 'right' && icon}
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-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
 
@@ -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};