-
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
[Feature] SwitchGroup 컴포넌트 구현 #32
Closed
Closed
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
ab68c96
chore: 스위치 컴포넌트 내부적으로 id 사용하도록 수정
ghdtjgus76 07fa5aa
feat: SwitchGroup 컴포넌트 구현
ghdtjgus76 a8d1f03
chore: Switch 컴포넌트 스토리 argTypes 수정
ghdtjgus76 ba67822
chore: init 함수 반환 타입 지정
ghdtjgus76 96c6824
feat: SwitchGroup 스토리 작성
ghdtjgus76 5d2dfc7
chore: switch 테스트 description 변경
ghdtjgus76 697d722
test: SwitchGroup 컴포넌트 테스트 작성
ghdtjgus76 abe4700
chore: 빌드 관련 설정 변경
ghdtjgus76 725b045
chore: SwitchGroup 컴포넌트 jsdoc 수정
ghdtjgus76 78eb600
chore: 테스트, 스토리북 코드 수정
ghdtjgus76 2f4df14
chore: 불필요한 label htmlFor, input id 속성 삭제
ghdtjgus76 40f171a
Merge branch 'main' into feature/switch-group-component
ghdtjgus76 0bbed6c
chore: wow-ui 불필요한 export 속성 삭제
ghdtjgus76 aeb8af1
chore: Switch 컴포넌트에 disabled 속성 추가 및 cursor default로 변경
ghdtjgus76 24fd4f1
chore: SwtichGroup 컴포넌트 children type 변경
ghdtjgus76 9f241d7
chore: Switch, SwitchGroup 컴포넌트 gap space 토큰 활용하도록 변경
ghdtjgus76 d907911
refactor: Switch 컴포넌트에 memo 사용하도록 로직 수정
ghdtjgus76 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
95 changes: 95 additions & 0 deletions
95
packages/wow-ui/src/components/SwitchGroup/SwitchGroup.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,95 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
import type { Meta, StoryObj } from "@storybook/react"; | ||||||||||||||||||||||||||||||||||||||||||||||
import { useState } from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
import Switch from "@/components/Switch"; | ||||||||||||||||||||||||||||||||||||||||||||||
import SwitchGroup from "@/components/SwitchGroup"; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
const meta = { | ||||||||||||||||||||||||||||||||||||||||||||||
title: "UI/SwitchGroup", | ||||||||||||||||||||||||||||||||||||||||||||||
component: SwitchGroup, | ||||||||||||||||||||||||||||||||||||||||||||||
tags: ["autodocs"], | ||||||||||||||||||||||||||||||||||||||||||||||
parameters: { | ||||||||||||||||||||||||||||||||||||||||||||||
componentSubtitle: "스위치 그룹 컴포넌트", | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
argTypes: { | ||||||||||||||||||||||||||||||||||||||||||||||
children: { | ||||||||||||||||||||||||||||||||||||||||||||||
description: "렌더링할 자식 요소를 나타냅니다.", | ||||||||||||||||||||||||||||||||||||||||||||||
table: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: { summary: "ReactNode" }, | ||||||||||||||||||||||||||||||||||||||||||||||
defaultValue: { summary: null }, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
control: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: "function", | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
type: { | ||||||||||||||||||||||||||||||||||||||||||||||
name: "function", | ||||||||||||||||||||||||||||||||||||||||||||||
required: true, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
value: { | ||||||||||||||||||||||||||||||||||||||||||||||
description: "value는 외부에서 제어할 활성 상태를 나타냅니다.", | ||||||||||||||||||||||||||||||||||||||||||||||
table: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: { summary: "boolean[]" }, | ||||||||||||||||||||||||||||||||||||||||||||||
defaultValue: { summary: null }, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
control: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: "array", | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
onChange: { | ||||||||||||||||||||||||||||||||||||||||||||||
description: "외부 활성 상태가 변경될 때 호출될 콜백 함수를 나타냅니다.", | ||||||||||||||||||||||||||||||||||||||||||||||
table: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: { summary: "(index: number) => void" }, | ||||||||||||||||||||||||||||||||||||||||||||||
defaultValue: { summary: null }, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
control: { | ||||||||||||||||||||||||||||||||||||||||||||||
type: "function", | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
} satisfies Meta<typeof SwitchGroup>; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
export default meta; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
type Story = StoryObj<typeof meta>; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
export const Primary: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||
children: ( | ||||||||||||||||||||||||||||||||||||||||||||||
<> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch text="Switch 1" /> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch isDisabled text="Switch 2" /> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch text="Switch 3" /> | ||||||||||||||||||||||||||||||||||||||||||||||
</> | ||||||||||||||||||||||||||||||||||||||||||||||
), | ||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
const ControlledSwitchGroup = () => { | ||||||||||||||||||||||||||||||||||||||||||||||
const [isCheckedState, setIsCheckedState] = useState<boolean[]>([ | ||||||||||||||||||||||||||||||||||||||||||||||
false, | ||||||||||||||||||||||||||||||||||||||||||||||
true, | ||||||||||||||||||||||||||||||||||||||||||||||
false, | ||||||||||||||||||||||||||||||||||||||||||||||
]); | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
const handleChange = (index: number) => { | ||||||||||||||||||||||||||||||||||||||||||||||
setIsCheckedState((prev) => | ||||||||||||||||||||||||||||||||||||||||||||||
prev.map((prevState, i) => (index === i ? !prevState : prevState)) | ||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||
<SwitchGroup value={isCheckedState} onChange={handleChange}> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch isDisabled text="Switch 1" /> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch text="Switch 2" /> | ||||||||||||||||||||||||||||||||||||||||||||||
<Switch text="Switch 3" /> | ||||||||||||||||||||||||||||||||||||||||||||||
</SwitchGroup> | ||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||
export const ControlledState: Story = { | ||||||||||||||||||||||||||||||||||||||||||||||
render: () => <ControlledSwitchGroup />, | ||||||||||||||||||||||||||||||||||||||||||||||
args: { | ||||||||||||||||||||||||||||||||||||||||||||||
children: null, | ||||||||||||||||||||||||||||||||||||||||||||||
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. p2;
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||
}; |
110 changes: 110 additions & 0 deletions
110
packages/wow-ui/src/components/SwitchGroup/SwitchGroup.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import type { RenderResult } from "@testing-library/react"; | ||
import { render, waitFor } from "@testing-library/react"; | ||
import fireEvent from "@testing-library/user-event"; | ||
|
||
import Switch from "@/components/Switch"; | ||
import SwitchGroup from "@/components/SwitchGroup"; | ||
|
||
describe("switch group", () => { | ||
let rendered: RenderResult; | ||
|
||
beforeEach(() => { | ||
rendered = render( | ||
<SwitchGroup> | ||
<Switch text="Switch 1" /> | ||
<Switch isDisabled text="Switch 2" /> | ||
<Switch text="Switch 3" /> | ||
</SwitchGroup> | ||
); | ||
}); | ||
|
||
it("should render switch components with its own state", () => { | ||
const switchComponents = rendered.getAllByRole("checkbox"); | ||
|
||
expect(switchComponents[0]).toHaveAttribute("aria-checked", "false"); | ||
expect(switchComponents[1]).toHaveAttribute("aria-disabled", "true"); | ||
expect(switchComponents[2]).toHaveAttribute("aria-checked", "false"); | ||
}); | ||
}); | ||
|
||
describe("with external value provided", () => { | ||
it("should render switch components with external value provided", () => { | ||
const rendered = render( | ||
<SwitchGroup value={[true, false, true]}> | ||
<Switch text="Switch 1" /> | ||
<Switch text="Switch 2" /> | ||
<Switch text="Switch 3" /> | ||
</SwitchGroup> | ||
); | ||
const switchComponents = rendered.getAllByRole("checkbox"); | ||
|
||
expect(switchComponents[0]).toHaveAttribute("aria-checked", "true"); | ||
expect(switchComponents[1]).toHaveAttribute("aria-checked", "false"); | ||
expect(switchComponents[2]).toHaveAttribute("aria-checked", "true"); | ||
}); | ||
|
||
it("should render switch components with default unchecked value provided", () => { | ||
const rendered = render( | ||
<SwitchGroup value={[]}> | ||
<Switch text="Switch 1" /> | ||
<Switch text="Switch 2" /> | ||
<Switch text="Switch 3" /> | ||
</SwitchGroup> | ||
); | ||
const switchComponents = rendered.getAllByRole("checkbox"); | ||
|
||
expect(switchComponents[0]).toHaveAttribute("aria-checked", "false"); | ||
expect(switchComponents[1]).toHaveAttribute("aria-checked", "false"); | ||
expect(switchComponents[2]).toHaveAttribute("aria-checked", "false"); | ||
}); | ||
|
||
it("should toggle state when onChange event fired", async () => { | ||
const checkedStates = [true, false, true]; | ||
const handleChange = jest.fn((index: number) => { | ||
checkedStates[index] = !checkedStates[index]; | ||
}); | ||
const rendered = render( | ||
<SwitchGroup value={checkedStates} onChange={handleChange}> | ||
<Switch text="Switch 1" /> | ||
<Switch text="Switch 2" /> | ||
<Switch text="Switch 3" /> | ||
</SwitchGroup> | ||
); | ||
const switchComponents = rendered.getAllByRole("checkbox"); | ||
|
||
fireEvent.click(switchComponents[0]!); | ||
fireEvent.click(switchComponents[1]!); | ||
fireEvent.click(switchComponents[2]!); | ||
|
||
await waitFor(() => { | ||
expect(checkedStates[0]).toBe(false); | ||
expect(checkedStates[1]).toBe(true); | ||
expect(checkedStates[2]).toBe(false); | ||
}); | ||
}); | ||
|
||
it("should not toggle state when toggle is disabled", async () => { | ||
const checkedStates = [true, false, true]; | ||
const handleChange = jest.fn((index: number) => { | ||
checkedStates[index] = !checkedStates[index]; | ||
}); | ||
const rendered = render( | ||
<SwitchGroup value={checkedStates} onChange={handleChange}> | ||
<Switch text="Switch 1" /> | ||
<Switch isDisabled text="Switch 2" /> | ||
<Switch text="Switch 3" /> | ||
</SwitchGroup> | ||
); | ||
const switchComponents = rendered.getAllByRole("checkbox"); | ||
|
||
fireEvent.click(switchComponents[0]!); | ||
fireEvent.click(switchComponents[1]!); | ||
fireEvent.click(switchComponents[2]!); | ||
|
||
await waitFor(() => { | ||
expect(checkedStates[0]).toBe(false); | ||
expect(checkedStates[1]).toBe(false); | ||
expect(checkedStates[2]).toBe(false); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
p2;
children
관련해서 타입 에러가 발생합니다.