@indico-data/design-system 3.14.1 → 3.16.0

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/lib/components/button/enums.d.ts +1 -1
  2. package/lib/components/button/types.d.ts +1 -1
  3. package/lib/components/icons/types.d.ts +1 -1
  4. package/lib/index.css +35 -28
  5. package/lib/index.d.ts +2 -2
  6. package/lib/index.esm.css +35 -28
  7. package/lib/index.esm.js +28 -7
  8. package/lib/index.esm.js.map +1 -1
  9. package/lib/index.js +28 -7
  10. package/lib/index.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/components/button/Button.mdx +24 -1
  13. package/src/components/button/Button.stories.tsx +7 -2
  14. package/src/components/button/Button.tsx +26 -16
  15. package/src/components/button/__tests__/Button.test.tsx +64 -11
  16. package/src/components/button/enums.ts +1 -1
  17. package/src/components/button/styles/Button.scss +19 -12
  18. package/src/components/button/styles/_variables.scss +2 -9
  19. package/src/components/button/types.ts +1 -1
  20. package/src/components/floatUI/FloatUI.stories.tsx +5 -0
  21. package/src/components/floatUI/FloatUI.tsx +5 -1
  22. package/src/components/forms/input/Input.tsx +7 -2
  23. package/src/components/forms/input/styles/Input.scss +4 -2
  24. package/src/components/forms/numberInput/NumberInput.tsx +7 -2
  25. package/src/components/forms/passwordInput/PasswordInput.tsx +2 -2
  26. package/src/components/icons/Icon.mdx +1 -1
  27. package/src/components/icons/Icon.stories.tsx +2 -2
  28. package/src/components/icons/styles/Icon.scss +1 -0
  29. package/src/components/icons/types.ts +1 -1
  30. package/src/components/menu/Menu.stories.tsx +3 -0
  31. package/src/components/menu/styles/Menu.scss +2 -2
  32. package/src/components/pagination/Pagination.tsx +2 -0
  33. package/src/components/stepper/components/Legend.tsx +1 -1
  34. package/src/components/toast/Toast.stories.tsx +5 -5
  35. package/src/docs/BaseColorPalette/Swatch.tsx +2 -2
  36. package/src/docs/Primitives.mdx +7 -1
  37. package/src/styles/primitives/_iconSizes.scss +4 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indico-data/design-system",
3
- "version": "3.14.1",
3
+ "version": "3.16.0",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "main": "lib/index.js",
@@ -20,7 +20,23 @@ Use the event props to respond to interactions, including `onBlur` for focus los
20
20
 
21
21
  ## Sizes
22
22
 
23
- The Sizes available are small (`xs`), medium (`sm`), large (`md`), and extra large (`lg`). The default size is medium.
23
+ The Sizes available are extra small (`xs`), small (`sm`), medium (`md`), large (`lg`), and extra large (`xl`). The default size is medium (`md`).
24
+
25
+ Each size has specific padding and icon spacing:
26
+
27
+ - **xs**: Vertical padding `spacing-xxs` (4px), horizontal padding `spacing-sm` (8px), icon gap `spacing-xs` (6px)
28
+ - **sm**: Vertical padding `spacing-xs` (6px), horizontal padding `spacing-lg` (12px), icon gap `spacing-xs` (6px)
29
+ - **md**: Vertical padding `spacing-sm` (8px), horizontal padding `spacing-2xl` (16px), icon gap `spacing-md` (10px)
30
+ - **lg**: Vertical padding `spacing-md` (10px), horizontal padding `spacing-2xl` (16px), icon gap `spacing-md` (10px)
31
+ - **xl**: Vertical padding `spacing-lg` (12px), horizontal padding `spacing-3xl` (20px), icon gap `spacing-md` (10px)
32
+
33
+ Icon sizes are mapped to button sizes as follows:
34
+
35
+ - **xs** button → **xs** icon (12px)
36
+ - **sm** button → **sm** icon (16px)
37
+ - **md** button → **md** icon (20px) - text is 13px
38
+ - **lg** button → **md** icon (20px)
39
+ - **xl** button → **lg** icon (24px) - text is 20px
24
40
 
25
41
  <Story of={ButtonStories.Sizes} />
26
42
 
@@ -52,4 +68,11 @@ The loading state can be achieved by passing the `isLoading` prop.
52
68
 
53
69
  To include an Icon, use either `iconLeft` or `iconRight` props with a valid icon name. If you only want an icon with no text, simply don't pass any children and the button will render as an icon-only button.
54
70
 
71
+ Icon spacing is automatically handled by the button's CSS `gap` property, which varies by button size:
72
+
73
+ - **xs** and **sm** buttons: `spacing-xs` (6px) gap between icons and text
74
+ - **md**, **lg**, and **xl** buttons: `spacing-md` (10px) gap between icons and text
75
+
76
+ Icon sizes are automatically mapped based on button size (see the Sizes section above), so you don't need to specify icon sizes separately.
77
+
55
78
  <Story of={ButtonStories.Icons} />
@@ -87,13 +87,13 @@ const meta: Meta = {
87
87
  },
88
88
  size: {
89
89
  control: 'select',
90
- options: ['xs', 'sm', 'md', 'lg'],
90
+ options: ['xs', 'sm', 'md', 'lg', 'xl'],
91
91
 
92
92
  defaultValue: { summary: 'md' },
93
93
  table: {
94
94
  category: 'Style Props',
95
95
  type: {
96
- summary: 'xs | sm | md | lg',
96
+ summary: 'xs | sm | md | lg | xl',
97
97
  },
98
98
  },
99
99
  },
@@ -200,6 +200,11 @@ export const Sizes: Story = {
200
200
  Large
201
201
  </Button>
202
202
  </Col>
203
+ <Col xs={6} sm={3} className="mb-3">
204
+ <Button size="xl" ariaLabel="Extra Large Button">
205
+ Extra Large
206
+ </Button>
207
+ </Col>
203
208
  </Row>
204
209
  ),
205
210
  };
@@ -1,6 +1,7 @@
1
1
  import React, { forwardRef } from 'react';
2
2
  import classNames from 'classnames';
3
3
  import { Icon } from '../icons/Icon';
4
+ import { IconSizes } from '../icons/types';
4
5
 
5
6
  import { ButtonProps } from './types';
6
7
 
@@ -35,6 +36,27 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) =>
35
36
  className,
36
37
  );
37
38
 
39
+ // Map button size to icon size
40
+ // xs → xs (12px), sm → sm (16px), md → md (20px), lg → md (20px), xl → lg (24px)
41
+ const getIconSize = (buttonSize: string): IconSizes => {
42
+ switch (buttonSize) {
43
+ case 'xs':
44
+ return 'xs';
45
+ case 'sm':
46
+ return 'sm';
47
+ case 'md':
48
+ return 'md'; // md buttons use md icons (20px)
49
+ case 'lg':
50
+ return 'md'; // lg buttons use md icons (20px)
51
+ case 'xl':
52
+ return 'lg'; // xl buttons use lg icons (24px)
53
+ default:
54
+ return 'md';
55
+ }
56
+ };
57
+
58
+ const iconSize = getIconSize(size);
59
+
38
60
  const handleOnClick = (event: React.MouseEvent<HTMLButtonElement>) => {
39
61
  if (!isLoading && onClick) {
40
62
  onClick(event);
@@ -60,20 +82,14 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) =>
60
82
  <Icon
61
83
  name="indico-o"
62
84
  style={{ animation: 'spin 1s linear infinite' }}
63
- className={children ? 'mr-2' : ''}
64
85
  ariaLabel="Loading..."
65
- size={size}
86
+ size={iconSize}
66
87
  />
67
88
  )}
68
89
 
69
90
  {/* Left Icon */}
70
91
  {iconLeft && !isLoading && (
71
- <Icon
72
- name={iconLeft}
73
- className={children ? 'mr-2' : ''}
74
- ariaLabel={`${iconLeft} Icon`}
75
- size={size}
76
- />
92
+ <Icon name={iconLeft} ariaLabel={`${iconLeft} Icon`} size={iconSize} />
77
93
  )}
78
94
 
79
95
  {/* Button children */}
@@ -81,12 +97,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) =>
81
97
 
82
98
  {/* Right Icon */}
83
99
  {iconRight && !isLoading && (
84
- <Icon
85
- name={iconRight}
86
- className={children ? 'ml-2' : ''}
87
- ariaLabel={`${iconRight} Icon`}
88
- size={size}
89
- />
100
+ <Icon name={iconRight} ariaLabel={`${iconRight} Icon`} size={iconSize} />
90
101
  )}
91
102
 
92
103
  {/* Loading Icon on the right */}
@@ -94,9 +105,8 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) =>
94
105
  <Icon
95
106
  name="indico-o"
96
107
  style={{ animation: 'spin 1s linear infinite' }}
97
- className={children ? 'ml-2' : ''}
98
108
  ariaLabel="Loading..."
99
- size={size}
109
+ size={iconSize}
100
110
  />
101
111
  )}
102
112
  </button>
@@ -57,7 +57,6 @@ describe('Button', () => {
57
57
  expect(button).toHaveClass('btn--loading');
58
58
  expect(button).toBeDisabled();
59
59
  expect(loadingIcon).toBeInTheDocument();
60
- expect(loadingIcon).toHaveClass('mr-2');
61
60
  });
62
61
 
63
62
  it('displays the loading icon on the left when isLoading and iconLeft exists and hides the iconLeft', () => {
@@ -69,7 +68,6 @@ describe('Button', () => {
69
68
  const loadingIcon = screen.getByLabelText('Loading...');
70
69
  const iconLeft = screen.queryByLabelText('check Icon');
71
70
 
72
- expect(loadingIcon).toHaveClass('mr-2');
73
71
  expect(iconLeft).not.toBeInTheDocument();
74
72
  });
75
73
 
@@ -82,19 +80,16 @@ describe('Button', () => {
82
80
  const loadingIcon = screen.getByLabelText('Loading...');
83
81
  const iconRight = screen.queryByLabelText('check Icon');
84
82
 
85
- expect(loadingIcon).toHaveClass('ml-2');
86
83
  expect(iconRight).not.toBeInTheDocument();
87
84
  });
88
85
 
89
86
  it('does not apply a margin to the loading icon when no children are present', () => {
90
87
  render(<Button isLoading iconLeft="check" onClick={onClick} ariaLabel="btn" />);
91
88
  const loadingIcon = screen.getByLabelText('Loading...');
92
- expect(loadingIcon).not.toHaveClass('mr-2');
93
- expect(loadingIcon).not.toHaveClass('ml-2');
89
+ expect(loadingIcon).toBeInTheDocument();
94
90
 
95
91
  render(<Button isLoading iconRight="check" onClick={onClick} ariaLabel="btn" />);
96
- expect(loadingIcon).not.toHaveClass('mr-2');
97
- expect(loadingIcon).not.toHaveClass('ml-2');
92
+ expect(loadingIcon).toBeInTheDocument();
98
93
  });
99
94
 
100
95
  it('does not apply the loading class when not loading', () => {
@@ -156,7 +151,6 @@ describe('Button', () => {
156
151
  const button = screen.getByRole('button');
157
152
 
158
153
  expect(button).toContainElement(icon);
159
- expect(icon).toHaveClass('mr-2');
160
154
  });
161
155
 
162
156
  it('renders a right icon with proper spacing when children are present', () => {
@@ -169,7 +163,6 @@ describe('Button', () => {
169
163
  const button = screen.getByRole('button');
170
164
 
171
165
  expect(button).toContainElement(icon);
172
- expect(icon).toHaveClass('ml-2');
173
166
  });
174
167
 
175
168
  it('renders both left and right icons with proper spacing when both are provided', () => {
@@ -184,8 +177,68 @@ describe('Button', () => {
184
177
 
185
178
  expect(button).toContainElement(leftIcon);
186
179
  expect(button).toContainElement(rightIcon);
187
- expect(leftIcon).toHaveClass('mr-2');
188
- expect(rightIcon).toHaveClass('ml-2');
180
+ });
181
+ });
182
+
183
+ describe('icon size mapping', () => {
184
+ it('uses xs icon size for xs button', () => {
185
+ render(
186
+ <Button size="xs" iconLeft="check" ariaLabel="xs button">
187
+ Button
188
+ </Button>,
189
+ );
190
+ const icon = screen.getByLabelText('check Icon');
191
+ expect(icon).toHaveClass('icon--xs');
192
+ });
193
+
194
+ it('uses sm icon size for sm button', () => {
195
+ render(
196
+ <Button size="sm" iconLeft="check" ariaLabel="sm button">
197
+ Button
198
+ </Button>,
199
+ );
200
+ const icon = screen.getByLabelText('check Icon');
201
+ expect(icon).toHaveClass('icon--sm');
202
+ });
203
+
204
+ it('uses md icon size for md button', () => {
205
+ render(
206
+ <Button size="md" iconLeft="check" ariaLabel="md button">
207
+ Button
208
+ </Button>,
209
+ );
210
+ const icon = screen.getByLabelText('check Icon');
211
+ expect(icon).toHaveClass('icon--md');
212
+ });
213
+
214
+ it('uses md icon size for lg button', () => {
215
+ render(
216
+ <Button size="lg" iconLeft="check" ariaLabel="lg button">
217
+ Button
218
+ </Button>,
219
+ );
220
+ const icon = screen.getByLabelText('check Icon');
221
+ expect(icon).toHaveClass('icon--md');
222
+ });
223
+
224
+ it('uses lg icon size for xl button', () => {
225
+ render(
226
+ <Button size="xl" iconLeft="check" ariaLabel="xl button">
227
+ Button
228
+ </Button>,
229
+ );
230
+ const icon = screen.getByLabelText('check Icon');
231
+ expect(icon).toHaveClass('icon--lg');
232
+ });
233
+
234
+ it('applies correct icon size to loading icon based on button size', () => {
235
+ render(
236
+ <Button size="sm" isLoading ariaLabel="loading button">
237
+ Button
238
+ </Button>,
239
+ );
240
+ const loadingIcon = screen.getByLabelText('Loading...');
241
+ expect(loadingIcon).toHaveClass('icon--sm');
189
242
  });
190
243
  });
191
244
  });
@@ -1,5 +1,5 @@
1
1
  export type ButtonVariants = 'solid' | 'outline' | 'link' | 'action' | 'destructive' | 'soft';
2
2
 
3
- export type ButtonSizes = 'xs' | 'sm' | 'md' | 'lg';
3
+ export type ButtonSizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
4
4
 
5
5
  export type ButtonTypes = 'button' | 'submit' | 'reset';
@@ -11,6 +11,7 @@
11
11
  border-color: transparent;
12
12
  border-radius: var(--pf-button-border-radius);
13
13
  font-weight: var(--pf-button-font-weight);
14
+ gap: 0; // Default gap, will be overridden by size-specific rules
14
15
 
15
16
  cursor: pointer;
16
17
  &:disabled {
@@ -20,27 +21,33 @@
20
21
 
21
22
  // Button Sizes
22
23
  .btn--xs {
23
- line-height: var(--pf-button-line-height-xs);
24
- padding: var(--pf-spacing-xxs) var(--pf-spacing-lg);
25
- font-size: var(--pf-button-font-size-xs);
24
+ padding: var(--pf-spacing-xxs) var(--pf-spacing-sm);
25
+ font-size: var(--pf-font-size-sm);
26
+ gap: var(--pf-spacing-xs);
26
27
  }
27
28
 
28
29
  .btn--sm {
29
- line-height: var(--pf-button-line-height-sm);
30
- padding: var(--pf-spacing-xxs) var(--pf-spacing-lg);
31
- font-size: var(--pf-button-font-size-sm);
30
+ padding: var(--pf-spacing-xs) var(--pf-spacing-lg);
31
+ font-size: var(--pf-font-size-md);
32
+ gap: var(--pf-spacing-xs);
32
33
  }
33
34
 
34
35
  .btn--md {
35
- line-height: var(--pf-button-line-height-md);
36
- padding: var(--pf-spacing-sm) var(--pf-spacing-lg);
37
- font-size: var(--pf-button-font-size-md);
36
+ padding: var(--pf-spacing-sm) var(--pf-spacing-2xl);
37
+ font-size: var(--pf-font-size-base);
38
+ gap: var(--pf-spacing-md);
38
39
  }
39
40
 
40
41
  .btn--lg {
41
- line-height: var(--pf-button-line-height-lg);
42
- padding: var(--pf-spacing-sm) var(--pf-spacing-2xl);
43
- font-size: var(--pf-button-font-size-lg);
42
+ padding: var(--pf-spacing-md) var(--pf-spacing-2xl);
43
+ font-size: var(--pf-font-size-2xl);
44
+ gap: var(--pf-spacing-md);
45
+ }
46
+
47
+ .btn--xl {
48
+ padding: var(--pf-spacing-lg) var(--pf-spacing-3xl);
49
+ font-size: var(--pf-font-size-3xl);
50
+ gap: var(--pf-spacing-md);
44
51
  }
45
52
 
46
53
  .btn--icon-only {
@@ -3,15 +3,8 @@
3
3
  :root [data-theme='light'],
4
4
  :root [data-theme='dark'] {
5
5
  // Typography
6
- --pf-button-font-weight: var(--pf-font-weight-regular);
7
- --pf-button-font-size-xs: calc(0.875 * var(--pf-font-size-base));
8
- --pf-button-font-size-sm: calc(0.875 * var(--pf-font-size-base));
9
- --pf-button-font-size-md: calc(0.875 * var(--pf-font-size-base));
10
- --pf-button-font-size-lg: var(--pf-font-size-base);
11
- --pf-button-line-height-xs: var(--pf-line-height-md);
12
- --pf-button-line-height-sm: var(--pf-line-height-md);
13
- --pf-button-line-height-md: var(--pf-line-height-md);
14
- --pf-button-line-height-lg: var(--pf-line-height-lg);
6
+
7
+ --pf-button-font-weight: var(--pf-font-weight-medium);
15
8
 
16
9
  // Border radii
17
10
  --pf-button-border-radius: var(--pf-border-radius-md);
@@ -2,7 +2,7 @@ import { IconName } from '../../types';
2
2
 
3
3
  export type ButtonVariants = 'solid' | 'outline' | 'link' | 'action' | 'destructive' | 'soft';
4
4
 
5
- export type ButtonSizes = 'xs' | 'sm' | 'md' | 'lg';
5
+ export type ButtonSizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
6
6
 
7
7
  export type ButtonTypes = 'button' | 'submit' | 'reset';
8
8
 
@@ -115,6 +115,7 @@ export const Uncontrolled: Story = {
115
115
  data-testid="refresh-library"
116
116
  ariaLabel="Refresh Data"
117
117
  iconLeft="retrain"
118
+ size="sm"
118
119
  onClick={() => console.log('Refresh Data')}
119
120
  >
120
121
  Refresh Data
@@ -123,6 +124,7 @@ export const Uncontrolled: Story = {
123
124
  data-testid="configure-fields"
124
125
  ariaLabel="Configure Fields"
125
126
  iconLeft="edit"
127
+ size="sm"
126
128
  onClick={() => console.log('Configure Fields')}
127
129
  >
128
130
  Configure Fields
@@ -131,6 +133,7 @@ export const Uncontrolled: Story = {
131
133
  data-testid="delete-library"
132
134
  ariaLabel="Delete Library"
133
135
  iconLeft="trash"
136
+ size="sm"
134
137
  onClick={() => console.log('Delete Library')}
135
138
  >
136
139
  Delete Library
@@ -198,6 +201,7 @@ export const Hover: Story = {
198
201
  data-testid="hover-item-1"
199
202
  ariaLabel="Item 1"
200
203
  iconLeft="retrain"
204
+ size="sm"
201
205
  onClick={() => console.log('Item 1')}
202
206
  >
203
207
  Item 1
@@ -206,6 +210,7 @@ export const Hover: Story = {
206
210
  data-testid="hover-item-2"
207
211
  ariaLabel="Item 2"
208
212
  iconLeft="edit"
213
+ size="sm"
209
214
  onClick={() => console.log('Item 2')}
210
215
  >
211
216
  Item 2
@@ -11,6 +11,8 @@ import {
11
11
  shift,
12
12
  Placement,
13
13
  useDismiss,
14
+ ReferenceType,
15
+ VirtualElement,
14
16
  } from '@floating-ui/react';
15
17
  import { FloatUIProps } from './types';
16
18
 
@@ -54,6 +56,8 @@ export function FloatUI({
54
56
  throw new Error('Both children of FloatUI must be valid React elements.');
55
57
  }
56
58
 
59
+ const referenceElement = floatingOptions.elements?.reference || referenceElementRef.current;
60
+
57
61
  const { refs, floatingStyles, context } = useFloating({
58
62
  ...floatingOptions,
59
63
  open: isOpen,
@@ -62,7 +66,7 @@ export function FloatUI({
62
66
  onOpenChange?.(isOpen);
63
67
  },
64
68
  elements: {
65
- reference: referenceElementRef.current,
69
+ reference: referenceElement as Element | null,
66
70
  },
67
71
  });
68
72
 
@@ -69,7 +69,12 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
69
69
  <>
70
70
  <div className="input-wrapper">
71
71
  {iconName && (
72
- <Icon name={iconName} data-testid={`${name}-embedded-icon`} className="embedded-icon" />
72
+ <Icon
73
+ name={iconName}
74
+ data-testid={`${name}-embedded-icon`}
75
+ className="embedded-icon"
76
+ size="sm"
77
+ />
73
78
  )}
74
79
  <input
75
80
  ref={ref}
@@ -95,7 +100,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
95
100
  <Icon
96
101
  name="x-close"
97
102
  data-testid={`${name}-clearable-icon`}
98
- size="sm"
103
+ size="xs"
99
104
  onClick={handleClear}
100
105
  className="clearable-icon"
101
106
  />
@@ -16,13 +16,15 @@
16
16
  position: relative;
17
17
  .embedded-icon {
18
18
  position: absolute;
19
- top: 10px;
19
+ top: 50%;
20
+ transform: translateY(-50%);
20
21
  left: var(--pf-spacing-sm);
21
22
  color: var(--pf-semantic-font-regular);
22
23
  }
23
24
  .clearable-icon {
24
25
  position: absolute;
25
- top: var(--pf-spacing-lg);
26
+ top: 50%;
27
+ transform: translateY(-50%);
26
28
  right: var(--pf-spacing-sm);
27
29
  color: var(--pf-semantic-font-regular);
28
30
  cursor: pointer;
@@ -55,7 +55,12 @@ const NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(
55
55
  <>
56
56
  <div className="number-input-wrapper">
57
57
  {iconName && (
58
- <Icon name={iconName} data-testid={`${name}-embedded-icon`} className="embedded-icon" />
58
+ <Icon
59
+ name={iconName}
60
+ data-testid={`${name}-embedded-icon`}
61
+ className="embedded-icon"
62
+ size="sm"
63
+ />
59
64
  )}
60
65
  <input
61
66
  ref={ref}
@@ -78,7 +83,7 @@ const NumberInput = React.forwardRef<HTMLInputElement, NumberInputProps>(
78
83
  data-testid={`${name}-clearable-icon`}
79
84
  onClick={handleClear}
80
85
  className="clearable-icon"
81
- size="sm"
86
+ size="xs"
82
87
  />
83
88
  )}
84
89
  </div>
@@ -55,7 +55,7 @@ const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(
55
55
  return (
56
56
  <>
57
57
  <div className="password-input-wrapper">
58
- <Icon name="lock" data-testid={`${name}-embedded-icon`} className="embedded-icon" />
58
+ <Icon name="lock" data-testid={`${name}-embedded-icon`} className="embedded-icon" size="sm" />
59
59
  <input
60
60
  ref={ref}
61
61
  data-testid={`form-password-input-${name}`}
@@ -76,7 +76,7 @@ const PasswordInput = React.forwardRef<HTMLInputElement, PasswordInputProps>(
76
76
  <Icon
77
77
  name={showPassword ? 'fa-eye-slash' : 'eye'}
78
78
  data-testid={`${name}-${showPassword ? 'hide' : 'show'}-password-icon`}
79
- size="md"
79
+ size="sm"
80
80
  onClick={handleShowPassword}
81
81
  className="toggle-show-password-icon"
82
82
  />
@@ -21,7 +21,7 @@ The `Icon` component provides unified rendering of both custom SVG icons (Indico
21
21
 
22
22
  ## Sizes
23
23
 
24
- The `Icon` component supports five predefined sizes:
24
+ The `Icon` component supports eight predefined sizes:
25
25
 
26
26
  <Story of={IconStories.IconStates} />
27
27
 
@@ -84,8 +84,8 @@ export const DefaultIcon: Story = {
84
84
 
85
85
  export const IconStates: Story = {
86
86
  render: (args) => {
87
- const sizes: IconSizes[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];
88
- const rems = ['10px', '12px', '16px', '24px', '32px', '48px', '64px'];
87
+ const sizes: IconSizes[] = ['xxs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl'];
88
+ const rems = ['10px', '12px', '16px', '20px', '24px', '32px', '48px', '64px'];
89
89
 
90
90
  return (
91
91
  <Row>
@@ -1,4 +1,5 @@
1
1
  $sizes: (
2
+ xxs: var(--pf-icon-size-xxs),
2
3
  xs: var(--pf-icon-size-xs),
3
4
  sm: var(--pf-icon-size-sm),
4
5
  md: var(--pf-icon-size-md),
@@ -3,7 +3,7 @@ import { PermafrostComponent } from '../../types';
3
3
  import { IconName as FAIconName, IconPrefix } from '@fortawesome/fontawesome-svg-core';
4
4
  import { indicons } from './indicons';
5
5
 
6
- export type IconSizes = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';
6
+ export type IconSizes = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';
7
7
 
8
8
  export type IndiconName = keyof typeof indicons;
9
9
 
@@ -41,6 +41,7 @@ export const Default: Story = {
41
41
  data-testid="refresh-library"
42
42
  ariaLabel="Refresh Data"
43
43
  iconLeft="retrain"
44
+ size="sm"
44
45
  onClick={() => console.log('Refresh Data')}
45
46
  >
46
47
  Refresh Data
@@ -49,6 +50,7 @@ export const Default: Story = {
49
50
  data-testid="configure-fields"
50
51
  ariaLabel="Configure Fields"
51
52
  iconLeft="edit"
53
+ size="sm"
52
54
  onClick={() => console.log('Configure Fields')}
53
55
  >
54
56
  Configure Fields
@@ -57,6 +59,7 @@ export const Default: Story = {
57
59
  data-testid="delete-library"
58
60
  ariaLabel="Delete Library"
59
61
  iconLeft="trash"
62
+ size="sm"
60
63
  onClick={() => console.log('Delete Library')}
61
64
  >
62
65
  Delete Library
@@ -5,8 +5,8 @@
5
5
  width: 100%;
6
6
  background: var(--pf-semantic-background-secondary);
7
7
  color: var(--pf-semantic-font-regular);
8
- display: block;
9
- width: 100%;
8
+ display: flex;
9
+ justify-content: flex-start;
10
10
  text-align: left;
11
11
  border: none;
12
12
  border-radius: 0;
@@ -64,6 +64,7 @@ export const Pagination = ({
64
64
  variant="link"
65
65
  onClick={handlePreviousPage}
66
66
  iconLeft="chevron-left"
67
+ size="sm"
67
68
  isDisabled={isPreviousButtonDisabled || totalPages === 0}
68
69
  />
69
70
  </div>
@@ -107,6 +108,7 @@ export const Pagination = ({
107
108
  onClick={handleNextPage}
108
109
  iconLeft="chevron-right"
109
110
  isDisabled={isNextButtonDisabled || totalPages === 0}
111
+ size="sm"
110
112
  />
111
113
  </div>
112
114
  </Col>
@@ -23,7 +23,7 @@ export const Legend = ({ currentStep, steps, onStepClick }: StepperLegendProps)
23
23
  current: isCurrent,
24
24
  })}
25
25
  >
26
- {isCompleted ? <Icon name="check" /> : index + 1}
26
+ {isCompleted ? <Icon name="check" size="sm" /> : index + 1}
27
27
  </div>
28
28
  </Col>
29
29
  <Col>
@@ -48,27 +48,27 @@ export const Default: Story = {
48
48
  render: (args) => (
49
49
  <Row>
50
50
  <Col>
51
- <Button ariaLabel="Click me" onClick={() => toast('Hello World')}>
51
+ <Button ariaLabel="Click me" onClick={() => toast('Hello World')} size="sm">
52
52
  Fire default toast
53
53
  </Button>
54
54
  </Col>
55
55
  <Col>
56
- <Button ariaLabel="Click me" onClick={() => toast.info('Hello World')}>
56
+ <Button ariaLabel="Click me" onClick={() => toast.info('Hello World')} size="sm">
57
57
  Fire info toast
58
58
  </Button>
59
59
  </Col>
60
60
  <Col>
61
- <Button ariaLabel="Click me" onClick={() => toast.warning('Hello World')}>
61
+ <Button ariaLabel="Click me" onClick={() => toast.warning('Hello World')} size="sm">
62
62
  Fire warning toast
63
63
  </Button>
64
64
  </Col>
65
65
  <Col>
66
- <Button ariaLabel="Click me" onClick={() => toast.error('Hello World')}>
66
+ <Button ariaLabel="Click me" onClick={() => toast.error('Hello World')} size="sm">
67
67
  Fire error toast
68
68
  </Button>
69
69
  </Col>
70
70
  <Col>
71
- <Button ariaLabel="Click me" onClick={() => toast.success('Hello World')}>
71
+ <Button ariaLabel="Click me" onClick={() => toast.success('Hello World')} size="sm">
72
72
  Fire success toast
73
73
  </Button>
74
74
  <ToastContainer {...args} />