-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(checkbox): Checkbox 컴포넌트 구현 #106
Changes from all commits
a6a2a04
5fda386
3f35e13
35f9f4c
78c4bf2
3d41c3c
991cf2b
9fbce40
630d3ee
b1925b8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { StorybookConfig } from '@storybook/react-vite'; | ||
|
||
export default { | ||
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], | ||
addons: [ | ||
'@storybook/addon-onboarding', | ||
'@storybook/addon-links', | ||
'@storybook/addon-essentials', | ||
'@storybook/addon-interactions', | ||
], | ||
framework: { | ||
name: '@storybook/react-vite', | ||
options: {}, | ||
}, | ||
} satisfies StorybookConfig; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { Preview } from '@storybook/react'; | ||
import 'sanitize.css'; | ||
|
||
const preview: Preview = { | ||
parameters: { | ||
actions: { argTypesRegex: '^on[A-Z].*' }, | ||
controls: { | ||
matchers: { | ||
color: /(background|color)$/i, | ||
date: /Date$/i, | ||
}, | ||
}, | ||
}, | ||
}; | ||
|
||
export default preview; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
declare module '*.module.css'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
{ | ||
"name": "@sipe-team/checkbox", | ||
"description": "Checkbox for Sipe Design System", | ||
"version": "0.0.0", | ||
"license": "MIT", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/sipe-team/3-2_side" | ||
}, | ||
"type": "module", | ||
"exports": "./src/index.ts", | ||
"files": ["dist"], | ||
"scripts": { | ||
"build": "tsup", | ||
"build:storybook": "storybook build", | ||
"dev:storybook": "storybook dev -p 6006", | ||
"lint:biome": "pnpm exec biome lint", | ||
"lint:eslint": "pnpm exec eslint --flag unstable_ts_config", | ||
"test": "vitest", | ||
"typecheck": "tsc", | ||
"prepack": "pnpm run build" | ||
}, | ||
"dependencies": { | ||
"@radix-ui/react-checkbox": "^1.0.4", | ||
"@sipe-team/tokens": "workspace:^", | ||
"@sipe-team/typography": "workspace:^", | ||
"clsx": "^2.1.1", | ||
"lucide-react": "^0.344.0" | ||
}, | ||
"devDependencies": { | ||
"@storybook/addon-essentials": "catalog:", | ||
"@storybook/addon-interactions": "catalog:", | ||
"@storybook/addon-links": "catalog:", | ||
"@storybook/blocks": "catalog:", | ||
"@storybook/react": "catalog:", | ||
"@storybook/react-vite": "catalog:", | ||
"@storybook/test": "catalog:", | ||
"@testing-library/jest-dom": "catalog:", | ||
"@testing-library/react": "catalog:", | ||
"@testing-library/user-event": "^14.5.2", | ||
"@types/react": "^18.3.12", | ||
"happy-dom": "catalog:", | ||
"react": "^18.3.1", | ||
"storybook": "catalog:", | ||
"tsup": "catalog:", | ||
"typescript": "catalog:", | ||
"vitest": "catalog:" | ||
}, | ||
"peerDependencies": { | ||
"react": ">= 18" | ||
}, | ||
"publishConfig": { | ||
"access": "public", | ||
"registry": "https://npm.pkg.github.com", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
}, | ||
"./styles.css": "./dist/index.css" | ||
} | ||
}, | ||
"sideEffects": false | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
.root { | ||
all: unset; | ||
display: flex; | ||
align-items: center; | ||
gap: var(--padding); | ||
margin: 4px; | ||
} | ||
|
||
.label { | ||
display: flex; | ||
align-items: center; | ||
gap: var(--padding); | ||
} | ||
|
||
.checkbox { | ||
all: unset; | ||
width: var(--size); | ||
height: var(--size); | ||
border-radius: 4px; | ||
border: 2px solid #a1a1aa; | ||
background-color: #ffffff; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
cursor: pointer; | ||
} | ||
|
||
.checkbox:focus-visible { | ||
border-color: #06b6d4; | ||
outline: none; | ||
} | ||
|
||
.checkbox[data-disabled] { | ||
cursor: not-allowed; | ||
opacity: 0.4; | ||
} | ||
|
||
.checkbox[data-state="checked"] { | ||
border-color: #00ffff; | ||
background-color: #00ffff; | ||
} | ||
|
||
.indicator { | ||
color: #ffffff; | ||
height: var(--indicator-size); | ||
width: var(--indicator-size); | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
line-height: 0; | ||
} | ||
|
||
.group { | ||
display: flex; | ||
flex-direction: column; | ||
gap: 8px; | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,102 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import type { Meta, StoryObj } from '@storybook/react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { Checkbox, CheckboxGroup } from './Checkbox'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const meta = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title: 'Components/Checkbox', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
component: Checkbox, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
parameters: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
layout: 'centered', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
argTypes: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
size: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description: '체크박스의 크기를 지정합니다', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
options: ['sm', 'md', 'lg'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
control: { type: 'radio' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
disabled: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description: '체크박스의 비활성화 상태를 지정합니다', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
control: { type: 'boolean' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checked: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description: '체크박스의 선택 상태를 지정합니다', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
control: { type: 'boolean' }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
description: '체크박스의 레이블을 지정합니다', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
control: 'text', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+11
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 접근성 속성에 대한 설명이 필요합니다. argTypes에 aria-label과 같은 접근성 속성에 대한 설명이 누락되어 있습니다. 다음과 같이 접근성 관련 argTypes를 추가해주세요: argTypes: {
+ 'aria-label': {
+ description: '스크린 리더를 위한 레이블을 지정합니다',
+ control: 'text',
+ },
+ 'aria-describedby': {
+ description: '스크린 리더를 위한 추가 설명을 지정합니다',
+ control: 'text',
+ },
size: { 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} satisfies Meta<typeof Checkbox>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default meta; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type Story = StoryObj<typeof meta>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const Basic: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: '체크박스', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
size: 'md', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const Sizes: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: '체크박스', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: (args) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} size="sm" label="Small" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} size="md" label="Medium (Default)" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} size="lg" label="Large" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const States: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: '체크박스', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: (args) => ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} label="Unchecked (Default)" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} label="Checked" defaultChecked /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} label="Disabled" disabled /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} label="Disabled & Checked" disabled defaultChecked /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+56
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 키보드 상호작용 예제가 필요합니다. 접근성을 위해 키보드 상호작용을 보여주는 스토리를 추가하면 좋을 것 같습니다. 다음과 같은 키보드 인터랙션 스토리를 추가해보세요: export const KeyboardInteraction: Story = {
args: {
label: '키보드 상호작용',
},
parameters: {
docs: {
description: {
story: '스페이스바 또는 엔터 키를 사용하여 체크박스를 토글할 수 있습니다.',
},
},
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const checkbox = canvas.getByRole('checkbox');
// 포커스
await userEvent.tab();
// 토글
await userEvent.keyboard('[Space]');
},
}; |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const Controlled: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
label: 'Controlled Checkbox', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: (args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [checked, setChecked] = useState<boolean | 'indeterminate'>(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{...args} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
checked={checked} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
onCheckedChange={(state) => setChecked(state)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const Group: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
size: 'md', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
render: (args) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const [selected, setSelected] = useState<string[]>([]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<CheckboxGroup value={selected} onChange={setSelected}> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} value="apple" label="사과" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} value="banana" label="바나나" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<Checkbox {...args} value="orange" label="오렌지" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</CheckboxGroup> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { render, screen } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { expect, test } from 'vitest'; | ||
import { useState } from 'react'; | ||
import { Checkbox, CheckboxGroup } from './Checkbox'; | ||
|
||
test('체크박스를 클릭하면 체크 상태가 활성화된다.', async () => { | ||
const user = userEvent.setup(); | ||
render(<Checkbox label="테스트" />); | ||
|
||
const checkbox = screen.getByRole('checkbox', { name: '테스트' }); | ||
expect(checkbox).not.toBeChecked(); | ||
|
||
await user.click(checkbox); | ||
expect(checkbox).toBeChecked(); | ||
}); | ||
|
||
test('disabled 상태의 체크박스를 클릭해도 체크 상태가 바뀌지 않는다.', async () => { | ||
const user = userEvent.setup(); | ||
render(<Checkbox disabled label="테스트" />); | ||
|
||
const checkbox = screen.getByRole('checkbox', { name: '테스트' }); | ||
expect(checkbox).toBeDisabled(); | ||
|
||
await user.click(checkbox); | ||
expect(checkbox).not.toBeChecked(); | ||
}); | ||
|
||
test('size를 주입하지 않으면 기본값 md로 설정된다.', () => { | ||
render(<Checkbox label="테스트" />); | ||
|
||
const checkbox = screen.getByRole('checkbox'); | ||
expect(checkbox).toHaveStyle({ width: '20px', height: '20px' }); | ||
}); | ||
|
||
test.each([ | ||
{ size: 'sm', expected: '16px' }, | ||
{ size: 'md', expected: '20px' }, | ||
{ size: 'lg', expected: '24px' }, | ||
] as const)('size가 $size일 때 체크박스 크기가 $expected로 설정된다.', ({ size, expected }) => { | ||
render(<Checkbox size={size} label="테스트" />); | ||
|
||
const checkbox = screen.getByRole('checkbox'); | ||
expect(checkbox).toHaveStyle({ width: expected, height: expected }); | ||
}); | ||
|
||
test('체크박스 그룹에서 여러 항목을 선택할 수 있다.', async () => { | ||
const user = userEvent.setup(); | ||
|
||
const TestComponent = () => { | ||
const [selected, setSelected] = useState<string[]>([]); | ||
return ( | ||
<CheckboxGroup value={selected} onChange={setSelected}> | ||
<Checkbox value="1" label="항목 1" /> | ||
<Checkbox value="2" label="항목 2" /> | ||
<Checkbox value="3" label="항목 3" /> | ||
</CheckboxGroup> | ||
); | ||
}; | ||
|
||
render(<TestComponent />); | ||
|
||
const checkbox1 = screen.getByRole('checkbox', { name: '항목 1' }); | ||
const checkbox2 = screen.getByRole('checkbox', { name: '항목 2' }); | ||
|
||
await user.click(checkbox1); | ||
expect(checkbox1).toBeChecked(); | ||
expect(checkbox2).not.toBeChecked(); | ||
|
||
await user.click(checkbox2); | ||
expect(checkbox1).toBeChecked(); | ||
expect(checkbox2).toBeChecked(); | ||
|
||
await user.click(checkbox1); | ||
expect(checkbox1).not.toBeChecked(); | ||
expect(checkbox2).toBeChecked(); | ||
}); | ||
|
||
test('체크박스 그룹에서 value prop으로 선택된 항목을 제어할 수 있다.', async () => { | ||
const selectedValues = ['1', '3']; | ||
|
||
render( | ||
<CheckboxGroup value={selectedValues}> | ||
<Checkbox value="1" label="항목 1" /> | ||
<Checkbox value="2" label="항목 2" /> | ||
<Checkbox value="3" label="항목 3" /> | ||
</CheckboxGroup> | ||
); | ||
|
||
const checkbox1 = screen.getByRole('checkbox', { name: '항목 1' }); | ||
const checkbox2 = screen.getByRole('checkbox', { name: '항목 2' }); | ||
const checkbox3 = screen.getByRole('checkbox', { name: '항목 3' }); | ||
|
||
expect(checkbox1).toBeChecked(); | ||
expect(checkbox2).not.toBeChecked(); | ||
expect(checkbox3).toBeChecked(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
접근성 애드온 추가가 필요합니다.
체크박스는 접근성이 매우 중요한 컴포넌트입니다. 접근성 테스트를 위한 애드온을 추가하면 좋을 것 같습니다.
다음과 같이 a11y 애드온을 추가해주세요:
addons: [ '@storybook/addon-onboarding', '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', + '@storybook/addon-a11y', ],
📝 Committable suggestion