Skip to content

Commit d21b8f3

Browse files
Merge pull request #699 from glints-dev/feature/foundations-icon
Add new icons and Icon component
2 parents 4b4a640 + 09f25ef commit d21b8f3

83 files changed

Lines changed: 729 additions & 73 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/cicd.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ jobs:
1212
- name: Use Node.js
1313
uses: actions/setup-node@v3
1414
with:
15-
node-version: "16"
16-
cache: "yarn"
15+
node-version: '16'
16+
cache: 'yarn'
1717
- name: Install dependencies
1818
run: yarn install --prefer-offline
1919
- name: Build
@@ -34,10 +34,12 @@ jobs:
3434
- name: Use Node.js
3535
uses: actions/setup-node@v3
3636
with:
37-
node-version: "16"
38-
cache: "yarn"
37+
node-version: '16'
38+
cache: 'yarn'
3939
- name: Install dependencies
4040
run: yarn install --prefer-offline
41+
- name: Build Icons
42+
run: yarn build:next:icon
4143
- name: Build storybook
4244
run: yarn storybook:build:test
4345
- name: Run Playwright tests
@@ -61,10 +63,12 @@ jobs:
6163
- name: Use Node.js
6264
uses: actions/setup-node@v3
6365
with:
64-
node-version: "16"
65-
cache: "yarn"
66+
node-version: '16'
67+
cache: 'yarn'
6668
- name: Install dependencies
6769
run: yarn install --prefer-offline
70+
- name: Build Icons
71+
run: yarn build:next:icon
6872
- name: Deploy to Chromatic
6973
uses: chromaui/action@v1
7074
with:

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ dist
33
es
44
lib
55
src/General/Icon/components
6+
src/General/@next/Icon/components
67
*.log
78
.out
89
.DS_Store

.storybook/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,7 @@ module.exports = {
99
'./*.stories.mdx',
1010
],
1111
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
12+
features: {
13+
storyStoreV7: true,
14+
},
1215
};

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
"node": "^14 || ^16"
1010
},
1111
"scripts": {
12-
"build": "npm run build:icon && npm run build:lib && npm run build:es && npm run build:ts",
12+
"build": "npm run build:icon && npm run build:next:icon && npm run build:lib && npm run build:es && npm run build:ts",
1313
"build:lib": "rm -rf lib && babel src -d lib --extensions .ts,.tsx --ignore src/**/*.test.tsx,src/**/*.test.ts",
1414
"build:es": "rm -rf es && cross-env BABEL_ENV=es babel src -d es --extensions .ts,.tsx --ignore src/**/*.test.tsx,src/**/*.test.ts",
1515
"build:ts": "tsc --project tsconfig.declaration.json -d --declarationDir lib && tsc --project tsconfig.declaration.json -d --declarationDir es",
1616
"build:icon": "rm -rf src/General/Icon/components && babel-node --extensions .ts,.tsx src/Utils/Icon/generateIcons.ts && npm run format:icon",
17+
"build:next:icon": "npx @svgr/cli --typescript --out-dir src/General/@next/Icon/components -- src/General/@next/Icon/icons",
1718
"format:icon": "prettier --write src/General/Icon/components/*.tsx",
1819
"imports": "babel-node --extensions .ts scripts/count-imports/index.ts",
1920
"lint": "npm run lint:css && npm run lint:ts",
@@ -62,6 +63,7 @@
6263
"@storybook/builder-webpack5": "^6.5.15",
6364
"@storybook/manager-webpack5": "^6.5.15",
6465
"@storybook/react": "^6.5.15",
66+
"@svgr/cli": "^6.5.1",
6567
"@testing-library/dom": "^8.11.3",
6668
"@testing-library/jest-dom": "^5.16.2",
6769
"@testing-library/react": "^11.2.7",

src/@next/index.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
1-
export { Typography } from '../General/@next/Typography';
2-
31
export {
42
Button,
53
OutlineButton,
64
DestructiveButton,
75
OutlineMonochromeButton,
86
PrimaryButton,
97
} from '../General/@next/Button';
10-
118
export { ButtonGroup } from '../General/@next/ButtonGroup';
9+
export { Icon } from '../General/@next/Icon';
10+
export { Typography } from '../General/@next/Typography';
11+
12+
// Utilities
13+
import * as Breakpoints from '../Utils/@next/breakpoints';
14+
import * as BorderRadius from '../Utils/@next/borderRadius';
15+
import * as Colors from '../Utils/@next/colors';
16+
import * as DropShadow from '../Utils/@next/dropShadow';
17+
import * as Fonts from '../Utils/@next/fonts';
18+
import * as Spacing from '../Utils/@next/spacing';
19+
export { Breakpoints, BorderRadius, Colors, DropShadow, Fonts, Spacing };

src/General/@next/Button/Button.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import Typography from '../Typography';
2+
import { Typography } from '../Typography';
33
import { BasicButton } from './ButtonStyle';
44

55
export type ButtonSize = 'default' | 'slim' | 'large';

src/General/@next/Button/ButtonStyle.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { CSSProperties } from 'react';
22
import styled from 'styled-components';
3-
import { Breakpoints } from '../../..';
3+
import * as Breakpoints from '../../../Utils/@next/breakpoints';
44
import { borderRadius4 } from '../../../Utils/@next/borderRadius';
55
import { Neutral } from '../../../Utils/@next/colors';
66
import {
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Meta } from '@storybook/addon-docs';
2+
import { iconNames } from './icons/icons';
3+
import { Typography } from '../Typography'
4+
import { StyledIcon, StyledItemList, StyledUnorderedList } from './IconStoriesStyles'
5+
import { Icon } from './Icon';
6+
import * as Colors from '../../../Utils/@next/colors';
7+
8+
<Meta title="General/@next/Icon" />
9+
10+
# Icons
11+
12+
<StyledUnorderedList>
13+
{iconNames.map((name) =>
14+
<StyledItemList key={name}>
15+
<StyledIcon name={name} height={28}/>
16+
<Typography variant='subtitle2'>{name}</Typography>
17+
</StyledItemList>
18+
)}
19+
</StyledUnorderedList>
20+
21+
## How to use
22+
- import NIcon component from glints-aries and pass name prop to use the specific icon
23+
24+
<div style={{ display: 'flex' }}>
25+
<StyledIcon name="ri-account-circle-fill" height={48}/>
26+
<Typography variant='subtitle2'>ri-account-circle-fill</Typography>
27+
</div>
28+
29+
```ts
30+
import { NIcon as Icon } from 'glints-aries';
31+
32+
export const MyComponent = () => (
33+
<Icon name="ri-account-circle-fill" />
34+
);
35+
```
36+
37+
### Color
38+
- you can change the color of the icon by passing the color to `fill` prop.
39+
40+
<StyledIcon name="ri-account-circle-fill" height={48} fill={Colors.Blue.Brand} />
41+
42+
```
43+
Import { Colors } from 'glints-aries'
44+
45+
<Icon name="ri-account-circle-fill" height={48} fill={Colors.Blue.Brand} />
46+
```
47+
48+
### Size
49+
- you can change the size of the icon by either passing a height or width as **props** or using **styles**.
50+
- passing at least either the `height` or `width` automatically sets the other with the same value.
51+
#### Props
52+
- Passing height or width as props
53+
```ts
54+
<Icon name="ri-account-circle-fill" height={48} />
55+
```
56+
57+
#### Style
58+
- Resizing by specifying height or width in styles
59+
```ts
60+
import { NIcon as Icon } from 'glints-aries';
61+
import styled from 'styled-components';
62+
63+
const StyledIcon = styled(Icon)`
64+
height: '48px';
65+
`;
66+
67+
export const MyComponent = () => (
68+
<StyledIcon name="ri-account-circle-fill" />
69+
);
70+
```
71+
72+
## Adding new icons
73+
1. Add svg file to `src/General/@next/Icon/icons`
74+
- make sure only viewBox is defined. Remove height, width or fill. This is to make sure the generated React component generates correct props for styles to work.
75+
2. Generate SVG React Component. Run `yarn build`. Components can be found in `src/General/@next/Icon/components`
76+
3. Update `src/General/@next/Icon/icons/icons.ts` file.
77+
- insert the new icon's name to `iconNames` in alphabetical order. Refer to Iconography naming convention.
78+
- update `iconsMappingComponent` with it's corresponding component name.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import * as React from 'react';
2+
import 'jest-styled-components';
3+
import { render } from '@testing-library/react';
4+
import '@testing-library/jest-dom/extend-expect';
5+
import * as Blue from '../../../Utils/@next/colors/blue';
6+
7+
import { Icon } from './Icon';
8+
import styled from 'styled-components';
9+
10+
describe('<Icon />', () => {
11+
const iconName = 'ri-account-circle-fill';
12+
13+
test('resize based on passed height prop', () => {
14+
const height = 24;
15+
render(<Icon name={iconName} height={height} />);
16+
17+
const svg = document.querySelector('svg');
18+
19+
expect(svg).toHaveStyle({ height });
20+
});
21+
22+
test('resize based on passed height from styled-component', () => {
23+
const customStyle = 'height: 24px';
24+
const StyledIcon = styled(Icon)`
25+
${customStyle}
26+
`;
27+
render(<StyledIcon name={iconName} />);
28+
29+
const svg = document.querySelector('svg');
30+
31+
expect(svg).toHaveStyle(customStyle);
32+
});
33+
34+
test('renders color based on fill prop', () => {
35+
render(<Icon name={iconName} height={24} fill={Blue.Brand} />);
36+
const svg = document.querySelector('svg');
37+
38+
expect(svg).toHaveAttribute('fill', Blue.Brand);
39+
});
40+
});

src/General/@next/Icon/Icon.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React, { SVGProps } from 'react';
2+
import { IconNames, iconNames, iconsMappingComponent } from './icons/icons';
3+
4+
export interface IconProps extends Omit<SVGProps<SVGSVGElement>, 'name'> {
5+
name: IconNames;
6+
}
7+
8+
export const Icon = ({ name, ...props }: IconProps) => {
9+
const IconComponent = iconsMappingComponent[name as typeof iconNames[number]];
10+
return <IconComponent {...props} />;
11+
};

0 commit comments

Comments
 (0)