uikit-react-public 0.50.1 → 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.
@@ -1,5 +1,11 @@
1
1
  import * as AlertStories from './Alert.stories';
2
- import { Meta, Title, Subtitle, Canvas, Controls } from '@storybook/addon-docs/blocks';
2
+ import {
3
+ Meta,
4
+ Title,
5
+ Subtitle,
6
+ Canvas,
7
+ Controls,
8
+ } from '@storybook/addon-docs/blocks';
3
9
 
4
10
  <Meta of={AlertStories} />
5
11
  <Title />
@@ -14,6 +20,12 @@ The `<Alert>` component is used to convey contextual messages with visual hierar
14
20
 
15
21
  Use the component with `Alert.Title` and `Alert.Message` as children to maintain semantic separation of content.
16
22
 
23
+ ## Action button
24
+
25
+ Pass a `Button` to `actionButton` to add an action. Alert sets the button to the extra-small size and applies the colour associated with the alert type.
26
+
27
+ <Canvas of={AlertStories.WithActionButton} />
28
+
17
29
  ## Variants
18
30
 
19
31
  ### Info
@@ -1,5 +1,7 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react-vite';
2
2
  import Alert from './Alert';
3
+ import Button from '../Button';
4
+ import Icon from '../Icon';
3
5
  import { theme } from '../../theme';
4
6
 
5
7
  const marginKeys = Object.keys(theme.margin) as Array<
@@ -35,6 +37,10 @@ const meta = {
35
37
  className: { control: { type: 'text' } },
36
38
  testId: { control: { type: 'text' } },
37
39
  children: { control: false },
40
+ actionButton: {
41
+ control: false,
42
+ table: { type: { summary: 'ReactElement<ButtonProps>' } },
43
+ },
38
44
  m: commonMarginPropsInfo,
39
45
  mv: commonMarginPropsInfo,
40
46
  mh: commonMarginPropsInfo,
@@ -98,6 +104,29 @@ export const Error: Story = {
98
104
  },
99
105
  };
100
106
 
107
+ export const WithActionButton: Story = {
108
+ name: 'With action button',
109
+ render: (args) => (
110
+ <Alert
111
+ {...args}
112
+ actionButton={
113
+ <Button
114
+ leftIcon={<Icon.ChevronRight />}
115
+ rightIcon={<Icon.ChevronRight />}
116
+ >
117
+ Action
118
+ </Button>
119
+ }
120
+ >
121
+ <Alert.Title>Title of {args.type} alert</Alert.Title>
122
+ <Alert.Message>This is a {args.type} alert message.</Alert.Message>
123
+ </Alert>
124
+ ),
125
+ args: {
126
+ type: 'info',
127
+ },
128
+ };
129
+
101
130
  export const CommonMargins: Story = {
102
131
  render: Template,
103
132
  name: 'With common margins',
@@ -1,6 +1,13 @@
1
- import { createContext, useContext, HTMLAttributes } from 'react';
1
+ import {
2
+ cloneElement,
3
+ createContext,
4
+ useContext,
5
+ HTMLAttributes,
6
+ ReactElement,
7
+ } from 'react';
2
8
  import { css, cx } from '@emotion/css';
3
9
  import Icon, { IconProps } from '../Icon';
10
+ import type { ButtonProps, ButtonVariant } from '../Button/Button';
4
11
  import AlertMessage from './AlertMessage';
5
12
  import AlertTitle from './AlertTitle';
6
13
  import marginsStyle, { MarginProps } from '../common/marginsStyle';
@@ -29,6 +36,7 @@ export interface AlertBaseProps extends HTMLAttributes<HTMLDivElement> {
29
36
  type: AlertType;
30
37
  iconProps?: Omit<IconProps, 'svg'>;
31
38
  contentProps?: HTMLAttributes<HTMLDivElement>;
39
+ actionButton?: ReactElement<ButtonProps>;
32
40
  testId?: string;
33
41
  }
34
42
 
@@ -38,6 +46,7 @@ const Alert = ({
38
46
  type,
39
47
  iconProps,
40
48
  contentProps,
49
+ actionButton,
41
50
  children,
42
51
  testId = NAME,
43
52
  className,
@@ -114,6 +123,12 @@ const Alert = ({
114
123
  overflow-wrap: anywhere;
115
124
  `;
116
125
 
126
+ const actionButtonStyle = css`
127
+ align-self: center;
128
+ flex-shrink: 0;
129
+ margin-left: auto;
130
+ `;
131
+
117
132
  const IconComp = {
118
133
  info: Icon.Info,
119
134
  success: Icon.CheckCircle,
@@ -121,6 +136,21 @@ const Alert = ({
121
136
  error: Icon.XCircle,
122
137
  }[type];
123
138
 
139
+ const actionButtonVariant: Record<AlertType, ButtonVariant> = {
140
+ info: 'accent',
141
+ success: 'primary-success',
142
+ warning: 'primary-warning',
143
+ error: 'primary-destructive',
144
+ };
145
+
146
+ const renderedActionButton = actionButton
147
+ ? cloneElement(actionButton, {
148
+ variant: actionButtonVariant[type],
149
+ size: 'xsmall',
150
+ className: cx(actionButtonStyle, actionButton.props.className),
151
+ })
152
+ : null;
153
+
124
154
  return (
125
155
  <AlertContext.Provider value={{ type }}>
126
156
  <div
@@ -140,6 +170,7 @@ const Alert = ({
140
170
  >
141
171
  {children}
142
172
  </div>
173
+ {renderedActionButton}
143
174
  </div>
144
175
  </AlertContext.Provider>
145
176
  );
@@ -1,7 +1,19 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { render } from '@testing-library/react';
3
- import { ThemeContextProvider } from '../../../theme/useTheme';
1
+ import { describe, expect, test, vitest } from 'vitest';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { theme, ThemeContextProvider } from '../../../theme';
4
5
  import Alert from '../Alert';
6
+ import Button from '../../Button';
7
+ import Icon from '../../Icon';
8
+
9
+ const hexToRgb = (hex: string) => {
10
+ const value = hex.replace('#', '');
11
+ const red = parseInt(value.slice(0, 2), 16);
12
+ const green = parseInt(value.slice(2, 4), 16);
13
+ const blue = parseInt(value.slice(4, 6), 16);
14
+
15
+ return `rgb(${red}, ${green}, ${blue})`;
16
+ };
5
17
 
6
18
  describe('Alert', () => {
7
19
  // Snapshot tests
@@ -10,15 +22,11 @@ describe('Alert', () => {
10
22
  const renderResult = render(
11
23
  <ThemeContextProvider>
12
24
  <Alert type='info'>
13
- <Alert.Message>
14
- This is an informational alert.
15
- </Alert.Message>
25
+ <Alert.Message>This is an informational alert.</Alert.Message>
16
26
  </Alert>
17
27
  </ThemeContextProvider>
18
28
  );
19
- expect(
20
- renderResult.container.firstChild
21
- ).toMatchSnapshot();
29
+ expect(renderResult.container.firstChild).toMatchSnapshot();
22
30
  });
23
31
 
24
32
  test('snapshot: type=success', () => {
@@ -26,15 +34,11 @@ describe('Alert', () => {
26
34
  <ThemeContextProvider>
27
35
  <Alert type='success'>
28
36
  <Alert.Title>Success</Alert.Title>
29
- <Alert.Message>
30
- Your operation completed successfully.
31
- </Alert.Message>
37
+ <Alert.Message>Your operation completed successfully.</Alert.Message>
32
38
  </Alert>
33
39
  </ThemeContextProvider>
34
40
  );
35
- expect(
36
- renderResult.container.firstChild
37
- ).toMatchSnapshot();
41
+ expect(renderResult.container.firstChild).toMatchSnapshot();
38
42
  });
39
43
 
40
44
  test('snapshot: type=warning', () => {
@@ -48,9 +52,7 @@ describe('Alert', () => {
48
52
  </Alert>
49
53
  </ThemeContextProvider>
50
54
  );
51
- expect(
52
- renderResult.container.firstChild
53
- ).toMatchSnapshot();
55
+ expect(renderResult.container.firstChild).toMatchSnapshot();
54
56
  });
55
57
 
56
58
  test('snapshot: type=error', () => {
@@ -58,14 +60,66 @@ describe('Alert', () => {
58
60
  <ThemeContextProvider>
59
61
  <Alert type='error'>
60
62
  <Alert.Title>Error Alert</Alert.Title>
61
- <Alert.Message>
62
- The operation failed.
63
- </Alert.Message>
63
+ <Alert.Message>The operation failed.</Alert.Message>
64
+ </Alert>
65
+ </ThemeContextProvider>
66
+ );
67
+ expect(renderResult.container.firstChild).toMatchSnapshot();
68
+ });
69
+
70
+ test.each([
71
+ ['info', theme.colour.fill.brand],
72
+ ['success', theme.colour.fill.success],
73
+ ['warning', theme.colour.fill.caution],
74
+ ['error', theme.colour.fill.critical],
75
+ ] as const)(
76
+ 'uses the semantic %s colour for its action button',
77
+ (type, expectedColour) => {
78
+ render(
79
+ <ThemeContextProvider>
80
+ <Alert
81
+ type={type}
82
+ actionButton={<Button>Action</Button>}
83
+ >
84
+ <Alert.Message>Alert message</Alert.Message>
85
+ </Alert>
86
+ </ThemeContextProvider>
87
+ );
88
+
89
+ const actionButton = screen.getByRole('button');
90
+ expect(actionButton).toHaveStyle({
91
+ height: '32px',
92
+ backgroundColor: hexToRgb(expectedColour),
93
+ });
94
+ }
95
+ );
96
+
97
+ test('supports an interactive action button with two icons', async () => {
98
+ const user = userEvent.setup();
99
+ const onClick = vitest.fn();
100
+
101
+ render(
102
+ <ThemeContextProvider>
103
+ <Alert
104
+ type='info'
105
+ actionButton={
106
+ <Button
107
+ leftIcon={<Icon.ChevronRight />}
108
+ rightIcon={<Icon.ChevronRight />}
109
+ onClick={onClick}
110
+ >
111
+ Action
112
+ </Button>
113
+ }
114
+ >
115
+ <Alert.Title>Information</Alert.Title>
116
+ <Alert.Message>Alert message</Alert.Message>
64
117
  </Alert>
65
118
  </ThemeContextProvider>
66
119
  );
67
- expect(
68
- renderResult.container.firstChild
69
- ).toMatchSnapshot();
120
+
121
+ expect(screen.getAllByTestId('ucl-uikit-icon')).toHaveLength(3);
122
+ await user.click(screen.getByRole('button', { name: 'Action' }));
123
+ expect(onClick).toHaveBeenCalledOnce();
70
124
  });
71
125
  });
@@ -13,9 +13,11 @@ 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
+ success: `<Button variant='primary-success'>Success Button</Button>`,
16
17
  destructiveNoPadding: `<Button variant='tertiary-destructive-no-padding'>Destructive Action</Button>`,
17
18
  onDark: `<Button variant='secondary' onLight={false}>Secondary Button</Button>`,
18
19
  withIcon: `<Button icon={<Icon.AlertTriangle />}>Button</Button>`,
20
+ withTwoIcons: `<Button leftIcon={<Icon.ChevronRight />} rightIcon={<Icon.ChevronRight />}>Action</Button>`,
19
21
  loading: `<Button loading>Loading Button</Button>`,
20
22
  link: `<Button as='a' href='https://www.ucl.ac.uk' target='_blank'>Go to UCL&#39;s website</Button>`,
21
23
  fullWidth: `<Button fullWidth>Full Width Button</Button>`,
@@ -24,25 +26,40 @@ export const usage = {
24
26
  <Meta of={ButtonStories} />
25
27
  <Title />
26
28
  <Subtitle>
27
- A polymorphic button component with modern variants and backwards-compatible legacy props
29
+ A polymorphic button component with modern variants and backwards-compatible
30
+ legacy props
28
31
  </Subtitle>
29
32
 
30
33
  <Description>
31
- `Button` supports the richer variant set and still supports legacy props such as `destructive` and `size='default'` for compatibility.
34
+ `Button` supports the richer variant set and still supports legacy props such
35
+ as `destructive` and `size='default'` for compatibility.
32
36
  </Description>
33
37
 
34
- <Canvas of={ButtonStories.Default} source={{ code: usage.default }} />
38
+ <Canvas
39
+ of={ButtonStories.Default}
40
+ source={{ code: usage.default }}
41
+ />
35
42
 
36
43
  ## Variants
37
44
 
38
45
  Use `variant` to control hierarchy and emphasis.
39
46
 
40
47
  <Canvas of={ButtonStories.Primary} />
41
- <Canvas of={ButtonStories.Secondary} source={{ code: usage.secondary }} />
48
+ <Canvas
49
+ of={ButtonStories.Secondary}
50
+ source={{ code: usage.secondary }}
51
+ />
42
52
  <Canvas of={ButtonStories.Tertiary} />
43
53
  <Canvas of={ButtonStories.Accent} />
44
54
  <Canvas of={ButtonStories.PrimarySubtle} />
45
- <Canvas of={ButtonStories.Destructive} source={{ code: usage.destructive }} />
55
+ <Canvas
56
+ of={ButtonStories.Success}
57
+ source={{ code: usage.success }}
58
+ />
59
+ <Canvas
60
+ of={ButtonStories.Destructive}
61
+ source={{ code: usage.destructive }}
62
+ />
46
63
  <Canvas
47
64
  of={ButtonStories.DestructiveTertiaryNoPadding}
48
65
  source={{ code: usage.destructiveNoPadding }}
@@ -52,7 +69,10 @@ Use `variant` to control hierarchy and emphasis.
52
69
 
53
70
  Set `onLight={false}` when a supported inverse variant is placed directly on a dark background.
54
71
 
55
- <Canvas of={ButtonStories.OnDark} source={{ code: usage.onDark }} />
72
+ <Canvas
73
+ of={ButtonStories.OnDark}
74
+ source={{ code: usage.onDark }}
75
+ />
56
76
 
57
77
  ## Sizes
58
78
 
@@ -62,20 +82,36 @@ Set `onLight={false}` when a supported inverse variant is placed directly on a d
62
82
  ## States
63
83
 
64
84
  <Canvas of={ButtonStories.Disabled} />
65
- <Canvas of={ButtonStories.Loading} source={{ code: usage.loading }} />
85
+ <Canvas
86
+ of={ButtonStories.Loading}
87
+ source={{ code: usage.loading }}
88
+ />
66
89
 
67
90
  ## Icons
68
91
 
69
- <Canvas of={ButtonStories.WithIcon} source={{ code: usage.withIcon }} />
92
+ <Canvas
93
+ of={ButtonStories.WithIcon}
94
+ source={{ code: usage.withIcon }}
95
+ />
96
+ <Canvas
97
+ of={ButtonStories.WithTwoIcons}
98
+ source={{ code: usage.withTwoIcons }}
99
+ />
70
100
  <Canvas of={ButtonStories.IconOnly} />
71
101
 
72
102
  ## Polymorphism
73
103
 
74
- <Canvas of={ButtonStories.Link} source={{ code: usage.link }} />
104
+ <Canvas
105
+ of={ButtonStories.Link}
106
+ source={{ code: usage.link }}
107
+ />
75
108
 
76
109
  ## Layout
77
110
 
78
- <Canvas of={ButtonStories.FullWidth} source={{ code: usage.fullWidth }} />
111
+ <Canvas
112
+ of={ButtonStories.FullWidth}
113
+ source={{ code: usage.fullWidth }}
114
+ />
79
115
 
80
116
  ## Common Margins
81
117
 
@@ -35,6 +35,7 @@ const variants = [
35
35
  'tertiary-destructive',
36
36
  'tertiary-destructive-no-padding',
37
37
  'primary-warning',
38
+ 'primary-success',
38
39
  ] as const;
39
40
 
40
41
  const meta = {
@@ -99,6 +100,14 @@ const meta = {
99
100
  type: { summary: 'string', detail: "'left' | 'right'" },
100
101
  },
101
102
  },
103
+ leftIcon: {
104
+ control: false,
105
+ table: { type: { summary: 'ReactElement' } },
106
+ },
107
+ rightIcon: {
108
+ control: false,
109
+ table: { type: { summary: 'ReactElement' } },
110
+ },
102
111
  children: {
103
112
  control: { type: 'text' },
104
113
  type: 'string',
@@ -208,6 +217,14 @@ export const DestructiveTertiaryNoPadding: Story = {
208
217
  },
209
218
  };
210
219
 
220
+ export const Success: Story = {
221
+ name: 'Success primary',
222
+ args: {
223
+ variant: 'primary-success',
224
+ children: 'Success button',
225
+ },
226
+ };
227
+
211
228
  export const OnDark: Story = {
212
229
  name: 'Inverse variants on dark',
213
230
  args: {
@@ -344,6 +361,15 @@ export const IconOnly: Story & {
344
361
  },
345
362
  };
346
363
 
364
+ export const WithTwoIcons: Story = {
365
+ name: 'With two icons',
366
+ args: {
367
+ children: 'Action',
368
+ leftIcon: <Icon.ChevronRight />,
369
+ rightIcon: <Icon.ChevronRight />,
370
+ },
371
+ };
372
+
347
373
  export const Loading: Story = {
348
374
  name: 'Loading',
349
375
  args: {
@@ -22,6 +22,7 @@ import buttonSecondaryDestructiveStyle from './style/buttonSecondaryDestructiveS
22
22
  import buttonTertiaryDestructiveStyle from './style/buttonTertiaryDestructiveStyle';
23
23
  import buttonTertiaryDestructiveNoPaddingStyle from './style/buttonTertiaryDestructiveNoPaddingStyle';
24
24
  import buttonPrimaryWarningStyle from './style/buttonPrimaryWarningStyle';
25
+ import buttonPrimarySuccessStyle from './style/buttonPrimarySuccessStyle';
25
26
  import buttonPrimarySubtleStyle from './style/buttonPrimarySubtleStyle';
26
27
  import buttonSecondarySubtleStyle from './style/buttonSecondarySubtleStyle';
27
28
  import buttonTertiaryNoPaddingStyle from './style/buttonTertiaryNoPaddingStyle';
@@ -42,7 +43,8 @@ export type ButtonVariant =
42
43
  | 'secondary-destructive'
43
44
  | 'tertiary-destructive'
44
45
  | 'tertiary-destructive-no-padding'
45
- | 'primary-warning';
46
+ | 'primary-warning'
47
+ | 'primary-success';
46
48
 
47
49
  const DESTRUCTIVE_VARIANT_MAP: Partial<Record<ButtonVariant, ButtonVariant>> = {
48
50
  primary: 'primary-destructive',
@@ -65,6 +67,8 @@ export interface ButtonBaseProps {
65
67
  disabled?: boolean;
66
68
  icon?: ReactElement<{ className?: string }>;
67
69
  iconPosition?: 'left' | 'right';
70
+ leftIcon?: ReactElement<{ className?: string }>;
71
+ rightIcon?: ReactElement<{ className?: string }>;
68
72
  tooltip?: string;
69
73
  loading?: boolean;
70
74
  fullWidth?: boolean;
@@ -116,6 +120,8 @@ const Button = <C extends ElementType = 'button'>({
116
120
  disabled = false,
117
121
  icon,
118
122
  iconPosition = 'left',
123
+ leftIcon,
124
+ rightIcon,
119
125
  tooltip,
120
126
  loading = false,
121
127
  fullWidth = false,
@@ -185,11 +191,18 @@ const Button = <C extends ElementType = 'button'>({
185
191
  width: ${children ? contentIconSize : iconOnlySize}px;
186
192
  height: ${children ? contentIconSize : iconOnlySize}px;
187
193
  `;
188
- const styledIcon = icon
189
- ? cloneElement(icon, {
190
- className: cx(icon.props.className, iconStyle),
191
- })
192
- : undefined;
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
+ );
193
206
 
194
207
  const sizeExtraSmallStyle = css`
195
208
  height: 32px;
@@ -273,6 +286,12 @@ const Button = <C extends ElementType = 'button'>({
273
286
  disabled,
274
287
  loading
275
288
  ),
289
+ 'primary-success': buttonPrimarySuccessStyle(
290
+ theme,
291
+ selected,
292
+ disabled,
293
+ loading
294
+ ),
276
295
  }[resolvedVariant];
277
296
 
278
297
  const commonDisabledStyle = css`
@@ -323,9 +342,9 @@ const Button = <C extends ElementType = 'button'>({
323
342
  />
324
343
  ) : (
325
344
  <>
326
- {styledIcon && iconPosition === 'left' && styledIcon}
345
+ {styledLeftIcon}
327
346
  {children}
328
- {styledIcon && iconPosition === 'right' && styledIcon}
347
+ {styledRightIcon}
329
348
  </>
330
349
  )}
331
350
  </Component>
@@ -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>
@@ -309,6 +328,7 @@ describe('Button', () => {
309
328
  ['accent', darkTheme.colour.text.inverse],
310
329
  ['primary-destructive', darkTheme.colour.text.inverse],
311
330
  ['primary-warning', darkTheme.colour.text.caution],
331
+ ['primary-success', darkTheme.colour.text.inverse],
312
332
  ] as const)(
313
333
  'uses readable semantic text colour for dark %s variant',
314
334
  (variant, expectedColour) => {
@@ -341,6 +361,25 @@ describe('Button', () => {
341
361
  );
342
362
  });
343
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
+
344
383
  test.each([
345
384
  ['xsmall', '32px', '16px'],
346
385
  ['small', '40px', '20px'],
@@ -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;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "uikit-react-public",
3
3
  "private": false,
4
4
  "license": "UNLICENSED",
5
- "version": "0.50.1",
5
+ "version": "0.50.2",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "types": "dist/index.d.ts",