@indico-data/design-system 2.45.1 → 2.45.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -4
- package/lib/components/forms/date/datePicker/contants.d.ts +1 -1
- package/lib/components/icons/Icon.stories.d.ts +1 -0
- package/lib/components/icons/indicons.d.ts +3 -1
- package/lib/components/icons/types.d.ts +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.esm.js +216 -166
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +214 -164
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/button/Button.stories.tsx +5 -0
- package/src/components/icons/Icon.mdx +26 -5
- package/src/components/icons/Icon.stories.tsx +21 -3
- package/src/components/icons/Icon.tsx +10 -14
- package/src/components/icons/__tests__/Icon.test.tsx +8 -8
- package/src/components/icons/indicons.tsx +296 -351
- package/src/components/icons/types.ts +2 -2
- package/src/legacy/components/modals/ModalBase/ModalBase.stories.tsx +2 -4
- package/src/legacy/components/modals/ModalBase/ModalBase.styles.tsx +8 -2
- package/src/setup/setupIcons.ts +5 -1
- package/src/storybook/iconNames.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
import { Button, Col, Row } from '@/components';
|
|
3
3
|
import { iconNames } from '@/storybook/iconNames';
|
|
4
|
+
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
5
|
+
import { registerFontAwesomeIcons } from '@/setup/setupIcons';
|
|
6
|
+
import { indiconDefinitions } from '@/components/icons/indicons';
|
|
7
|
+
|
|
8
|
+
registerFontAwesomeIcons(...Object.values(fas), ...indiconDefinitions);
|
|
4
9
|
|
|
5
10
|
const meta: Meta = {
|
|
6
11
|
title: 'Components/Button',
|
|
@@ -6,7 +6,7 @@ import { Col, Row } from '@/components';
|
|
|
6
6
|
|
|
7
7
|
# Icon
|
|
8
8
|
|
|
9
|
-
The `Icon` component provides unified rendering of both custom SVG icons (Indicons) and
|
|
9
|
+
The `Icon` component provides unified rendering of both custom SVG icons (Indicons) and Font Awesome icons.
|
|
10
10
|
|
|
11
11
|
<Canvas
|
|
12
12
|
of={IconStories.DefaultIcon}
|
|
@@ -31,17 +31,38 @@ You can use the `className` prop to apply custom styles to the icons.
|
|
|
31
31
|
|
|
32
32
|
<Story of={IconStories.CustomStyledIcon} />
|
|
33
33
|
```tsx // .tsx
|
|
34
|
-
<Icon name="fa-mountain-sun" className="color-primary-600" />
|
|
34
|
+
<Icon name="fa-mountain-sun" size="xl" className="color-primary-600" />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Duotone Icons
|
|
38
|
+
|
|
39
|
+
Some icons are duotone, meaning they have two non-overlapping layers that can be styled differently. By default, the secondary (top) layer is differentiated by an opacity of 40% (while the primary layer has an opacity of 100%). To apply different styles to the primary and secondary layers, use the `--fa-primary-` and `--fa-secondary-` prefixes to set the `color` and `opacity` styles.
|
|
40
|
+
|
|
41
|
+
<Story of={IconStories.DuotoneIconStory} />
|
|
42
|
+
```tsx // .tsx
|
|
43
|
+
<Icon
|
|
44
|
+
name="warning-stroke"
|
|
45
|
+
size="xl"
|
|
46
|
+
// in a real scenario, these should be set via CSS rather than inline
|
|
47
|
+
style={{
|
|
48
|
+
'--fa-primary-color': 'gold',
|
|
49
|
+
'--fa-secondary-color': 'black',
|
|
50
|
+
'--fa-secondary-opacity': '1.0',
|
|
51
|
+
}}
|
|
52
|
+
/>
|
|
35
53
|
```
|
|
36
54
|
|
|
37
55
|
## Indicons (Custom Icons)
|
|
38
56
|
|
|
39
|
-
Indicons are custom SVG icons created specifically for our design system.
|
|
57
|
+
Indicons are custom SVG icons created specifically for our design system. The complete icon set is registered and available by default, unlike Font Awesome icons.
|
|
58
|
+
|
|
59
|
+
Below is a list of all available custom icons.
|
|
40
60
|
|
|
41
61
|
<Story of={IconStories.Indicons} />
|
|
62
|
+
|
|
42
63
|
## Font Awesome Icons
|
|
43
64
|
|
|
44
|
-
All
|
|
65
|
+
All Font Awesome icon names are prefixed with `fa-`. For a Font Awesome icon to be available, it must be registered globally via `registerFontAwesomeIcons`.
|
|
45
66
|
|
|
46
67
|
For example:
|
|
47
68
|
|
|
@@ -66,7 +87,7 @@ import { registerFontAwesomeIcons } from '@indico-data/design-system';
|
|
|
66
87
|
registerFontAwesomeIcons(...Object.values(fas));
|
|
67
88
|
```
|
|
68
89
|
|
|
69
|
-
Below is a list of
|
|
90
|
+
Below is a list of Font Awesome icons available in our design system. Use the search bar to find specific icons, and navigate
|
|
70
91
|
through the pages to explore all icons.
|
|
71
92
|
|
|
72
93
|
<Story of={IconStories.FontAwesomeIcons} />
|
|
@@ -5,8 +5,9 @@ import { IconName, IconProps, IconSizes } from './types';
|
|
|
5
5
|
import { fas } from '@fortawesome/free-solid-svg-icons';
|
|
6
6
|
import { registerFontAwesomeIcons } from '@/index';
|
|
7
7
|
import { fontAwesomeIconNames, iconNames, indiconIconNames } from '@/storybook/iconNames';
|
|
8
|
+
import { indiconDefinitions } from './indicons';
|
|
8
9
|
|
|
9
|
-
registerFontAwesomeIcons(...Object.values(fas));
|
|
10
|
+
registerFontAwesomeIcons(...Object.values(fas), ...indiconDefinitions);
|
|
10
11
|
|
|
11
12
|
const meta: Meta = {
|
|
12
13
|
title: 'Components/Icon',
|
|
@@ -105,7 +106,24 @@ export const IconStates: Story = {
|
|
|
105
106
|
|
|
106
107
|
export const CustomStyledIcon: Story = {
|
|
107
108
|
render: () => {
|
|
108
|
-
return <Icon name="fa-mountain-sun" className="color-primary-600" />;
|
|
109
|
+
return <Icon name="fa-mountain-sun" size="xl" className="color-primary-600" />;
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const DuotoneIconStory: Story = {
|
|
114
|
+
render: () => {
|
|
115
|
+
return (
|
|
116
|
+
<Icon
|
|
117
|
+
name="warning-stroke"
|
|
118
|
+
size="xl"
|
|
119
|
+
style={{
|
|
120
|
+
// @ts-ignore
|
|
121
|
+
'--fa-primary-color': 'gold',
|
|
122
|
+
'--fa-secondary-color': 'black',
|
|
123
|
+
'--fa-secondary-opacity': '1.0',
|
|
124
|
+
}}
|
|
125
|
+
/>
|
|
126
|
+
);
|
|
109
127
|
},
|
|
110
128
|
};
|
|
111
129
|
|
|
@@ -164,7 +182,7 @@ export const FontAwesomeIcons: Story = {
|
|
|
164
182
|
const [searchQuery, setSearchQuery] = useState('');
|
|
165
183
|
const iconsPerPage = 60;
|
|
166
184
|
|
|
167
|
-
// Filter
|
|
185
|
+
// Filter Font Awesome icons based on the search query
|
|
168
186
|
const filteredIcons = fontAwesomeIconNames.filter((icon) =>
|
|
169
187
|
icon.toLowerCase().includes(searchQuery.toLowerCase()),
|
|
170
188
|
);
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { ReactElement, cloneElement } from 'react';
|
|
2
1
|
import classNames from 'classnames';
|
|
3
2
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
4
3
|
import { IconName as FAIconName, findIconDefinition } from '@fortawesome/fontawesome-svg-core';
|
|
5
4
|
import { IconProps } from './types';
|
|
6
|
-
import { indicons } from './indicons';
|
|
7
5
|
|
|
8
6
|
export const Icon = ({ name, size = 'md', className, ariaLabel, ...props }: IconProps) => {
|
|
9
7
|
const label = ariaLabel || `${name} Icon`;
|
|
@@ -16,7 +14,6 @@ export const Icon = ({ name, size = 'md', className, ariaLabel, ...props }: Icon
|
|
|
16
14
|
className,
|
|
17
15
|
);
|
|
18
16
|
|
|
19
|
-
const customIcon = indicons[name as keyof typeof indicons];
|
|
20
17
|
const faIconName = name.split('fa-')[1];
|
|
21
18
|
const faIcon =
|
|
22
19
|
faIconName &&
|
|
@@ -24,21 +21,20 @@ export const Icon = ({ name, size = 'md', className, ariaLabel, ...props }: Icon
|
|
|
24
21
|
prefix: 'fas',
|
|
25
22
|
iconName: faIconName as FAIconName,
|
|
26
23
|
});
|
|
24
|
+
const icon =
|
|
25
|
+
faIcon ||
|
|
26
|
+
findIconDefinition({
|
|
27
|
+
prefix: 'fak',
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
iconName: name,
|
|
30
|
+
});
|
|
27
31
|
|
|
28
|
-
if (!
|
|
32
|
+
if (!icon) {
|
|
29
33
|
console.error(
|
|
30
|
-
`Icon '${name}' not found.
|
|
34
|
+
`Icon '${name}' not found. Is it entered correctly, and did you remember to register it? See the [Permafrost Icon Documentation](https://ds.indico-dev.indico.io/iframe.html?viewMode=docs&id=components-icon--icon#font-awesome-icons) for more.`,
|
|
31
35
|
);
|
|
32
36
|
return null;
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
return
|
|
36
|
-
<FontAwesomeIcon icon={faIcon} className={iconClasses} aria-label={label} {...props} />
|
|
37
|
-
) : (
|
|
38
|
-
cloneElement(customIcon as ReactElement, {
|
|
39
|
-
className: iconClasses,
|
|
40
|
-
'aria-label': label,
|
|
41
|
-
...props,
|
|
42
|
-
})
|
|
43
|
-
);
|
|
39
|
+
return <FontAwesomeIcon icon={icon} className={iconClasses} aria-label={label} {...props} />;
|
|
44
40
|
};
|
|
@@ -3,48 +3,48 @@ import userEvent from '@testing-library/user-event';
|
|
|
3
3
|
import { Icon } from '@/components/icons/Icon';
|
|
4
4
|
|
|
5
5
|
describe('Icon Component', () => {
|
|
6
|
-
describe('
|
|
6
|
+
describe('Font Awesome Icons', () => {
|
|
7
7
|
const faIconName = 'fa-arrow-down';
|
|
8
8
|
const labelText = `${faIconName} Icon`;
|
|
9
9
|
|
|
10
|
-
test('renders
|
|
10
|
+
test('renders Font Awesome icon', () => {
|
|
11
11
|
render(<Icon name={faIconName} />);
|
|
12
12
|
const icon = screen.getByLabelText(labelText);
|
|
13
13
|
expect(icon).toBeInTheDocument();
|
|
14
14
|
expect(icon).toHaveClass(faIconName);
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
test('applies size class to
|
|
17
|
+
test('applies size class to Font Awesome icon', () => {
|
|
18
18
|
render(<Icon name={faIconName} size="lg" />);
|
|
19
19
|
const icon = screen.getByLabelText(labelText);
|
|
20
20
|
expect(icon).toHaveClass('icon--lg');
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
test('applies custom className to
|
|
23
|
+
test('applies custom className to Font Awesome icon', () => {
|
|
24
24
|
render(<Icon name={faIconName} className="custom-class" />);
|
|
25
25
|
const icon = screen.getByLabelText(labelText);
|
|
26
26
|
expect(icon).toHaveClass('custom-class');
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test('applies style to
|
|
29
|
+
test('applies style to Font Awesome icon', () => {
|
|
30
30
|
render(<Icon name={faIconName} style={{ color: 'red' }} />);
|
|
31
31
|
const icon = screen.getByLabelText(labelText);
|
|
32
32
|
expect(icon).toHaveStyle('color: red');
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
test('uses ariaLabel prop for
|
|
35
|
+
test('uses ariaLabel prop for Font Awesome icon', () => {
|
|
36
36
|
render(<Icon name={faIconName} ariaLabel="custom label" />);
|
|
37
37
|
const icon = screen.getByLabelText('custom label');
|
|
38
38
|
expect(icon).toBeInTheDocument();
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test('applies id to
|
|
41
|
+
test('applies id to Font Awesome icon', () => {
|
|
42
42
|
render(<Icon name={faIconName} id="test-id" />);
|
|
43
43
|
const icon = screen.getByLabelText(labelText);
|
|
44
44
|
expect(icon).toHaveAttribute('id', 'test-id');
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
-
test('handles onClick event for
|
|
47
|
+
test('handles onClick event for Font Awesome icon', async () => {
|
|
48
48
|
const handleClick = jest.fn();
|
|
49
49
|
render(<Icon name={faIconName} onClick={handleClick} />);
|
|
50
50
|
const icon = screen.getByLabelText(labelText);
|