diff --git a/src/components/chip/Chip.stories.tsx b/src/components/chip/Chip.stories.tsx index ee2229b9..65e6d013 100644 --- a/src/components/chip/Chip.stories.tsx +++ b/src/components/chip/Chip.stories.tsx @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import Chip from './Chip'; const meta = { - title: 'Components/Chip', + title: 'Components/Chip/Base', component: Chip, parameters: { layout: 'centered', @@ -29,7 +29,7 @@ export const RoundedLight: Story = { export const SquareOutlined: Story = { args: { text: '오프라인', - variant: 'square-light', + variant: 'square-outlined', }, }; @@ -54,13 +54,13 @@ export const AllStates: Story = {
- +
- +
diff --git a/src/components/chip/Chip.test.tsx b/src/components/chip/Chip.test.tsx index cb924c0a..0611475d 100644 --- a/src/components/chip/Chip.test.tsx +++ b/src/components/chip/Chip.test.tsx @@ -2,7 +2,7 @@ import Chip from '@/components/chip/Chip'; import '@testing-library/jest-dom'; import { render, screen } from '@testing-library/react'; -describe('TextChip', () => { +describe('Chip', () => { it('텍스트가 올바르게 렌더링되어야 한다', () => { render(); const chip = screen.getByText('테스트'); diff --git a/src/components/chip/Chip.tsx b/src/components/chip/Chip.tsx index 9e3e3a03..af5810ef 100644 --- a/src/components/chip/Chip.tsx +++ b/src/components/chip/Chip.tsx @@ -1,11 +1,13 @@ import { twMerge } from 'tailwind-merge'; const CHIP_VARIANTS = { - 'rounded-filled': 'rounded-full bg-green-light-02 text-green-dark-01', - 'rounded-light': 'rounded-full bg-green-normal-01 text-gray-white', - 'square-light': - 'rounded border border-gray-normal-02 bg-gray-light-01 text-gray-dark-01', - 'square-filled': 'rounded bg-green-dark-01 text-gray-dark-01', + 'rounded-filled': + 'rounded-full bg-green-light-02 text-green-dark-01 font-semibold', + 'rounded-light': + 'rounded-full bg-green-normal-01 text-gray-white font-semibold', + 'square-outlined': + 'rounded-md border border-green-normal-01 bg-gray-white text-green-normal-01', + 'square-filled': 'rounded-md bg-green-normal-01 text-gray-white px-2', } as const; type ChipVariant = keyof typeof CHIP_VARIANTS; @@ -24,7 +26,7 @@ function Chip({ className, }: ChipProps) { const baseStyles = - 'inline-flex items-center justify-center px-2.5 py-1 text-sm font-semibold'; + 'inline-flex items-center justify-center px-2.5 py-1 text-sm font-medium'; const combinedClassName = twMerge( baseStyles, diff --git a/src/components/chip/club-chip/ClubChip.stories.tsx b/src/components/chip/club-chip/ClubChip.stories.tsx new file mode 100644 index 00000000..74f41fcc --- /dev/null +++ b/src/components/chip/club-chip/ClubChip.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import ClubChip from './ClubChip'; + +const meta = { + title: 'Components/Chip/ClubChip', + component: ClubChip, + parameters: { + layout: 'centered', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Completed: Story = { + args: { + variant: 'completed', + }, +}; + +export const Scheduled: Story = { + args: { + variant: 'scheduled', + }, +}; + +export const Pending: Story = { + args: { + variant: 'pending', + }, +}; + +export const Confirmed: Story = { + args: { + variant: 'confirmed', + }, +}; + +export const AllStates: Story = { + render: () => ( +
+ + + + +
+ ), +}; diff --git a/src/components/chip/club-chip/ClubChip.test.tsx b/src/components/chip/club-chip/ClubChip.test.tsx new file mode 100644 index 00000000..f511a9a2 --- /dev/null +++ b/src/components/chip/club-chip/ClubChip.test.tsx @@ -0,0 +1,29 @@ +import ClubChip from './ClubChip'; +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; + +describe('ClubChip', () => { + it('variant에 따라 올바른 텍스트가 렌더링되어야 한다', () => { + render(); + expect(screen.getByText('참여완료')).toBeInTheDocument(); + }); + + it('모든 variant가 올바르게 렌더링되어야 한다', () => { + const { rerender } = render(); + expect(screen.getByText('참여완료')).toBeInTheDocument(); + + rerender(); + expect(screen.getByText('참여예정')).toBeInTheDocument(); + + rerender(); + expect(screen.getByText('개설대기')).toBeInTheDocument(); + + rerender(); + expect(screen.getByText('개설확정')).toBeInTheDocument(); + }); + + it('className prop으로 스타일을 오버라이드할 수 있어야 한다', () => { + render(); + expect(screen.getByText('참여완료')).toHaveClass('custom-class'); + }); +}); diff --git a/src/components/chip/club-chip/ClubChip.tsx b/src/components/chip/club-chip/ClubChip.tsx new file mode 100644 index 00000000..500baa9e --- /dev/null +++ b/src/components/chip/club-chip/ClubChip.tsx @@ -0,0 +1,54 @@ +import Chip from '../Chip'; +import { twMerge } from 'tailwind-merge'; + +type ClubChipVariant = 'completed' | 'scheduled' | 'pending' | 'confirmed'; + +const CLUB_CHIP_TEXT = { + completed: '참여완료', + scheduled: '참여예정', + pending: '개설대기', + confirmed: '개설확정', +} as const; + +interface ClubChipProps { + variant: ClubChipVariant; + className?: string; +} + +function ClubChip({ variant, className }: ClubChipProps) { + const getChipVariant = () => { + switch (variant) { + case 'completed': + return 'square-filled'; + case 'scheduled': + return 'square-filled'; + case 'pending': + return 'square-outlined'; + case 'confirmed': + return 'square-filled'; + } + }; + + const getCustomClassName = () => { + switch (variant) { + case 'completed': + return 'bg-gray-normal-01 text-gray-dark-02'; + case 'scheduled': + return 'bg-green-normal-01 text-gray-white'; + case 'pending': + return 'border-blue-normal-01 text-blue-normal-01'; + case 'confirmed': + return 'bg-blue-normal-01 text-gray-white'; + } + }; + + return ( + + ); +} + +export default ClubChip; diff --git a/tailwind.config.ts b/tailwind.config.ts index ec01778d..c017cc5e 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -37,6 +37,9 @@ const config: Config = { 'dark-03': '#004c41', darker: '#003b33', }, + blue: { + 'normal-01': '#007AFF', + }, }, }, },