Skip to content

Commit 7769999

Browse files
committed
Added basic buttons
1 parent 0b884d1 commit 7769999

File tree

10 files changed

+484
-87
lines changed

10 files changed

+484
-87
lines changed

__tests__/Button.test.tsx

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { shallow } from 'enzyme';
2+
import React from 'react';
3+
import Button from '@/components/Button';
4+
import { Variant } from '@/components';
5+
6+
describe('Button test', () => {
7+
it('should render button', () => {
8+
const container = shallow(
9+
<Button
10+
variant={Variant.PRIMARY}
11+
>
12+
Hello world
13+
</Button>
14+
);
15+
16+
expect(container.find('button').length).toBe(1);
17+
});
18+
19+
it('should render button as link', () => {
20+
const container = shallow(
21+
<Button
22+
as="a"
23+
variant={Variant.PRIMARY}
24+
>
25+
Hello world
26+
</Button>
27+
);
28+
29+
expect(container.find('a').length).toBe(1);
30+
});
31+
32+
it('should render block button', () => {
33+
const container = shallow(
34+
<Button
35+
variant={Variant.PRIMARY}
36+
block
37+
>
38+
Hello world
39+
</Button>
40+
);
41+
42+
expect(container.find('button').hasClass('btn-block')).toBeTruthy();
43+
});
44+
45+
it('should render small button', () => {
46+
const container = shallow(
47+
<Button
48+
variant={Variant.PRIMARY}
49+
small
50+
>
51+
Hello world
52+
</Button>
53+
);
54+
55+
expect(container.find('button').hasClass('btn-small')).toBeTruthy();
56+
});
57+
58+
it('should render button with icon left', () => {
59+
const container = shallow(
60+
<Button
61+
variant={Variant.PRIMARY}
62+
iconLeft={<i>icon</i>}
63+
>
64+
Hello world
65+
</Button>
66+
);
67+
68+
expect(container.find('button').find('i').text()).toContain('icon');
69+
});
70+
71+
it('should render button with icon left', () => {
72+
const container = shallow(
73+
<Button
74+
variant={Variant.PRIMARY}
75+
iconRight={<i>icon</i>}
76+
>
77+
Hello world
78+
</Button>
79+
);
80+
81+
expect(container.find('button').find('i').text()).toContain('icon');
82+
});
83+
});

package-lock.json

Lines changed: 35 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
"webpack-dev-server": "^3.11.0"
4141
},
4242
"dependencies": {
43+
"@fortawesome/fontawesome-free": "^5.15.1",
44+
"@fortawesome/fontawesome-svg-core": "^1.2.32",
45+
"@fortawesome/free-regular-svg-icons": "^5.15.1",
46+
"@fortawesome/react-fontawesome": "^0.1.11",
4347
"clsx": "^1.1.1",
4448
"react": "^17.0.1"
4549
}

src/components/Button/index.tsx

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import * as React from 'react';
2+
import clsx from 'clsx';
3+
import PropTypes from 'prop-types';
4+
import { Variant } from '@/components';
5+
6+
export type ButtonComponentTypes = 'button' | 'a';
7+
8+
export interface ButtonProps extends React.HTMLAttributes<HTMLElement> {
9+
as?: ButtonComponentTypes;
10+
variant: Variant | string;
11+
iconLeft?: React.ReactElement;
12+
iconRight?: React.ReactElement;
13+
block?: boolean;
14+
small?: boolean;
15+
}
16+
17+
const Button = React.forwardRef<HTMLElement, ButtonProps>((
18+
{
19+
as: Component = 'button',
20+
children,
21+
className,
22+
variant,
23+
iconLeft,
24+
iconRight,
25+
block,
26+
small,
27+
...rest
28+
},
29+
ref
30+
): React.ReactElement => {
31+
return (
32+
<Component
33+
ref={ref as React.RefObject<any>}
34+
className={clsx(
35+
'btn',
36+
`btn-${variant}`,
37+
block &&'btn-block',
38+
small && 'btn-small',
39+
className
40+
)}
41+
{...rest}
42+
>
43+
{iconLeft && (
44+
<div className="icon-container icon-left">
45+
{iconLeft}
46+
</div>
47+
)}
48+
<span>{children}</span>
49+
{iconRight && (
50+
<div className="icon-container icon-right">
51+
{iconRight}
52+
</div>
53+
)}
54+
</Component>
55+
);
56+
});
57+
58+
Button.displayName = 'Button';
59+
Button.propTypes = {
60+
as: PropTypes.oneOf(['button', 'a']),
61+
children: PropTypes.node.isRequired,
62+
className: PropTypes.string,
63+
variant: PropTypes.string.isRequired,
64+
iconLeft: PropTypes.element,
65+
iconRight: PropTypes.element,
66+
block: PropTypes.bool,
67+
small: PropTypes.bool
68+
};
69+
70+
export default Button;

src/components/utils/Variant.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,15 @@
11
export enum Variant {
2+
PRIMARY = 'primary',
3+
PRIMARY_GHOST = 'primary-ghost',
4+
SECONDARY = 'secondary',
5+
DANGER = 'danger',
6+
DANGER_GHOST = 'danger-ghost'
27
}
8+
9+
export const variantList: string[] = [
10+
'primary',
11+
'primary-ghost',
12+
'secondary',
13+
'danger',
14+
'danger-ghost'
15+
];

src/style/base/_base.scss

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
html {
22
font-size: var(--base-font-size);
3+
-moz-osx-font-smoothing: grayscale;
4+
-webkit-font-smoothing: antialiased;
35
}
46

57
body {
@@ -9,4 +11,5 @@ body {
911
font: {
1012
family: var(--base-font-family);
1113
}
14+
line-height: 1.2rem;
1215
}

0 commit comments

Comments
 (0)