Skip to content

Commit

Permalink
Merge pull request #3 from wanted-fork-fork/refactor/cva
Browse files Browse the repository at this point in the history
Refactor/cva
  • Loading branch information
ooooorobo authored Nov 25, 2024
2 parents 9a4587c + a7a5140 commit 9b540e6
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 56 deletions.
21 changes: 21 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@remix-run/serve": "^2.9.2",
"@tanstack/react-query": "^5.51.23",
"axios": "^1.7.2",
"cva": "npm:class-variance-authority@^0.7.0",
"dayjs": "^1.11.11",
"i18next": "^23.13.0",
"i18next-browser-languagedetector": "^8.0.0",
Expand Down
86 changes: 48 additions & 38 deletions src/shared/ui/Button/Button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,84 @@
align-items: center;
}

.Button:not(:disabled)[data-variant='filled'] {
&[data-color='primary'] {
background-color: var(--color-neutral-900);
color: var(--color-primary);
}
&[data-color='neutral'] {
background-color: var(--color-neutral-200);
color: #fff;
}
}
.Button:not(:disabled)[data-variant='outline'] {
&[data-color='primary'] {
border: 1px solid var(--color-primary);
color: var(--color-primary);
}
&[data-color='neutral'] {
border: 1px solid var(--color-neutral-300);
color: var(--color-neutral-900);
}
}
.Button:not(:disabled)[data-variant='ghost'] {
.Variant_Filled_Primary {
background-color: var(--color-neutral-900);
color: var(--color-primary);
}

.Variant_Filled_Neutral {
background-color: var(--color-neutral-200);
color: #fff;
}

.Variant_Outline_Primary {
border: 1px solid var(--color-primary);
color: var(--color-primary);
}

.Variant_Outline_Neutral {
border: 1px solid var(--color-neutral-300);
color: var(--color-neutral-900);
&[data-color='primary'] {
color: var(--color-primary);
}
&[data-color='neutral'] {
color: var(--color-neutral-900);
}
}

.Variant_Ghost {

}

.Variant_Ghost_Primary {
color: var(--color-primary);
}

.Variant_Ghost_Neutral {
color: var(--color-neutral-900);
}

.Button:disabled {
color: var(--color-neutral-300);
background-color: var(--color-neutral-200);

&[data-variant='ghost'] {
background-color: transparent;
}
}

.Disabled_Ghost {
background-color: transparent !important;
}

.Button[data-size='M'] {
.Size_M {
height: 48px;
border-radius: 48px;
padding: 8px 16px;
font-size: 16px;
font-weight: 600;
}
.Button[data-size='S'] {

.Size_S {
height: 32px;
border-radius: 40px;
padding: 8px 12px;
}
.Button[data-size='fit'] {

.Size_Fit {
padding-left: 0;
padding-right: 0;
}


.Button[data-width-type='fill'] {
.WidthType_Fill {
width: 100%;
}
.Button[data-width-type='hug'] {

.WidthType_Hug {
width: fit-content;
}

.Button[data-text-align='left'] {
.TextAlign_Left {
text-align: left;
}
.Button[data-text-align='right'] {

.TextAlign_Center {
text-align: center;
}

.TextAlign_Right {
text-align: right;
}

Expand Down
45 changes: 45 additions & 0 deletions src/shared/ui/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,51 @@ const meta: Meta<typeof Button> = {
export default meta;
type Story = StoryObj<typeof Button>;

export const Default: Story = {
render: () => {
const variantList = ['filled', 'outline', 'ghost'] as const;
const colorList = ['primary', 'neutral'] as const;
const widthType = ['fill', 'hug'] as const;
const size = ['fit', 'S', 'M'] as const;
return (
<div style={{ display: 'grid', gap: '20px', padding: '20px' }}>
<div style={{ display: 'grid', gap: '8px' }}>
<h3>variant</h3>
{variantList.map((v) => (
<Button key={v} variant={v} color={'primary'} widthType={'hug'}>
variant: {v}
</Button>
))}
</div>
<div style={{ display: 'grid', gap: '8px' }}>
<h3>color</h3>
{colorList.map((v) => (
<Button key={v} variant={'filled'} color={v} widthType={'hug'}>
color: {v}
</Button>
))}
</div>
<div style={{ display: 'grid', gap: '8px' }}>
<h3>widthType</h3>
{widthType.map((v) => (
<Button key={v} variant={'filled'} color={'primary'} widthType={v}>
widthType: {v}
</Button>
))}
</div>
<div style={{ display: 'grid', gap: '8px' }}>
<h3>size</h3>
{size.map((v) => (
<Button key={v} variant={'filled'} color={'primary'} widthType={'hug'} size={v}>
size: {v}
</Button>
))}
</div>
</div>
);
},
};

export const PrimaryButton: Story = {
args: {
variant: 'filled',
Expand Down
48 changes: 30 additions & 18 deletions src/shared/ui/Button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,49 @@
import { ButtonHTMLAttributes, DetailedHTMLProps, ReactNode } from 'react';
import styles from './Button.module.css';
import { cva, VariantProps } from 'cva';

const buttonStyle = cva(styles.Button, {
variants: {
widthType: { fill: styles.WidthType_Fill, hug: styles.WidthType_Hug },
textAlign: { left: styles.TextAlign_Left, center: styles.TextAlign_Center, right: styles.TextAlign_Right },
size: { M: styles.Size_M, S: styles.Size_S, fit: styles.Size_Fit },
variant: { filled: '', outline: '', ghost: '' },
color: { primary: '', neutral: '' },
},
compoundVariants: [
{ variant: 'filled', color: 'primary', className: styles.Variant_Filled_Primary },
{ variant: 'filled', color: 'neutral', className: styles.Variant_Filled_Neutral },
{ variant: 'outline', color: 'primary', className: styles.Variant_Outline_Primary },
{ variant: 'outline', color: 'neutral', className: styles.Variant_Outline_Neutral },
{ variant: 'ghost', color: 'primary', className: styles.Variant_Ghost_Primary },
{ variant: 'ghost', color: 'neutral', className: styles.Variant_Ghost_Neutral },
],
defaultVariants: {
variant: 'filled',
color: 'primary',
size: 'M',
textAlign: 'center',
},
});

type ButtonProps = DetailedHTMLProps<ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> & {
variant: 'filled' | 'outline' | 'ghost' | 'link';
color: 'primary' | 'neutral';
widthType: 'fill' | 'hug';
suffixSlot?: ReactNode;
prefixSlot?: ReactNode;
textAlign?: 'left' | 'center' | 'right';
size?: 'fit' | 'S' | 'M';
};
} & VariantProps<typeof buttonStyle>;

export const Button = ({
className = '',
variant,
color,
size = 'M',
widthType = 'fill',
textAlign = 'center',
size,
widthType,
textAlign,
suffixSlot,
prefixSlot,
children,
...props
}: ButtonProps) => (
<button
className={`${styles.Button} ${className}`}
{...props}
data-variant={variant}
data-color={color}
data-size={size}
data-width-type={widthType}
data-text-align={textAlign}
>
<button className={`${buttonStyle({ variant, color, widthType, textAlign, size })} ${className}`} {...props}>
{prefixSlot && <span className={styles.PrefixSlot}>{prefixSlot}</span>}
{children && <span className={styles.Center}>{children}</span>}
{suffixSlot && <span className={styles.SuffixSlot}>{suffixSlot}</span>}
Expand Down

0 comments on commit 9b540e6

Please sign in to comment.