Skip to content

Commit bbbdc00

Browse files
committed
feat: add button component
1 parent 9f994f0 commit bbbdc00

File tree

8 files changed

+188
-2
lines changed

8 files changed

+188
-2
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
import { ButtonProps, ButtonStyleType, ButtonVariantType } from './types'
3+
import { BUTTON_SIZE_TO_CLASS_NAME_MAP, BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP } from './constants'
4+
import './button.scss'
5+
6+
export const getButtonDerivedClass = ({ size, variant, style }: Pick<ButtonProps, 'variant' | 'size' | 'style'>) =>
7+
`button button__${ButtonVariantType[variant]}--${ButtonStyleType[style]} ${BUTTON_SIZE_TO_CLASS_NAME_MAP[size]}`
8+
9+
const Button = ({
10+
buttonProps = {},
11+
variant = ButtonVariantType.primary,
12+
size = ComponentSizeType.large,
13+
style = ButtonStyleType.default,
14+
text,
15+
startIcon,
16+
endIcon,
17+
}: ButtonProps) => {
18+
const iconClass = `dc__no-shrink flex dc__fill-available-space ${BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP[size]}`
19+
20+
return (
21+
<button
22+
{...buttonProps}
23+
// eslint-disable-next-line react/button-has-type
24+
type={buttonProps.type || 'button'}
25+
className={`br-4 flex cursor dc__mnw-100 ${getButtonDerivedClass({ size, variant, style })} ${buttonProps.className || ''}`}
26+
>
27+
{startIcon && <span className={iconClass}>{startIcon}</span>}
28+
<span className="dc__mxw-150 dc__align-left dc__truncate">{text}</span>
29+
{endIcon && <span className={iconClass}>{endIcon}</span>}
30+
</button>
31+
)
32+
}
33+
34+
export default Button
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
@mixin button-variant-styles($background, $text-color, $border-color) {
2+
background: $background;
3+
color: $text-color;
4+
border: 1px solid $border-color;
5+
}
6+
7+
.button {
8+
// Reset the default styles
9+
background: none;
10+
color: inherit;
11+
border: none;
12+
outline: inherit;
13+
14+
&:focus,
15+
&:active,
16+
&:hover {
17+
outline: unset;
18+
// border: unset;
19+
}
20+
21+
&__primary {
22+
$border-color: transparent;
23+
$text-color: var(--N0);
24+
25+
&--default {
26+
@include button-variant-styles(var(--B500), $text-color, $border-color);
27+
}
28+
29+
&--negative {
30+
@include button-variant-styles(var(--R500), $text-color, $border-color);
31+
}
32+
33+
&--positive {
34+
@include button-variant-styles(var(--G500), $text-color, $border-color);
35+
}
36+
37+
&--warning {
38+
$text-color: var(--N900);
39+
40+
@include button-variant-styles(var(--Y500), var(--N900), $border-color);
41+
}
42+
43+
&--neutral {
44+
@include button-variant-styles(var(--N500), $text-color, $border-color);
45+
}
46+
}
47+
48+
&__secondary {
49+
$background: var(--N0);
50+
$border-color: var(--N200);
51+
52+
&--default {
53+
@include button-variant-styles($background, var(--B500), $border-color);
54+
}
55+
56+
&--negative {
57+
@include button-variant-styles($background, var(--R600), $border-color);
58+
}
59+
60+
&--positive {
61+
@include button-variant-styles($background, var(--G600), $border-color);
62+
}
63+
64+
&--warning {
65+
@include button-variant-styles($background, var(--Y700), $border-color);
66+
}
67+
68+
&--neutral {
69+
@include button-variant-styles($background, var(--N700), $border-color);
70+
}
71+
}
72+
73+
&__text,
74+
&__link {
75+
$background: transparent;
76+
$border-color: transparent;
77+
78+
&--default {
79+
@include button-variant-styles($background, var(--B500), $border-color);
80+
}
81+
82+
&--negative {
83+
@include button-variant-styles($background, var(--R600), $border-color);
84+
}
85+
86+
&--positive {
87+
@include button-variant-styles($background, var(--G600), $border-color);
88+
}
89+
90+
&--warning {
91+
@include button-variant-styles($background, var(--Y700), $border-color);
92+
}
93+
94+
&--neutral {
95+
@include button-variant-styles($background, var(--N700), $border-color);
96+
}
97+
}
98+
99+
&__link {
100+
padding: 0;
101+
}
102+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
import { ButtonProps } from './types'
3+
4+
export const BUTTON_SIZE_TO_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
5+
[ComponentSizeType.xs]: 'px-9 py-1 fs-14 lh-20 fw-6 dc__gap-6',
6+
[ComponentSizeType.small]: 'px-9 py-3 fs-12 lh-20 fw-6 dc__gap-6',
7+
[ComponentSizeType.medium]: 'px-11 py-5 fs-13 lh-20 fw-6 dc__gap-8',
8+
[ComponentSizeType.large]: 'px-13 py-7 fs-13 lh-20 fw-6 dc__gap-10',
9+
[ComponentSizeType.xl]: 'px-15 py-9 fs-14 lh-20 fw-6 dc__gap-12',
10+
}
11+
12+
export const BUTTON_SIZE_TO_ICON_CLASS_NAME_MAP: Record<ButtonProps['size'], string> = {
13+
[ComponentSizeType.xs]: 'icon-dim-12',
14+
[ComponentSizeType.small]: 'icon-dim-12',
15+
[ComponentSizeType.medium]: 'icon-dim-16',
16+
[ComponentSizeType.large]: 'icon-dim-16',
17+
[ComponentSizeType.xl]: 'icon-dim-20',
18+
}

src/Shared/Components/Button/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default as Button } from './Button.component'
2+
export type { ButtonProps, ButtonStyleType, ButtonVariantType } from './types'

src/Shared/Components/Button/types.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { ComponentSizeType } from '@Shared/constants'
2+
import { ButtonHTMLAttributes, ReactElement } from 'react'
3+
4+
export enum ButtonVariantType {
5+
primary = 'primary',
6+
secondary = 'secondary',
7+
text = 'text',
8+
link = 'link',
9+
}
10+
11+
export enum ButtonStyleType {
12+
default = 'default',
13+
negative = 'negative',
14+
positive = 'positive',
15+
warning = 'warning',
16+
neutral = 'neutral',
17+
}
18+
19+
export interface ButtonProps {
20+
buttonProps?: ButtonHTMLAttributes<HTMLButtonElement>
21+
variant?: ButtonVariantType
22+
size?: ComponentSizeType
23+
style?: ButtonStyleType
24+
text: string
25+
startIcon?: ReactElement
26+
endIcon?: ReactElement
27+
}

src/Shared/Components/ButtonWithLoader/ButtonWithLoader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import React, { Component } from 'react'
2020
import { Progressing } from '../../../Common'
2121

22-
export interface ButtonProps {
22+
export interface ButtonWithLoaderProps {
2323
disabled?: boolean
2424
rootClassName: string
2525
isLoading: boolean
@@ -29,7 +29,7 @@ export interface ButtonProps {
2929
type?: 'submit' | 'reset' | 'button'
3030
}
3131

32-
export class ButtonWithLoader extends Component<ButtonProps> {
32+
export class ButtonWithLoader extends Component<ButtonWithLoaderProps> {
3333
constructor(props) {
3434
super(props)
3535
this.clickHandler = this.clickHandler.bind(this)

src/Shared/Components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,4 @@ export * from './DetectBottom'
5555
export * from './EditImageFormField'
5656
export * from './Collapse'
5757
export * from './FilterButton'
58+
export * from './Button'

src/Shared/constants.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,9 +452,11 @@ export const ANSI_UP_REGEX = /\x1B\[.*?m/g
452452
* Size variants for components
453453
*/
454454
export enum ComponentSizeType {
455+
xs = 'xs',
455456
small = 'small',
456457
medium = 'medium',
457458
large = 'large',
459+
xl = 'xl',
458460
}
459461

460462
export const POP_UP_MENU_MODAL_ID = 'popup'

0 commit comments

Comments
 (0)