daleui 0.0.2 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -0
- package/dist/check-DEVerfH5.js +72 -0
- package/dist/components/Box/Box.d.ts +34 -0
- package/dist/components/Box/Box.js +34 -0
- package/dist/components/Button/Button.d.ts +37 -0
- package/dist/components/Button/Button.js +367 -0
- package/dist/components/Card/Card.d.ts +68 -0
- package/dist/components/Card/Card.js +132 -0
- package/dist/components/Checkbox/Checkbox.d.ts +34 -0
- package/dist/components/Checkbox/Checkbox.js +657 -0
- package/dist/components/Flex/Flex.d.ts +361 -0
- package/dist/components/Flex/Flex.js +65 -0
- package/dist/components/HStack/HStack.d.ts +23 -0
- package/dist/components/HStack/HStack.js +35 -0
- package/dist/components/Heading/Heading.d.ts +33 -0
- package/dist/components/Heading/Heading.js +67 -0
- package/dist/components/Icon/Icon.d.ts +20 -0
- package/dist/components/Icon/Icon.js +325 -0
- package/dist/components/Label/Label.d.ts +35 -0
- package/dist/components/Label/Label.js +74 -0
- package/dist/components/Link/Link.d.ts +33 -0
- package/dist/components/Link/Link.js +176 -0
- package/dist/components/PasswordInput/PasswordInput.d.ts +17 -0
- package/dist/components/PasswordInput/PasswordInput.js +151 -0
- package/dist/components/RadioGroup/RadioGroup.d.ts +82 -0
- package/dist/components/RadioGroup/RadioGroup.js +713 -0
- package/dist/components/Select/Select.d.ts +39 -0
- package/dist/components/Select/Select.js +222 -0
- package/dist/components/Tag/Tag.d.ts +26 -0
- package/dist/components/Tag/Tag.js +189 -0
- package/dist/components/Text/Text.d.ts +22 -0
- package/dist/components/Text/Text.js +115 -0
- package/dist/components/TextInput/TextInput.d.ts +21 -0
- package/dist/components/TextInput/TextInput.js +106 -0
- package/dist/components/VStack/VStack.d.ts +23 -0
- package/dist/components/VStack/VStack.js +35 -0
- package/dist/css-QiVVeZaw.js +212 -0
- package/dist/cva-BrKodHDH.js +57 -0
- package/dist/cx-DN21T1EH.js +9 -0
- package/dist/hstack-cCrHxysi.js +43 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +37 -0
- package/dist/tokens/colors.d.ts +4 -0
- package/dist/tokens/iconography.d.ts +45 -0
- package/dist/tokens/spacing.d.ts +42 -0
- package/dist/tokens/typography.d.ts +312 -0
- package/dist/use-locale-context-DYXE7B4r.js +775 -0
- package/package.json +62 -39
- package/styled-system/css/conditions.mjs +36 -0
- package/styled-system/css/css.d.ts +22 -0
- package/styled-system/css/css.mjs +45 -0
- package/styled-system/css/cva.d.ts +6 -0
- package/styled-system/css/cva.mjs +87 -0
- package/styled-system/css/cx.d.ts +5 -0
- package/styled-system/css/cx.mjs +15 -0
- package/styled-system/css/index.d.ts +5 -0
- package/styled-system/css/index.mjs +4 -0
- package/styled-system/css/sva.d.ts +4 -0
- package/styled-system/css/sva.mjs +46 -0
- package/styled-system/helpers.mjs +316 -0
- package/styled-system/patterns/aspect-ratio.d.ts +20 -0
- package/styled-system/patterns/aspect-ratio.mjs +38 -0
- package/styled-system/patterns/bleed.d.ts +21 -0
- package/styled-system/patterns/bleed.mjs +24 -0
- package/styled-system/patterns/box.d.ts +20 -0
- package/styled-system/patterns/box.mjs +15 -0
- package/styled-system/patterns/center.d.ts +20 -0
- package/styled-system/patterns/center.mjs +21 -0
- package/styled-system/patterns/circle.d.ts +20 -0
- package/styled-system/patterns/circle.mjs +25 -0
- package/styled-system/patterns/container.d.ts +20 -0
- package/styled-system/patterns/container.mjs +21 -0
- package/styled-system/patterns/cq.d.ts +21 -0
- package/styled-system/patterns/cq.mjs +21 -0
- package/styled-system/patterns/divider.d.ts +22 -0
- package/styled-system/patterns/divider.mjs +25 -0
- package/styled-system/patterns/flex.d.ts +26 -0
- package/styled-system/patterns/flex.mjs +26 -0
- package/styled-system/patterns/float.d.ts +23 -0
- package/styled-system/patterns/float.mjs +52 -0
- package/styled-system/patterns/grid-item.d.ts +25 -0
- package/styled-system/patterns/grid-item.mjs +25 -0
- package/styled-system/patterns/grid.d.ts +24 -0
- package/styled-system/patterns/grid.mjs +27 -0
- package/styled-system/patterns/hstack.d.ts +21 -0
- package/styled-system/patterns/hstack.mjs +24 -0
- package/styled-system/patterns/index.d.ts +21 -0
- package/styled-system/patterns/index.mjs +20 -0
- package/styled-system/patterns/link-overlay.d.ts +20 -0
- package/styled-system/patterns/link-overlay.mjs +24 -0
- package/styled-system/patterns/spacer.d.ts +20 -0
- package/styled-system/patterns/spacer.mjs +21 -0
- package/styled-system/patterns/square.d.ts +20 -0
- package/styled-system/patterns/square.mjs +24 -0
- package/styled-system/patterns/stack.d.ts +23 -0
- package/styled-system/patterns/stack.mjs +24 -0
- package/styled-system/patterns/visually-hidden.d.ts +20 -0
- package/styled-system/patterns/visually-hidden.mjs +18 -0
- package/styled-system/patterns/vstack.d.ts +21 -0
- package/styled-system/patterns/vstack.mjs +24 -0
- package/styled-system/patterns/wrap.d.ts +24 -0
- package/styled-system/patterns/wrap.mjs +25 -0
- package/styled-system/tokens/index.d.ts +9 -0
- package/styled-system/tokens/index.mjs +3176 -0
- package/styled-system/tokens/tokens.d.ts +63 -0
- package/styled-system/types/composition.d.ts +224 -0
- package/styled-system/types/conditions.d.ts +310 -0
- package/styled-system/types/csstype.d.ts +21298 -0
- package/styled-system/types/global.d.ts +20 -0
- package/styled-system/types/index.d.ts +7 -0
- package/styled-system/types/parts.d.ts +8 -0
- package/styled-system/types/pattern.d.ts +78 -0
- package/styled-system/types/prop-type.d.ts +265 -0
- package/styled-system/types/recipe.d.ts +181 -0
- package/styled-system/types/selectors.d.ts +59 -0
- package/styled-system/types/static-css.d.ts +56 -0
- package/styled-system/types/style-props.d.ts +7504 -0
- package/styled-system/types/system-types.d.ts +269 -0
- package/.github/CODEOWNERS +0 -1
- package/.github/FUNDING.yml +0 -1
- package/.github/workflows/automation.yml +0 -13
- package/.github/workflows/chromatic.yml +0 -19
- package/.github/workflows/deployment.yml +0 -32
- package/.github/workflows/integration.yml +0 -15
- package/.github/workflows/storybook-tests.yml +0 -17
- package/.storybook/main.ts +0 -18
- package/.storybook/preview.ts +0 -29
- package/.storybook/test-runner.ts +0 -33
- package/bun.lock +0 -2099
- package/chromatic.config.json +0 -5
- package/eslint.config.js +0 -28
- package/index.html +0 -13
- package/panda.config.ts +0 -61
- package/postcss.config.cjs +0 -5
- package/public/logo.svg +0 -9
- package/src/App.tsx +0 -67
- package/src/assets/Discord.svg +0 -1
- package/src/assets/GitHub.svg +0 -1
- package/src/assets/LinkedIn.svg +0 -1
- package/src/assets/Medium.svg +0 -1
- package/src/assets/YouTube.svg +0 -1
- package/src/components/Button/Button.stories.tsx +0 -115
- package/src/components/Button/Button.test.tsx +0 -108
- package/src/components/Button/Button.tsx +0 -245
- package/src/components/Button/index.tsx +0 -1
- package/src/components/Checkbox/Checkbox.stories.tsx +0 -129
- package/src/components/Checkbox/Checkbox.test.tsx +0 -169
- package/src/components/Checkbox/Checkbox.tsx +0 -190
- package/src/components/Heading/Heading.stories.tsx +0 -72
- package/src/components/Heading/Heading.test.tsx +0 -55
- package/src/components/Heading/Heading.tsx +0 -73
- package/src/components/Heading/index.tsx +0 -1
- package/src/components/Icon/Icon.stories.tsx +0 -106
- package/src/components/Icon/Icon.test.tsx +0 -44
- package/src/components/Icon/Icon.tsx +0 -116
- package/src/components/Icon/index.tsx +0 -1
- package/src/components/Text/Text.stories.tsx +0 -65
- package/src/components/Text/Text.test.tsx +0 -54
- package/src/components/Text/Text.tsx +0 -93
- package/src/components/Text/index.tsx +0 -1
- package/src/index.css +0 -2
- package/src/main.tsx +0 -10
- package/src/setupTests.tsx +0 -5
- package/src/styles/globalCss.ts +0 -43
- package/src/tokens/colors.mdx +0 -100
- package/src/tokens/colors.ts +0 -288
- package/src/tokens/iconography.mdx +0 -15
- package/src/tokens/iconography.tsx +0 -54
- package/src/tokens/typography.mdx +0 -38
- package/src/tokens/typography.ts +0 -132
- package/src/vite-env.d.ts +0 -2
- package/tsconfig.app.json +0 -25
- package/tsconfig.json +0 -7
- package/tsconfig.node.json +0 -22
- package/vite.config.ts +0 -16
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { Checkbox } from "./Checkbox";
|
|
3
|
-
import { vstack } from "../../../styled-system/patterns";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
component: Checkbox,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "centered",
|
|
9
|
-
},
|
|
10
|
-
args: {
|
|
11
|
-
id: "checkbox",
|
|
12
|
-
label: "기본 체크박스",
|
|
13
|
-
},
|
|
14
|
-
} satisfies Meta<typeof Checkbox>;
|
|
15
|
-
|
|
16
|
-
export const Basic: StoryObj<typeof Checkbox> = {};
|
|
17
|
-
|
|
18
|
-
export const Tones: StoryObj<typeof Checkbox> = {
|
|
19
|
-
render: (args) => {
|
|
20
|
-
return (
|
|
21
|
-
<div className={vstack({ gap: "4" })}>
|
|
22
|
-
<Checkbox {...args} id="neutral" label="중립 색조" tone="neutral" />
|
|
23
|
-
<Checkbox {...args} id="accent" label="강조 색조" tone="accent" />
|
|
24
|
-
<Checkbox {...args} id="danger" label="위험 색조" tone="danger" />
|
|
25
|
-
<Checkbox {...args} id="warning" label="경고 색조" tone="warning" />
|
|
26
|
-
</div>
|
|
27
|
-
);
|
|
28
|
-
},
|
|
29
|
-
argTypes: {
|
|
30
|
-
label: {
|
|
31
|
-
control: false,
|
|
32
|
-
},
|
|
33
|
-
tone: {
|
|
34
|
-
control: false,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const States: StoryObj<typeof Checkbox> = {
|
|
40
|
-
render: (args) => {
|
|
41
|
-
return (
|
|
42
|
-
<div className={vstack({ gap: "4" })}>
|
|
43
|
-
<Checkbox {...args} id="checked" label="체크된 상태" checked={true} />
|
|
44
|
-
<Checkbox
|
|
45
|
-
{...args}
|
|
46
|
-
id="unchecked"
|
|
47
|
-
label="체크되지 않은 상태"
|
|
48
|
-
checked={false}
|
|
49
|
-
/>
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
},
|
|
53
|
-
argTypes: {
|
|
54
|
-
label: {
|
|
55
|
-
control: false,
|
|
56
|
-
},
|
|
57
|
-
checked: {
|
|
58
|
-
control: false,
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
export const Disabled: StoryObj<typeof Checkbox> = {
|
|
64
|
-
render: (args) => {
|
|
65
|
-
return (
|
|
66
|
-
<div className={vstack({ gap: "4" })}>
|
|
67
|
-
<Checkbox
|
|
68
|
-
{...args}
|
|
69
|
-
id="disabled-checked"
|
|
70
|
-
label="비활성화 & 체크된 상태"
|
|
71
|
-
disabled
|
|
72
|
-
checked
|
|
73
|
-
/>
|
|
74
|
-
<Checkbox
|
|
75
|
-
{...args}
|
|
76
|
-
id="disabled-unchecked"
|
|
77
|
-
label="비활성화 & 체크되지 않은 상태"
|
|
78
|
-
disabled
|
|
79
|
-
/>
|
|
80
|
-
<Checkbox {...args} id="enabled" label="활성화 상태" />
|
|
81
|
-
</div>
|
|
82
|
-
);
|
|
83
|
-
},
|
|
84
|
-
argTypes: {
|
|
85
|
-
label: {
|
|
86
|
-
control: false,
|
|
87
|
-
},
|
|
88
|
-
disabled: {
|
|
89
|
-
control: false,
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
export const Required: StoryObj<typeof Checkbox> = {
|
|
95
|
-
render: (args) => {
|
|
96
|
-
return (
|
|
97
|
-
<div className={vstack({ gap: "4" })}>
|
|
98
|
-
<Checkbox {...args} id="required" label="필수 체크박스" required />
|
|
99
|
-
<Checkbox {...args} id="optional" label="선택 체크박스" />
|
|
100
|
-
</div>
|
|
101
|
-
);
|
|
102
|
-
},
|
|
103
|
-
argTypes: {
|
|
104
|
-
label: {
|
|
105
|
-
control: false,
|
|
106
|
-
},
|
|
107
|
-
required: {
|
|
108
|
-
control: false,
|
|
109
|
-
},
|
|
110
|
-
},
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
export const WithValue: StoryObj<typeof Checkbox> = {
|
|
114
|
-
render: (args) => {
|
|
115
|
-
return (
|
|
116
|
-
<div className={vstack({ gap: "4" })}>
|
|
117
|
-
<Checkbox
|
|
118
|
-
{...args}
|
|
119
|
-
id="value-example"
|
|
120
|
-
label="값이 있는 체크박스"
|
|
121
|
-
value="checkbox-value"
|
|
122
|
-
onChange={(checked, value) =>
|
|
123
|
-
console.log(`체크박스 상태: ${checked}, 값: ${value}`)
|
|
124
|
-
}
|
|
125
|
-
/>
|
|
126
|
-
</div>
|
|
127
|
-
);
|
|
128
|
-
},
|
|
129
|
-
};
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { composeStories } from "@storybook/react";
|
|
2
|
-
import { render, screen, fireEvent } from "@testing-library/react";
|
|
3
|
-
import { expect, test, vi } from "vitest";
|
|
4
|
-
import * as stories from "./Checkbox.stories";
|
|
5
|
-
import { Checkbox } from "./Checkbox";
|
|
6
|
-
|
|
7
|
-
const { Basic, Tones, States, Disabled, Required } = composeStories(stories);
|
|
8
|
-
|
|
9
|
-
test("renders the checkbox with the correct label", () => {
|
|
10
|
-
render(<Basic />);
|
|
11
|
-
expect(screen.getByText("기본 체크박스")).toBeInTheDocument();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
test("applies the correct tone styles when checked", () => {
|
|
15
|
-
render(<Tones />);
|
|
16
|
-
|
|
17
|
-
const neutralCheckbox = screen.getByLabelText("중립 색조");
|
|
18
|
-
const accentCheckbox = screen.getByLabelText("강조 색조");
|
|
19
|
-
const dangerCheckbox = screen.getByLabelText("위험 색조");
|
|
20
|
-
const warningCheckbox = screen.getByLabelText("경고 색조");
|
|
21
|
-
|
|
22
|
-
// Simulate checking each checkbox
|
|
23
|
-
fireEvent.click(neutralCheckbox);
|
|
24
|
-
fireEvent.click(accentCheckbox);
|
|
25
|
-
fireEvent.click(dangerCheckbox);
|
|
26
|
-
fireEvent.click(warningCheckbox);
|
|
27
|
-
|
|
28
|
-
// Check for data-state attribute which indicates checked state
|
|
29
|
-
expect(neutralCheckbox).toHaveAttribute("data-state", "checked");
|
|
30
|
-
expect(accentCheckbox).toHaveAttribute("data-state", "checked");
|
|
31
|
-
expect(dangerCheckbox).toHaveAttribute("data-state", "checked");
|
|
32
|
-
expect(warningCheckbox).toHaveAttribute("data-state", "checked");
|
|
33
|
-
|
|
34
|
-
// Check for correct background colors based on tone
|
|
35
|
-
expect(neutralCheckbox).toHaveClass("[&[data-state='checked']]:bg-c_bg");
|
|
36
|
-
expect(accentCheckbox).toHaveClass(
|
|
37
|
-
"[&[data-state='checked']]:bg-c_bg.accent"
|
|
38
|
-
);
|
|
39
|
-
expect(dangerCheckbox).toHaveClass(
|
|
40
|
-
"[&[data-state='checked']]:bg-c_bg.danger"
|
|
41
|
-
);
|
|
42
|
-
expect(warningCheckbox).toHaveClass(
|
|
43
|
-
"[&[data-state='checked']]:bg-c_bg.warning"
|
|
44
|
-
);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test("renders checked and unchecked states correctly", () => {
|
|
48
|
-
render(<States />);
|
|
49
|
-
|
|
50
|
-
const checkedCheckbox = screen.getByLabelText("체크된 상태");
|
|
51
|
-
const uncheckedCheckbox = screen.getByLabelText("체크되지 않은 상태");
|
|
52
|
-
|
|
53
|
-
expect(checkedCheckbox).toHaveAttribute("data-state", "checked");
|
|
54
|
-
expect(uncheckedCheckbox).toHaveAttribute("data-state", "unchecked");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("applies the correct disabled styles", () => {
|
|
58
|
-
render(<Disabled />);
|
|
59
|
-
|
|
60
|
-
const disabledCheckedCheckbox =
|
|
61
|
-
screen.getByLabelText("비활성화 & 체크된 상태");
|
|
62
|
-
const disabledUncheckedCheckbox =
|
|
63
|
-
screen.getByLabelText("비활성화 & 체크되지 않은 상태");
|
|
64
|
-
const enabledCheckbox = screen.getByLabelText("활성화 상태");
|
|
65
|
-
|
|
66
|
-
expect(disabledCheckedCheckbox).toBeDisabled();
|
|
67
|
-
expect(disabledUncheckedCheckbox).toBeDisabled();
|
|
68
|
-
expect(enabledCheckbox).not.toBeDisabled();
|
|
69
|
-
|
|
70
|
-
// Check for opacity class that indicates disabled state
|
|
71
|
-
expect(disabledCheckedCheckbox).toHaveClass("[&:disabled]:op_0.5");
|
|
72
|
-
expect(disabledUncheckedCheckbox).toHaveClass("[&:disabled]:op_0.5");
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test("displays required indicator correctly", () => {
|
|
76
|
-
render(<Required />);
|
|
77
|
-
|
|
78
|
-
const requiredLabel = screen.getByText("필수 체크박스").parentElement;
|
|
79
|
-
const optionalLabel = screen.getByText("선택 체크박스");
|
|
80
|
-
|
|
81
|
-
// Check for required indicator (asterisk)
|
|
82
|
-
expect(requiredLabel).toContainHTML("*");
|
|
83
|
-
expect(optionalLabel).not.toContainHTML("*");
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("calls onChange handler when checkbox is clicked", () => {
|
|
87
|
-
const handleChange = vi.fn();
|
|
88
|
-
|
|
89
|
-
render(
|
|
90
|
-
<Checkbox
|
|
91
|
-
id="test-checkbox"
|
|
92
|
-
label="테스트 체크박스"
|
|
93
|
-
onChange={handleChange}
|
|
94
|
-
/>
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
const checkbox = screen.getByLabelText("테스트 체크박스");
|
|
98
|
-
|
|
99
|
-
// Initially unchecked
|
|
100
|
-
expect(checkbox).toHaveAttribute("data-state", "unchecked");
|
|
101
|
-
|
|
102
|
-
// Click to check
|
|
103
|
-
fireEvent.click(checkbox);
|
|
104
|
-
expect(handleChange).toHaveBeenCalledTimes(1);
|
|
105
|
-
expect(handleChange).toHaveBeenCalledWith(true, undefined);
|
|
106
|
-
|
|
107
|
-
// Click again to uncheck
|
|
108
|
-
fireEvent.click(checkbox);
|
|
109
|
-
expect(handleChange).toHaveBeenCalledTimes(2);
|
|
110
|
-
expect(handleChange).toHaveBeenCalledWith(false, undefined);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test("passes value to onChange handler when provided", () => {
|
|
114
|
-
const handleChange = vi.fn();
|
|
115
|
-
|
|
116
|
-
render(
|
|
117
|
-
<Checkbox
|
|
118
|
-
id="value-checkbox"
|
|
119
|
-
label="값이 있는 체크박스"
|
|
120
|
-
value="test-value"
|
|
121
|
-
onChange={handleChange}
|
|
122
|
-
/>
|
|
123
|
-
);
|
|
124
|
-
|
|
125
|
-
const checkbox = screen.getByLabelText("값이 있는 체크박스");
|
|
126
|
-
|
|
127
|
-
// Click to check
|
|
128
|
-
fireEvent.click(checkbox);
|
|
129
|
-
expect(handleChange).toHaveBeenCalledWith(true, "test-value");
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test("correctly handles required attribute", () => {
|
|
133
|
-
render(
|
|
134
|
-
<Checkbox id="required-checkbox" label="필수 체크박스" required={true} />
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
// 정규 표현식을 사용하여 라벨 찾기 (별표가 있어도 일치)
|
|
138
|
-
const checkbox = screen.getByRole("checkbox", { name: /필수 체크박스/ });
|
|
139
|
-
|
|
140
|
-
// aria-required 속성 확인
|
|
141
|
-
expect(checkbox).toHaveAttribute("aria-required", "true");
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test("toggles checked state when clicked", () => {
|
|
145
|
-
render(<Basic />);
|
|
146
|
-
|
|
147
|
-
const checkbox = screen.getByLabelText("기본 체크박스");
|
|
148
|
-
|
|
149
|
-
// Initially unchecked
|
|
150
|
-
expect(checkbox).toHaveAttribute("data-state", "unchecked");
|
|
151
|
-
|
|
152
|
-
// Click to check
|
|
153
|
-
fireEvent.click(checkbox);
|
|
154
|
-
expect(checkbox).toHaveAttribute("data-state", "checked");
|
|
155
|
-
|
|
156
|
-
// Click again to uncheck
|
|
157
|
-
fireEvent.click(checkbox);
|
|
158
|
-
expect(checkbox).toHaveAttribute("data-state", "unchecked");
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
test("adds asterisk to label when required is true", () => {
|
|
162
|
-
render(
|
|
163
|
-
<Checkbox id="required-checkbox" label="필수 체크박스" required={true} />
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const requiredIndicator = screen.getByText("*");
|
|
167
|
-
expect(requiredIndicator).toBeInTheDocument();
|
|
168
|
-
expect(requiredIndicator).toHaveClass("c_text.danger");
|
|
169
|
-
});
|
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import React, { type ButtonHTMLAttributes } from "react";
|
|
2
|
-
import { css, cva } from "../../../styled-system/css";
|
|
3
|
-
import type { Tone } from "../../tokens/colors";
|
|
4
|
-
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
5
|
-
import { Check } from "lucide-react";
|
|
6
|
-
|
|
7
|
-
export interface CheckboxProps
|
|
8
|
-
extends Omit<
|
|
9
|
-
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
10
|
-
"type" | "onChange" | "checked" | "value" | "required"
|
|
11
|
-
> {
|
|
12
|
-
/** 라벨 */
|
|
13
|
-
label: React.ReactNode;
|
|
14
|
-
/** 체크박스의 값 */
|
|
15
|
-
value?: string;
|
|
16
|
-
/** 색조 */
|
|
17
|
-
tone?: Tone;
|
|
18
|
-
/** 체크박스 비활성화 여부 */
|
|
19
|
-
disabled?: boolean;
|
|
20
|
-
/** 체크박스 선택 여부 */
|
|
21
|
-
checked?: boolean;
|
|
22
|
-
/** 필수 입력 여부 */
|
|
23
|
-
required?: boolean;
|
|
24
|
-
/** 변경 이벤트 핸들러 */
|
|
25
|
-
onChange?: (checked: boolean, value?: string) => void;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* - `tone` 속성으로 체크박스의 색상 강조를 지정할 수 있습니다.
|
|
30
|
-
* - `disabled` 속성을 사용하여 체크박스를 비활성화할 수 있습니다.
|
|
31
|
-
* - `value` 속성을 통해 체크박스에 값을 지정할 수 있습니다.
|
|
32
|
-
* - `required` 속성을 사용하여 필수 입력 항목으로 지정할 수 있습니다.
|
|
33
|
-
*/
|
|
34
|
-
export const Checkbox = ({
|
|
35
|
-
label,
|
|
36
|
-
value,
|
|
37
|
-
tone = "neutral",
|
|
38
|
-
disabled,
|
|
39
|
-
checked,
|
|
40
|
-
required,
|
|
41
|
-
onChange,
|
|
42
|
-
...rest
|
|
43
|
-
}: CheckboxProps) => {
|
|
44
|
-
return (
|
|
45
|
-
<label
|
|
46
|
-
className={css({
|
|
47
|
-
display: "flex",
|
|
48
|
-
alignItems: "center",
|
|
49
|
-
gap: "0.5rem",
|
|
50
|
-
cursor: "pointer",
|
|
51
|
-
color: "text",
|
|
52
|
-
})}
|
|
53
|
-
>
|
|
54
|
-
<CheckboxPrimitive.Root
|
|
55
|
-
checked={checked}
|
|
56
|
-
required={required}
|
|
57
|
-
onCheckedChange={(checked) => {
|
|
58
|
-
onChange?.(checked === true, value);
|
|
59
|
-
}}
|
|
60
|
-
disabled={disabled}
|
|
61
|
-
className={styles({ tone })}
|
|
62
|
-
{...rest}
|
|
63
|
-
>
|
|
64
|
-
<CheckboxPrimitive.Indicator
|
|
65
|
-
className={css({
|
|
66
|
-
width: "100%",
|
|
67
|
-
height: "100%",
|
|
68
|
-
display: "flex",
|
|
69
|
-
alignItems: "center",
|
|
70
|
-
justifyContent: "center",
|
|
71
|
-
})}
|
|
72
|
-
>
|
|
73
|
-
<Check size={16} />
|
|
74
|
-
</CheckboxPrimitive.Indicator>
|
|
75
|
-
</CheckboxPrimitive.Root>
|
|
76
|
-
{label}
|
|
77
|
-
{required && <span className={css({ color: "text.danger" })}>*</span>}
|
|
78
|
-
</label>
|
|
79
|
-
);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const styles = cva({
|
|
83
|
-
base: {
|
|
84
|
-
appearance: "none",
|
|
85
|
-
margin: "0",
|
|
86
|
-
backgroundColor: "transparent",
|
|
87
|
-
border: "3px solid",
|
|
88
|
-
borderColor: "border",
|
|
89
|
-
borderRadius: "4px",
|
|
90
|
-
width: "1.5rem",
|
|
91
|
-
height: "1.5rem",
|
|
92
|
-
display: "flex",
|
|
93
|
-
alignItems: "center",
|
|
94
|
-
justifyContent: "center",
|
|
95
|
-
cursor: "pointer",
|
|
96
|
-
transition: "0.2s",
|
|
97
|
-
outline: "none",
|
|
98
|
-
"&:hover": {
|
|
99
|
-
backgroundColor: "bg.hover",
|
|
100
|
-
},
|
|
101
|
-
"&:focus": {
|
|
102
|
-
outline: "3px solid",
|
|
103
|
-
outlineOffset: "2px",
|
|
104
|
-
},
|
|
105
|
-
"&:disabled": {
|
|
106
|
-
opacity: 0.5,
|
|
107
|
-
cursor: "not-allowed",
|
|
108
|
-
"&:hover": {
|
|
109
|
-
backgroundColor: "transparent",
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
},
|
|
113
|
-
variants: {
|
|
114
|
-
tone: {
|
|
115
|
-
neutral: {
|
|
116
|
-
"&[data-state='checked']": {
|
|
117
|
-
backgroundColor: "bg",
|
|
118
|
-
borderColor: "border",
|
|
119
|
-
color: "text",
|
|
120
|
-
},
|
|
121
|
-
"&:disabled[data-state='checked']": {
|
|
122
|
-
backgroundColor: "bg",
|
|
123
|
-
borderColor: "border",
|
|
124
|
-
},
|
|
125
|
-
"&:focus": {
|
|
126
|
-
outlineColor: "border",
|
|
127
|
-
},
|
|
128
|
-
},
|
|
129
|
-
accent: {
|
|
130
|
-
"&[data-state='checked']": {
|
|
131
|
-
backgroundColor: "bg.accent",
|
|
132
|
-
borderColor: "border.accent",
|
|
133
|
-
color: "text.accent",
|
|
134
|
-
},
|
|
135
|
-
"&:disabled[data-state='checked']": {
|
|
136
|
-
backgroundColor: "bg.accent",
|
|
137
|
-
borderColor: "border.accent",
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
danger: {
|
|
141
|
-
"&[data-state='checked']": {
|
|
142
|
-
backgroundColor: "bg.danger",
|
|
143
|
-
borderColor: "border.danger",
|
|
144
|
-
color: "text.danger",
|
|
145
|
-
},
|
|
146
|
-
"&:disabled[data-state='checked']": {
|
|
147
|
-
backgroundColor: "bg.danger",
|
|
148
|
-
borderColor: "border.danger",
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
warning: {
|
|
152
|
-
"&[data-state='checked']": {
|
|
153
|
-
backgroundColor: "bg.warning",
|
|
154
|
-
borderColor: "border.warning",
|
|
155
|
-
color: "text.warning",
|
|
156
|
-
},
|
|
157
|
-
"&:disabled[data-state='checked']": {
|
|
158
|
-
backgroundColor: "bg.warning",
|
|
159
|
-
borderColor: "border.warning",
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
compoundVariants: [
|
|
165
|
-
{
|
|
166
|
-
tone: "accent",
|
|
167
|
-
css: {
|
|
168
|
-
"&:focus": {
|
|
169
|
-
outlineColor: "border.accent",
|
|
170
|
-
},
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
tone: "danger",
|
|
175
|
-
css: {
|
|
176
|
-
"&:focus": {
|
|
177
|
-
outlineColor: "border.danger",
|
|
178
|
-
},
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
{
|
|
182
|
-
tone: "warning",
|
|
183
|
-
css: {
|
|
184
|
-
"&:focus": {
|
|
185
|
-
outlineColor: "border.warning",
|
|
186
|
-
},
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
],
|
|
190
|
-
});
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
-
import { vstack } from "../../../styled-system/patterns";
|
|
3
|
-
import { Heading } from "./Heading";
|
|
4
|
-
|
|
5
|
-
export default {
|
|
6
|
-
component: Heading,
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: "centered",
|
|
9
|
-
},
|
|
10
|
-
args: {
|
|
11
|
-
children: "제목",
|
|
12
|
-
level: 1,
|
|
13
|
-
},
|
|
14
|
-
} satisfies Meta<typeof Heading>;
|
|
15
|
-
|
|
16
|
-
export const Basic: StoryObj<typeof Heading> = {};
|
|
17
|
-
|
|
18
|
-
export const Levels: StoryObj<typeof Heading> = {
|
|
19
|
-
render: (args) => {
|
|
20
|
-
return (
|
|
21
|
-
<div className={vstack({ gap: "6" })}>
|
|
22
|
-
<Heading {...args} level={1}>
|
|
23
|
-
1 단계
|
|
24
|
-
</Heading>
|
|
25
|
-
<Heading {...args} level={2}>
|
|
26
|
-
2 단계
|
|
27
|
-
</Heading>
|
|
28
|
-
<Heading {...args} level={3}>
|
|
29
|
-
3 단계
|
|
30
|
-
</Heading>
|
|
31
|
-
<Heading {...args} level={4}>
|
|
32
|
-
4 단계
|
|
33
|
-
</Heading>
|
|
34
|
-
<Heading {...args} level={5}>
|
|
35
|
-
5 단계
|
|
36
|
-
</Heading>
|
|
37
|
-
<Heading {...args} level={6}>
|
|
38
|
-
6 단계
|
|
39
|
-
</Heading>
|
|
40
|
-
</div>
|
|
41
|
-
);
|
|
42
|
-
},
|
|
43
|
-
argTypes: {
|
|
44
|
-
children: {
|
|
45
|
-
control: false,
|
|
46
|
-
},
|
|
47
|
-
level: {
|
|
48
|
-
control: false,
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const Contrasts: StoryObj<typeof Heading> = {
|
|
54
|
-
render: (args) => {
|
|
55
|
-
return (
|
|
56
|
-
<div className={vstack({ gap: "6" })}>
|
|
57
|
-
<Heading {...args} muted>
|
|
58
|
-
낮은 명암비
|
|
59
|
-
</Heading>
|
|
60
|
-
<Heading {...args}>높은 명암비</Heading>
|
|
61
|
-
</div>
|
|
62
|
-
);
|
|
63
|
-
},
|
|
64
|
-
argTypes: {
|
|
65
|
-
children: {
|
|
66
|
-
control: false,
|
|
67
|
-
},
|
|
68
|
-
muted: {
|
|
69
|
-
control: false,
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { faker } from "@faker-js/faker";
|
|
2
|
-
import { composeStories } from "@storybook/react";
|
|
3
|
-
import { render, screen } from "@testing-library/react";
|
|
4
|
-
import { expect, test } from "vitest";
|
|
5
|
-
import { fontSizes, fontWeights } from "../../tokens/typography";
|
|
6
|
-
import * as stories from "./Heading.stories";
|
|
7
|
-
|
|
8
|
-
const { Basic, Contrasts } = composeStories(stories);
|
|
9
|
-
|
|
10
|
-
test("renders the heading with the correct text content", () => {
|
|
11
|
-
render(<Basic>제목</Basic>);
|
|
12
|
-
|
|
13
|
-
expect(screen.getByRole("heading")).toHaveTextContent("제목");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test.each([1, 2, 3, 4, 5, 6] as const)(
|
|
17
|
-
"renders the correct HTML heading element for level %i",
|
|
18
|
-
(level) => {
|
|
19
|
-
render(<Basic level={level} />);
|
|
20
|
-
|
|
21
|
-
expect(screen.getByRole("heading", { level })).toBeInTheDocument();
|
|
22
|
-
}
|
|
23
|
-
);
|
|
24
|
-
|
|
25
|
-
test("applies the correct font weight class based on the weight prop", () => {
|
|
26
|
-
const weight = faker.helpers.arrayElement(
|
|
27
|
-
Object.keys(fontWeights)
|
|
28
|
-
) as keyof typeof fontWeights;
|
|
29
|
-
|
|
30
|
-
render(<Basic weight={weight} />);
|
|
31
|
-
|
|
32
|
-
expect(screen.getByRole("heading")).toHaveClass(`fw_${weight}`);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("applies the correct font size class based on the size prop", () => {
|
|
36
|
-
const size = faker.helpers.arrayElement(
|
|
37
|
-
Object.keys(fontSizes)
|
|
38
|
-
) as keyof typeof fontSizes;
|
|
39
|
-
|
|
40
|
-
render(<Basic size={size} />);
|
|
41
|
-
|
|
42
|
-
expect(screen.getByRole("heading")).toHaveClass(`fs_${size}`);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("applies the correct color for low and high contrast", () => {
|
|
46
|
-
render(<Contrasts />);
|
|
47
|
-
|
|
48
|
-
expect(screen.getByRole("heading", { name: "낮은 명암비" })).toHaveClass(
|
|
49
|
-
"c_text.muted"
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
expect(screen.getByRole("heading", { name: "높은 명암비" })).toHaveClass(
|
|
53
|
-
"c_text"
|
|
54
|
-
);
|
|
55
|
-
});
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type { ReactNode, HTMLAttributes } from "react";
|
|
2
|
-
import { css, cva } from "../../../styled-system/css";
|
|
3
|
-
import type { FontSize, FontWeight } from "../../tokens/typography";
|
|
4
|
-
|
|
5
|
-
type Level = 1 | 2 | 3 | 4 | 5 | 6;
|
|
6
|
-
|
|
7
|
-
export interface HeadingProps extends HTMLAttributes<HTMLHeadingElement> {
|
|
8
|
-
/** 텍스트 */
|
|
9
|
-
children: ReactNode;
|
|
10
|
-
/** 단계 */
|
|
11
|
-
level: Level;
|
|
12
|
-
/** 크기 */
|
|
13
|
-
size?: FontSize;
|
|
14
|
-
/** 굵기 */
|
|
15
|
-
weight?: FontWeight;
|
|
16
|
-
/** 명암비 낮출지 */
|
|
17
|
-
muted?: boolean;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* - `level` 속성을 통해서 `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>` 요소 중 하나를 선택할 수 있습니다.
|
|
22
|
-
* - `level` 속성은 단계 별 기본 텍스트 스타일을 제공합니다.
|
|
23
|
-
* - `size` 속성과 `weight` 속성을 통해서 기본 스타일을 변경할 수 있습니다.
|
|
24
|
-
* - `muted` 속성을 주시면 글자색이 옅어집니다. 명암비가 낮아지므로 접근성 측면에서 주의해서 사용하세요.
|
|
25
|
-
*/
|
|
26
|
-
export const Heading = ({
|
|
27
|
-
children,
|
|
28
|
-
level,
|
|
29
|
-
size,
|
|
30
|
-
weight,
|
|
31
|
-
muted = false,
|
|
32
|
-
...rest
|
|
33
|
-
}: HeadingProps) => {
|
|
34
|
-
if (!level) {
|
|
35
|
-
throw new Error(
|
|
36
|
-
"The level prop is required and you can cause accessibility issues."
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const Tag = `h${level}` as const;
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<Tag
|
|
44
|
-
className={css(
|
|
45
|
-
styles.raw({ level, muted }),
|
|
46
|
-
css.raw({
|
|
47
|
-
fontSize: size,
|
|
48
|
-
fontWeight: weight,
|
|
49
|
-
})
|
|
50
|
-
)}
|
|
51
|
-
{...rest}
|
|
52
|
-
>
|
|
53
|
-
{children}
|
|
54
|
-
</Tag>
|
|
55
|
-
);
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
const styles = cva({
|
|
59
|
-
variants: {
|
|
60
|
-
level: {
|
|
61
|
-
1: { textStyle: "4xl" },
|
|
62
|
-
2: { textStyle: "3xl" },
|
|
63
|
-
3: { textStyle: "2xl" },
|
|
64
|
-
4: { textStyle: "xl" },
|
|
65
|
-
5: { textStyle: "lg" },
|
|
66
|
-
6: { textStyle: "md" },
|
|
67
|
-
},
|
|
68
|
-
muted: {
|
|
69
|
-
true: { color: "text.muted" },
|
|
70
|
-
false: { color: "text" },
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Heading } from "./Heading";
|