Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ export default function RootLayout({
}>) {
return (
<html lang="ko">
<body className="min-h-screen bg-gray-100">
<body className="min-h-screen bg-white">
<ReactQueryProviders>
<HeaderBar />
<main className="mx-auto min-h-screen max-w-[1200px] bg-gray-50 px-4 pt-[56px] md:px-6 lg:px-10">
<main className="mx-auto min-h-screen max-w-[1200px] bg-white pt-[56px]">
{children}
</main>
</ReactQueryProviders>
Expand Down
27 changes: 18 additions & 9 deletions src/components/button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ const meta = {
export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
export const Solid: Story = {
args: {
text: '확인',
size: 'medium',
fillType: 'solid',
themeColor: 'green-normal-01',
},
};

export const Small: Story = {
export const Outline: Story = {
args: {
text: '확인',
size: 'small',
size: 'medium',
fillType: 'outline',
themeColor: 'green-light-03',
themeColor: 'green-normal-01',
},
};

Expand All @@ -35,7 +34,16 @@ export const LightSolid: Story = {
text: '확인',
size: 'modal',
fillType: 'lightSolid',
themeColor: 'gray-normal-03',
themeColor: 'green-normal-01',
lightColor: 'green-light-03',
},
};
export const Small: Story = {
args: {
text: '확인',
size: 'small',
fillType: 'outline',
themeColor: 'green-light-03',
},
};

Expand All @@ -58,10 +66,11 @@ export const Submitting: Story = {

export const Disabled: Story = {
args: {
text: '확인',
text: '생성하기',
size: 'large',
fillType: 'solid',
themeColor: 'gray-darker',
fillType: 'lightSolid',
themeColor: 'gray-dark-01',
lightColor: 'gray-normal-01',
disabled: true,
},
parameters: {
Expand Down
45 changes: 12 additions & 33 deletions src/components/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import React from 'react';
import { twMerge } from 'tailwind-merge';
import { BASE_CLASSES, COLOR_GROUPS, SIZE } from '@/constants';
import { COLOR_SCHEMES, SIZE } from '@/constants';

interface ButtonProps extends React.ComponentPropsWithoutRef<'button'> {
text: string;
size: 'large' | 'medium' | 'small' | 'modal';
fillType: 'solid' | 'outline' | 'lightSolid' | 'lightOutline';
themeColor:
| 'green-normal-01'
| 'green-light-03'
| 'gray-normal-03'
| 'gray-normal-02'
| 'gray-darker';
fillType: 'solid' | 'outline' | 'lightSolid';
themeColor: keyof typeof COLOR_SCHEMES;
lightColor?: keyof typeof COLOR_SCHEMES;
isSubmitting?: boolean;
}

Expand All @@ -20,6 +16,7 @@ export default function Button({
size,
fillType = 'solid',
themeColor = 'green-normal-01',
lightColor,
isSubmitting,
...buttonProps
}: ButtonProps) {
Expand All @@ -36,35 +33,17 @@ export default function Button({
: themeColor;

const variantClasses = (() => {
const color = COLOR_GROUPS[resolvedColor];

type TextClassType =
| 'text-green-normal-01'
| 'text-gray-darker'
| 'text-white'
| 'text-gray-dark-02';

let textClass: TextClassType = color.text;

// 배경색과 글자색이 동일한 경우 textClass를 흰색으로 덮어쓰기
if (
(fillType === 'lightSolid' || fillType === 'lightOutline') &&
color.bg.includes(color.text.replace('text-', 'bg-'))
) {
textClass = 'text-white';
}

switch (fillType) {
case 'solid':
return `${color.bg} ${BASE_CLASSES.solid}`;
return `text-gray-white ${COLOR_SCHEMES[resolvedColor]['bg']}`;
case 'outline':
return `${BASE_CLASSES.outline} ${color.text} ${color.border}`;
return `bg-gray-white border ${COLOR_SCHEMES[resolvedColor]['text']} ${COLOR_SCHEMES[resolvedColor]['border']}`;
case 'lightSolid':
return `${color.bg} ${textClass}`;
case 'lightOutline':
return `${BASE_CLASSES.lightOutline} ${color.bg} ${textClass} ${color.border}`;
default:
throw new Error(`잘못된 fillType 값입니다: ${fillType}`);
if (lightColor) {
return `${COLOR_SCHEMES[resolvedColor]['text']} ${COLOR_SCHEMES[lightColor]['bg']}`;
} else {
return `${COLOR_SCHEMES[resolvedColor]['text']} bg-gray-white`;
}
}
})();

Expand Down
123 changes: 100 additions & 23 deletions src/constants/button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,118 @@ export const SIZE = {
small: 'min-w-[120px] h-[40px] px-3 text-sm',
} as const;

export const BASE_CLASSES = {
solid: 'text-white',
outline: 'bg-white border',
lightSolid: '',
lightOutline: 'border',
} as const;

export const COLOR_GROUPS = {
'green-normal-01': {
bg: 'bg-green-normal-01',
text: 'text-green-normal-01',
border: 'border-green-normal-01',
export const COLOR_SCHEMES = {
'gray-white': {
bg: 'bg-gray-white',
text: 'text-gray-white',
border: 'border-gray-white',
},
'green-light-03': {
bg: 'bg-green-light-03',
text: 'text-green-normal-01',
border: 'border-green-normal-01',
'gray-light-01': {
bg: 'bg-gray-light-01',
text: 'text-gray-light-01',
border: 'border-gray-light-01',
},
'gray-normal-03': {
bg: 'bg-gray-normal-03',
text: 'text-gray-darker',
border: 'border-gray-darker',
'gray-light-02': {
bg: 'bg-gray-light-02',
text: 'text-gray-light-02',
border: 'border-gray-light-02',
},
'gray-normal-01': {
bg: 'bg-gray-normal-01',
text: 'text-gray-normal-01',
border: 'border-gray-normal-01',
},
'gray-normal-02': {
bg: 'bg-gray-normal-02',
text: 'text-gray-dark-02',
text: 'text-gray-normal-02',
border: 'border-gray-normal-02',
},
'gray-normal-03': {
bg: 'bg-gray-normal-03',
text: 'text-gray-normal-03',
border: 'border-gray-normal-03',
},
'gray-dark-01': {
bg: 'bg-gray-dark-01',
text: 'text-gray-dark-01',
border: 'border-gray-dark-01',
},
'gray-dark-02': {
bg: 'bg-gray-dark-02',
text: 'text-gray-dark-02',
border: 'border-gray-dark-02',
},
'gray-dark-03': {
bg: 'bg-gray-dark-03',
text: 'text-gray-dark-03',
border: 'border-gray-dark-03',
},
'gray-darker': {
bg: 'bg-gray-darker',
text: 'text-gray-darker',
border: 'border-gray-darker',
},
'gray-black': {
bg: 'bg-gray-black',
text: 'text-gray-black',
border: 'border-gray-black',
},
'green-light-01': {
bg: 'bg-green-light-01',
text: 'text-green-light-01',
border: 'border-green-light-01',
},
'green-light-02': {
bg: 'bg-green-light-02',
text: 'text-green-light-02',
border: 'border-green-light-02',
},
'green-light-03': {
bg: 'bg-green-light-03',
text: 'text-green-light-03',
border: 'border-green-light-03',
},
'green-normal-01': {
bg: 'bg-green-normal-01',
text: 'text-green-normal-01',
border: 'border-green-normal-01',
},
'green-normal-02': {
bg: 'bg-green-normal-02',
text: 'text-green-normal-02',
border: 'border-green-normal-02',
},
'green-normal-03': {
bg: 'bg-green-normal-03',
text: 'text-green-normal-03',
border: 'border-green-normal-03',
},
'green-dark-01': {
bg: 'bg-green-dark-01',
text: 'text-green-dark-01',
border: 'border-green-dark-01',
},
'green-dark-02': {
bg: 'bg-green-dark-02',
text: 'text-green-dark-02',
border: 'border-green-dark-02',
},
'green-dark-03': {
bg: 'bg-green-dark-03',
text: 'text-green-dark-03',
border: 'border-green-dark-03',
},
'green-darker': {
bg: 'bg-green-darker',
text: 'text-green-darker',
border: 'border-green-darker',
},
'blue-normal-01': {
bg: 'bg-blue-normal-01',
text: 'text-blue-normal-01',
border: 'border-blue-normal-01',
},
} as const;

export type ButtonSize = keyof typeof SIZE;
export type ButtonFillType = keyof typeof BASE_CLASSES;
export type ButtonColorGroup = keyof typeof COLOR_GROUPS;
export type ButtonColorGroup = keyof typeof COLOR_SCHEMES;
Loading