-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
281 additions
and
3 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
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,106 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { vstack } from "../../../styled-system/patterns"; | ||
import { Heading } from "../Heading/Heading"; | ||
import { Text } from "../Text/Text"; | ||
import { Icon } from "./Icon"; | ||
|
||
export default { | ||
component: Icon, | ||
parameters: { | ||
layout: "centered", | ||
}, | ||
args: { | ||
name: "user", | ||
}, | ||
} satisfies Meta<typeof Icon>; | ||
|
||
export const Basic: StoryObj<typeof Icon> = { | ||
args: { | ||
tone: "accent", | ||
muted: true, | ||
size: "xl", | ||
}, | ||
}; | ||
|
||
export const Sizes: StoryObj<typeof Icon> = { | ||
render: (args) => { | ||
return ( | ||
<div className={vstack({ gap: "6" })}> | ||
<Icon {...args} size="xs" /> | ||
<Icon {...args} size="sm" /> | ||
<Icon {...args} size="md" /> | ||
<Icon {...args} size="lg" /> | ||
<Icon {...args} size="xl" /> | ||
</div> | ||
); | ||
}, | ||
argTypes: { | ||
size: { | ||
control: false, | ||
}, | ||
}, | ||
args: { | ||
tone: "accent", | ||
muted: true, | ||
}, | ||
}; | ||
|
||
export const Tones: StoryObj<typeof Icon> = { | ||
render: (args) => { | ||
return ( | ||
<div className={vstack({ gap: "6" })}> | ||
<Icon {...args} tone="neutral" /> | ||
<Icon {...args} tone="accent" /> | ||
<Icon {...args} tone="danger" /> | ||
<Icon {...args} tone="warning" /> | ||
</div> | ||
); | ||
}, | ||
argTypes: { | ||
tone: { | ||
control: false, | ||
}, | ||
}, | ||
args: { | ||
muted: true, | ||
}, | ||
}; | ||
|
||
export const Contrasts: StoryObj<typeof Icon> = { | ||
render: (args) => { | ||
return ( | ||
<div className={vstack({ gap: "6" })}> | ||
<Text {...args} muted> | ||
낮은 <Icon name="moon" /> 명암비 | ||
</Text> | ||
<Text {...args}> | ||
높은 <Icon name="sun" /> 명암비 | ||
</Text> | ||
</div> | ||
); | ||
}, | ||
argTypes: { | ||
name: { | ||
control: false, | ||
}, | ||
muted: { | ||
control: false, | ||
}, | ||
}, | ||
}; | ||
|
||
export const WithHeading: StoryObj<typeof Icon> = { | ||
render: (args) => { | ||
return ( | ||
<Heading level={2}> | ||
<Icon {...args} name="user" /> | ||
프로필 | ||
</Heading> | ||
); | ||
}, | ||
argTypes: { | ||
name: { | ||
control: false, | ||
}, | ||
}, | ||
}; |
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,44 @@ | ||
import { composeStories } from "@storybook/react"; | ||
import { render } from "@testing-library/react"; | ||
import { expect, test } from "vitest"; | ||
import * as stories from "./Icon.stories"; | ||
|
||
const { Basic } = composeStories(stories); | ||
|
||
test("renders an svg element", () => { | ||
const { container } = render(<Basic />); | ||
|
||
expect(container.querySelector("svg")).toBeInTheDocument(); | ||
}); | ||
|
||
test.each([ | ||
["xs", "w_1em h_1em"], | ||
["sm", "w_1.25em h_1.25em"], | ||
["md", "w_1.5em h_1.5em"], | ||
["lg", "w_1.875em h_1.875em"], | ||
["xl", "w_2.25em h_2.25em"], | ||
] as const)('applies the correct class for size="%s"', (size, className) => { | ||
const { container } = render(<Basic size={size} />); | ||
|
||
expect(container.querySelector("svg")).toHaveClass(className); | ||
}); | ||
|
||
test.each([ | ||
["neutral", "c_text"], | ||
["accent", "c_text.accent"], | ||
["danger", "c_text.danger"], | ||
["warning", "c_text.warning"], | ||
] as const)('applies the correct class for tone="%s"', (tone, className) => { | ||
const { container } = render(<Basic tone={tone} muted={false} />); | ||
|
||
expect(container.querySelector("svg")).toHaveClass(className); | ||
}); | ||
|
||
test.each([ | ||
[false, "c_text"], | ||
[true, "c_text.muted"], | ||
] as const)("applies the correct class for muted={%s}", (muted, className) => { | ||
const { container } = render(<Basic tone="neutral" muted={muted} />); | ||
|
||
expect(container.querySelector("svg")).toHaveClass(className); | ||
}); |
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,116 @@ | ||
import { css, cva } from "../../../styled-system/css"; | ||
import type { Tone } from "../../tokens/colors"; | ||
import { type IconName, icons } from "../../tokens/iconography"; | ||
export interface IconProps { | ||
/** 이름 */ | ||
name: IconName; | ||
/** 색조 */ | ||
tone?: Tone; | ||
/** 크기 */ | ||
size?: "xs" | "sm" | "md" | "lg" | "xl"; | ||
/** 명암비 낮출지 */ | ||
muted?: boolean; | ||
} | ||
|
||
/** | ||
* - `name` 속성으로 어떤 모양의 아이콘을 사용할지 지정할 수 있습니다. | ||
* - 아이콘의 기본 크기는 부모 요소에서 설정한 글자 크기의 1.5배이며, `size` 속성을 통해서 크기를 변경할 수 있습니다. | ||
* - 아이콘의 기본 색상은 부모 요소에서 설정한 글자 색상과 동일하며, `tone` 속성과 `muted` 속성을 통해서 색상을 변경할 수 있습니다. | ||
*/ | ||
export const Icon = ({ | ||
name, | ||
size, | ||
tone, | ||
muted = false, | ||
...rest | ||
}: IconProps) => { | ||
const Tag = icons[name]; | ||
|
||
return ( | ||
<Tag | ||
className={css( | ||
sizeStyles.raw({ size }), | ||
colorStyles.raw({ tone, muted }), | ||
css.raw({ | ||
display: "inline-block", | ||
}) | ||
)} | ||
{...rest} | ||
/> | ||
); | ||
}; | ||
|
||
const sizeStyles = cva({ | ||
variants: { | ||
size: { | ||
xs: { | ||
width: "1em", | ||
height: "1em", | ||
}, | ||
sm: { | ||
width: "1.25em", | ||
height: "1.25em", | ||
}, | ||
md: { | ||
width: "1.5em", | ||
height: "1.5em", | ||
}, | ||
lg: { | ||
width: "1.875em", | ||
height: "1.875em", | ||
}, | ||
xl: { | ||
width: "2.25em", | ||
height: "2.25em", | ||
}, | ||
}, | ||
}, | ||
defaultVariants: { | ||
size: "md", | ||
}, | ||
}); | ||
|
||
const colorStyles = cva({ | ||
compoundVariants: [ | ||
{ | ||
muted: false, | ||
tone: "neutral", | ||
css: { color: "text" }, | ||
}, | ||
{ | ||
muted: false, | ||
tone: "accent", | ||
css: { color: "text.accent" }, | ||
}, | ||
{ | ||
muted: false, | ||
tone: "danger", | ||
css: { color: "text.danger" }, | ||
}, | ||
{ | ||
muted: false, | ||
tone: "warning", | ||
css: { color: "text.warning" }, | ||
}, | ||
{ | ||
muted: true, | ||
tone: "neutral", | ||
css: { color: "text.muted" }, | ||
}, | ||
{ | ||
muted: true, | ||
tone: "accent", | ||
css: { color: "text.muted.accent" }, | ||
}, | ||
{ | ||
muted: true, | ||
tone: "danger", | ||
css: { color: "text.muted.danger" }, | ||
}, | ||
{ | ||
muted: true, | ||
tone: "warning", | ||
css: { color: "text.muted.warning" }, | ||
}, | ||
], | ||
}); |
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 @@ | ||
export { Icon as Text } from "./Icon"; |
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