Skip to content

Commit bed73c1

Browse files
authored
Merge pull request #251 from DaleStudy/239-color-token
Color 토큰 구현
2 parents c8367f7 + e2ca0a1 commit bed73c1

24 files changed

+1247
-605
lines changed

src/components/Button/Button.stories.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ export default {
1414
args: {
1515
children: "시작하기",
1616
variant: "solid",
17+
size: "md",
18+
disabled: false,
1719
},
1820
} satisfies Meta<typeof Button>;
1921

@@ -46,18 +48,24 @@ export const Tones: StoryObj<typeof Button> = {
4648
render: (args) => {
4749
return (
4850
<div className={vstack({ gap: "16" })}>
49-
<Button {...args} tone="neutral">
50-
중립 색조
51+
<Button {...args} variant="solid" tone="brand">
52+
브랜드 색조
5153
</Button>
52-
<Button {...args} tone="accent">
53-
강조 색조
54+
<Button {...args} variant="solid" tone="neutral">
55+
중립 색조
5456
</Button>
55-
<Button {...args} tone="danger">
57+
<Button {...args} variant="solid" tone="danger">
5658
위험 색조
5759
</Button>
58-
<Button {...args} tone="warning">
60+
<Button {...args} variant="solid" tone="success">
61+
성공 색조
62+
</Button>
63+
<Button {...args} variant="solid" tone="warning">
5964
경고 색조
6065
</Button>
66+
<Button {...args} variant="solid" tone="info">
67+
정보 색조
68+
</Button>
6169
</div>
6270
);
6371
},

src/components/Button/Button.test.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { composeStories } from "@storybook/react";
22
import { render, screen } from "@testing-library/react";
33
import userEvent from "@testing-library/user-event";
44
import { expect, test, vi } from "vitest";
5-
import * as stories from "./Button.stories";
65
import { Button } from "./Button";
6+
import * as stories from "./Button.stories";
77

88
const { Basic, Variants, Tones, Sizes, Disabled } = composeStories(stories);
99

@@ -16,17 +16,19 @@ test("텍스트와 함께 버튼이 올바르게 렌더링됨", () => {
1616
test("variant 속성이 올바르게 적용됨", () => {
1717
render(<Variants />);
1818

19-
expect(screen.getByText("솔리드 버튼")).toHaveClass("bg_bg");
20-
expect(screen.getByText("아웃라인 버튼")).toHaveClass("bd_3px_solid");
19+
expect(screen.getByText("솔리드 버튼")).toHaveClass("bg_bgSolid.brand");
20+
expect(screen.getByText("아웃라인 버튼")).toHaveClass("bd_1px_solid");
2121
});
2222

2323
test("tone 속성이 올바르게 적용됨", () => {
2424
render(<Tones />);
2525

26-
expect(screen.getByText("중립 색조")).toHaveClass("bg_bg");
27-
expect(screen.getByText("강조 색조")).toHaveClass("bg_bg.accent");
28-
expect(screen.getByText("위험 색조")).toHaveClass("bg_bg.danger");
29-
expect(screen.getByText("경고 색조")).toHaveClass("bg_bg.warning");
26+
expect(screen.getAllByText("브랜드 색조")[0]).toHaveClass("bg_bgSolid.brand");
27+
expect(screen.getAllByText("중립 색조")[0]).toHaveClass("bg_bgSolid.neutral");
28+
expect(screen.getAllByText("성공 색조")[0]).toHaveClass("bg_bgSolid.success");
29+
expect(screen.getAllByText("경고 색조")[0]).toHaveClass("bg_bgSolid.warning");
30+
expect(screen.getAllByText("위험 색조")[0]).toHaveClass("bg_bgSolid.danger");
31+
expect(screen.getAllByText("정보 색조")[0]).toHaveClass("bg_bgSolid.info");
3032
});
3133

3234
test("size prop에 따라 font size가 올바르게 적용됨", () => {
@@ -42,7 +44,9 @@ test("disabled 속성이 올바르게 적용됨", () => {
4244

4345
expect(screen.getByText("비활성화 버튼")).toBeDisabled();
4446
expect(screen.getByText("활성화 버튼")).toBeEnabled();
45-
expect(screen.getByText("비활성화 버튼")).toHaveClass("[&:disabled]:op_0.5");
47+
expect(screen.getByText("비활성화 버튼")).toHaveClass(
48+
"bg_bg.neutral.disabled!",
49+
);
4650
});
4751

4852
test("기본적으로 버튼이 type='button'으로 렌더링됨", () => {

src/components/Button/Button.tsx

Lines changed: 121 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ export const Button = ({
3535
type = "button",
3636
onClick,
3737
variant = "solid",
38-
tone = "neutral",
38+
tone = "brand",
3939
size = "md",
4040
disabled,
4141
...rest
4242
}: ButtonProps) => {
4343
return (
4444
<button
45-
className={styles({ tone, variant, size })}
45+
className={styles({ tone, variant, size, disabled })}
4646
type={type}
4747
onClick={onClick}
4848
disabled={disabled}
@@ -69,10 +69,14 @@ const styles = cva({
6969
transition: "0.2s",
7070
lineHeight: "1",
7171
outline: "0",
72-
"&:disabled": {
73-
opacity: 0.5,
72+
_disabled: {
7473
cursor: "not-allowed",
7574
},
75+
_focusVisible: {
76+
outline: "2px solid",
77+
outlineOffset: "2px",
78+
outlineColor: "border.brand.focus",
79+
},
7680
},
7781
variants: {
7882
size: {
@@ -97,147 +101,181 @@ const styles = cva({
97101
outline: {},
98102
},
99103
tone: {
104+
brand: {},
100105
neutral: {},
101-
accent: {},
102106
danger: {},
107+
success: {},
103108
warning: {},
109+
info: {},
110+
},
111+
disabled: {
112+
true: {},
113+
false: {},
104114
},
105115
},
106116
compoundVariants: [
117+
// Solid Variants
107118
{
108119
variant: "solid",
109-
tone: "neutral",
120+
tone: "brand",
110121
css: {
111-
background: "bg",
112-
color: "text",
113-
"&:active, &:hover": {
114-
background: "bg.hover",
122+
bg: "bgSolid.brand",
123+
color: "fgSolid.brand",
124+
"&:hover": {
125+
bg: "bgSolid.brand.hover",
115126
},
116-
"&:focus": {
117-
outlineColor: "border.neutral",
118-
outline: "3px solid",
119-
outlineOffset: "2px",
127+
"&:active": {
128+
bg: "bgSolid.brand.active",
120129
},
121130
},
122131
},
123132
{
124133
variant: "solid",
125-
tone: "accent",
134+
tone: "neutral",
126135
css: {
127-
background: "bg.accent",
128-
color: "text.accent",
129-
"&:active, &:hover": {
130-
background: "bg.hover.accent",
136+
bg: "bgSolid.neutral",
137+
color: "fgSolid.neutral",
138+
"&:hover": {
139+
bg: "bgSolid.neutral.hover",
131140
},
132-
"&:focus": {
133-
outlineColor: "border.accent",
134-
outline: "3px solid",
135-
outlineOffset: "2px",
141+
"&:active": {
142+
bg: "bgSolid.neutral.active",
136143
},
137144
},
138145
},
139146
{
140147
variant: "solid",
141148
tone: "danger",
142149
css: {
143-
background: "bg.danger",
144-
color: "text.danger",
145-
"&:active, &:hover": {
146-
background: "bg.hover.danger",
150+
bg: "bgSolid.danger",
151+
color: "fgSolid.danger",
152+
"&:hover": {
153+
bg: "bgSolid.danger.hover",
147154
},
148-
"&:focus": {
149-
outlineColor: "border.danger",
150-
outline: "3px solid",
151-
outlineOffset: "2px",
155+
"&:active": {
156+
bg: "bgSolid.danger.active",
152157
},
153158
},
154159
},
160+
{
161+
variant: "solid",
162+
tone: "success",
163+
css: {
164+
bg: "bgSolid.success",
165+
color: "fgSolid.success",
166+
},
167+
},
155168
{
156169
variant: "solid",
157170
tone: "warning",
158171
css: {
159-
background: "bg.warning",
160-
color: "text.warning",
161-
"&:active, &:hover": {
162-
background: "bg.hover.warning",
163-
},
164-
"&:focus": {
165-
outlineColor: "border.warning",
166-
outline: "3px solid",
167-
outlineOffset: "2px",
168-
},
172+
bg: "bgSolid.warning",
173+
color: "fgSolid.warning",
174+
},
175+
},
176+
{
177+
variant: "solid",
178+
tone: "info",
179+
css: {
180+
bg: "bgSolid.info",
181+
color: "fgSolid.info",
169182
},
170183
},
184+
// Outline Variants
171185
{
172186
variant: "outline",
173-
tone: "neutral",
187+
tone: "brand",
174188
css: {
175-
border: "3px solid",
176-
borderColor: "border",
177-
color: "text",
178-
"&:active, &:hover": {
179-
background: "bg.hover",
180-
color: "text.muted",
189+
border: "1px solid",
190+
borderColor: "border.brand",
191+
color: "fg.brand",
192+
"&:hover": {
193+
bg: "bg.brand.hover",
194+
color: "fg.brand.hover",
181195
},
182-
"&:focus": {
183-
outlineColor: "border.neutral",
184-
outline: "3px solid",
185-
outlineOffset: "2px",
196+
"&:active": {
197+
bg: "bg.brand.active",
198+
color: "fg.brand.active",
186199
},
187200
},
188201
},
189202
{
190203
variant: "outline",
191-
tone: "accent",
204+
tone: "neutral",
192205
css: {
193-
border: "3px solid",
194-
borderColor: "border.accent",
195-
color: "text.accent",
196-
"&:active, &:hover": {
197-
background: "bg.hover.accent",
198-
color: "text.muted.accent",
206+
border: "1px solid",
207+
borderColor: "border.neutral",
208+
color: "fg.neutral",
209+
"&:hover": {
210+
bg: "bg.neutral.hover",
211+
color: "fg.neutral.hover",
212+
borderColor: "border.neutral.hover",
199213
},
200-
"&:focus": {
201-
outlineColor: "border.accent",
202-
outline: "3px solid",
203-
outlineOffset: "2px",
214+
"&:active": {
215+
bg: "bg.neutral.active",
216+
color: "fg.neutral.active",
217+
borderColor: "border.neutral.active",
204218
},
205219
},
206220
},
207221
{
208222
variant: "outline",
209223
tone: "danger",
210224
css: {
211-
border: "3px solid",
225+
border: "1px solid",
212226
borderColor: "border.danger",
213-
color: "text.danger",
214-
"&:active, &:hover": {
215-
background: "bg.hover.danger",
216-
color: "text.muted.danger",
227+
color: "fg.danger",
228+
"&:hover": {
229+
bg: "bg.danger.hover",
217230
},
218-
"&:focus": {
219-
outlineColor: "border.danger",
220-
outline: "3px solid",
221-
outlineOffset: "2px",
231+
"&:active": {
232+
bg: "bg.danger.active",
222233
},
223234
},
224235
},
236+
{
237+
variant: "outline",
238+
tone: "success",
239+
css: {
240+
border: "1px solid",
241+
borderColor: "border.success",
242+
color: "fg.success",
243+
},
244+
},
225245
{
226246
variant: "outline",
227247
tone: "warning",
228248
css: {
229-
border: "3px solid",
249+
border: "1px solid",
230250
borderColor: "border.warning",
231-
color: "text.warning",
232-
"&:active, &:hover": {
233-
background: "bg.hover.warning",
234-
color: "text.muted.warning",
235-
},
236-
"&:focus": {
237-
outlineColor: "border.warning",
238-
outline: "3px solid",
239-
outlineOffset: "2px",
240-
},
251+
color: "fg.warning",
252+
},
253+
},
254+
{
255+
variant: "outline",
256+
tone: "info",
257+
css: {
258+
border: "1px solid",
259+
borderColor: "border.info",
260+
color: "fg.info",
261+
},
262+
},
263+
// Disabled States
264+
{
265+
variant: "solid",
266+
disabled: true,
267+
css: {
268+
bg: "bg.neutral.disabled!",
269+
color: "fg.neutral.disabled!",
270+
},
271+
},
272+
{
273+
variant: "outline",
274+
disabled: true,
275+
css: {
276+
bg: "transparent!",
277+
color: "fg.neutral.disabled!",
278+
borderColor: "border.neutral.disabled!",
241279
},
242280
},
243281
],

src/components/Checkbox/Checkbox.stories.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@ export const Tones: StoryObj<typeof Checkbox> = {
1919
render: (args) => {
2020
return (
2121
<div className={vstack({ gap: "16" })}>
22+
<Checkbox {...args} id="brand" label="브랜드 색조" tone="brand" />
2223
<Checkbox {...args} id="neutral" label="중립 색조" tone="neutral" />
23-
<Checkbox {...args} id="accent" label="강조 색조" tone="accent" />
2424
<Checkbox {...args} id="danger" label="위험 색조" tone="danger" />
25+
<Checkbox {...args} id="success" label="성공 색조" tone="success" />
2526
<Checkbox {...args} id="warning" label="경고 색조" tone="warning" />
27+
<Checkbox {...args} id="info" label="정보 색조" tone="info" />
2628
</div>
2729
);
2830
},

0 commit comments

Comments
 (0)