Skip to content

Commit f8dcc6a

Browse files
feat: Icon 컴포넌트 및 스토리북 추가
1 parent 23f306e commit f8dcc6a

File tree

4 files changed

+194
-0
lines changed

4 files changed

+194
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Meta, StoryObj } from '@storybook/nextjs'
2+
import { Icon } from './Icon'
3+
import { IconList } from './IconMap'
4+
import { Column } from '../Layout'
5+
6+
const meta: Meta<typeof Icon> = {
7+
title: 'Components/Icon',
8+
component: Icon,
9+
parameters: {
10+
layout: 'centered',
11+
},
12+
tags: ['autodocs'],
13+
}
14+
15+
export default meta
16+
type Story = StoryObj<typeof Icon>
17+
18+
// 단일 아이콘
19+
export const Default: Story = {
20+
args: {
21+
type: 'chicken',
22+
size: 48,
23+
},
24+
}
25+
26+
// 전체 아이콘
27+
export const AllIcons: Story = {
28+
render: () => (
29+
<Column className={'ui:gap-4'}>
30+
{IconList.map((type) => (
31+
<Column
32+
key={type}
33+
className={'ui:items-center ui:text-center ui:text-xs'}
34+
>
35+
<Icon type={type} size={40} />
36+
<span>{type}</span>
37+
</Column>
38+
))}
39+
</Column>
40+
),
41+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { iconMap, IconType } from './IconMap'
2+
import { SVGProps } from 'react'
3+
import '@repo/tailwind-config'
4+
5+
const IconColor = {
6+
'--color-main': '#313D4C',
7+
'--color-blue': '#3182F7',
8+
'--color-red': '#EF4452',
9+
'--color-white': '#FFFFFF',
10+
'--color-gray-50': '#F3F4F6',
11+
'--color-gray-100': '#E4E7EB',
12+
'--color-gray-200': '#B0B9C2',
13+
'--color-gray-300': '#6C7887',
14+
'--color-gray-400': '#3D3D3D',
15+
'--color-gray-500': '#403E3F',
16+
} as const
17+
18+
type IconColorType = keyof typeof IconColor
19+
20+
export type Props = {
21+
type: IconType
22+
size?: number
23+
color?: IconColorType
24+
} & Omit<SVGProps<SVGSVGElement>, 'color'>
25+
26+
/**
27+
* `iconMap`에 정의된 `type` 값을 기반으로 SVG 아이콘을 렌더링합니다.
28+
* `size`를 지정하면 아이콘의 `width`와 `height`가 동일하게 변경됩니다.
29+
*
30+
* @example
31+
* // 기본 아이콘
32+
* <Icon type="chicken" />
33+
*
34+
* @param props - Icon 컴포넌트 속성
35+
* @param props.type - 렌더링할 아이콘의 키값 (`iconMap`의 key)
36+
* @param [props.size=24] - 아이콘의 크기 (width, height에 동일 적용)
37+
* @param [props.color] - 아이콘의 색상
38+
* @returns 렌더링된 SVG 아이콘
39+
*/
40+
export function Icon({ type, size = 24, color, ...props }: Props) {
41+
const Icon = iconMap[type]
42+
43+
return (
44+
<Icon
45+
width={size}
46+
height={size}
47+
color={color ? IconColor[color] : undefined}
48+
{...props}
49+
/>
50+
)
51+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// 메뉴
2+
import { Asian } from './assets/icons/menu/asian'
3+
import { Bunsik } from './assets/icons/menu/bunsik'
4+
import { Burger } from './assets/icons/menu/burger'
5+
import { Cafe } from './assets/icons/menu/cafe'
6+
import { Chicken } from './assets/icons/menu/chicken'
7+
import { Chinese } from './assets/icons/menu/chinese'
8+
import { Japanese } from './assets/icons/menu/japanese'
9+
import { Korean } from './assets/icons/menu/korean'
10+
import { Lunchbox } from './assets/icons/menu/lunchbox'
11+
import { Meat } from './assets/icons/menu/meat'
12+
import { Mexican } from './assets/icons/menu/mexican'
13+
import { Pizza } from './assets/icons/menu/pizza'
14+
import { Salad } from './assets/icons/menu/salad'
15+
import { Soup } from './assets/icons/menu/soup'
16+
import { Western } from './assets/icons/menu/western'
17+
// 네비게이션
18+
import { Home } from './assets/icons/navigation/home'
19+
import { Map } from './assets/icons/navigation/map'
20+
import { CirclePlus } from './assets/icons/navigation/circlePlus'
21+
import { Heart as NavHeart } from './assets/icons/navigation/heart'
22+
import { User as NavUSer } from './assets/icons/navigation/user'
23+
// 태그
24+
import { FingerUp } from './assets/icons/tag/fingerUp'
25+
import { Calculator } from './assets/icons/tag/calculator'
26+
import { BlingBling } from './assets/icons/tag/blingBling'
27+
import { Waiter } from './assets/icons/tag/waiter'
28+
// 헤더
29+
import { MarkerWithMap } from './assets/icons/header/markerWithMap'
30+
import { Logo } from './assets/icons/header/logo'
31+
import { Heart as HeaderHeart } from './assets/icons/header/heart'
32+
import { User as HeaderUser } from './assets/icons/header/user'
33+
import { ShakingHeart } from './assets/icons/header/shakingHeart'
34+
35+
import { ArrowLeft } from './assets/icons/arrowLeft'
36+
import { ArrowRight } from './assets/icons/arrowRight'
37+
import { Search } from './assets/icons/search'
38+
import { FireHeart } from './assets/icons/fireHeart'
39+
import { Fire } from './assets/icons/fire'
40+
import { Marker } from './assets/icons/marker'
41+
import { Pin } from './assets/icons/pin'
42+
import { Note } from './assets/icons/note'
43+
import { Smile } from './assets/icons/smile'
44+
import { Cry } from './assets/icons/cry'
45+
import { KakaoLogo } from './assets/icons/kakaoLogo'
46+
import { Crosshairs } from './assets/icons/crosshairs'
47+
48+
export const iconMap = {
49+
// 메뉴
50+
asian: Asian, // 아시안
51+
bunsik: Bunsik, // 분식
52+
burger: Burger, // 햄버거
53+
cafe: Cafe, // 카페
54+
chicken: Chicken, // 치킨
55+
chinese: Chinese, // 중식
56+
japanese: Japanese, // 일식
57+
korean: Korean, // 한식
58+
lunchbox: Lunchbox, // 도시락
59+
meat: Meat, // 고기·구이
60+
mexican: Mexican, // 멕시칸
61+
pizza: Pizza, // 피자
62+
salad: Salad, // 샐러드
63+
soup: Soup, // 찜·탕
64+
western: Western, // 양식
65+
66+
// 네비게이션
67+
home: Home,
68+
map: Map,
69+
circlePlus: CirclePlus,
70+
navHeart: NavHeart,
71+
navUser: NavUSer,
72+
73+
// 태그
74+
fingerUp: FingerUp,
75+
calculator: Calculator,
76+
blingBling: BlingBling,
77+
waiter: Waiter,
78+
79+
// 헤더
80+
logo: Logo,
81+
markerWithMap: MarkerWithMap,
82+
headerHeart: HeaderHeart,
83+
headerUser: HeaderUser,
84+
shakingHeart: ShakingHeart,
85+
86+
arrowLeft: ArrowLeft,
87+
arrowRight: ArrowRight,
88+
search: Search,
89+
fireHeart: FireHeart,
90+
fire: Fire,
91+
marker: Marker,
92+
pin: Pin,
93+
note: Note,
94+
smile: Smile,
95+
cry: Cry,
96+
kakkoLogo: KakaoLogo,
97+
crosshairs: Crosshairs,
98+
}
99+
100+
export type IconType = keyof typeof iconMap
101+
export const IconList = Object.keys(iconMap) as IconType[]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { Icon } from './Icon'

0 commit comments

Comments
 (0)