diff --git a/flexisvg.config.ts b/flexisvg.config.ts new file mode 100644 index 00000000..9f6627ae --- /dev/null +++ b/flexisvg.config.ts @@ -0,0 +1,10 @@ +import { SpriteGeneratorConfig } from 'flexisvg'; + +const config: SpriteGeneratorConfig = { + dynamicDir: 'public/icons/dynamic', + resizableDir: 'public/icons/resizable', + outputSpriteDir: 'public/icons', + outputComponentPath: 'src/components/icon/index.tsx', +}; + +export default config; diff --git a/package.json b/package.json index fbeb6029..48b89e2d 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ "eslint-plugin-perfectionist": "^4.15.1", "eslint-plugin-simple-import-sort": "^12.1.1", "eslint-plugin-storybook": "^10.0.5", + "flexisvg": "^1.1.0", "husky": "^9.1.7", "jest": "^30.2.0", "jest-environment-jsdom": "^30.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1df65272..b401ceba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -132,6 +132,9 @@ importers: eslint-plugin-storybook: specifier: ^10.0.5 version: 10.0.5(eslint@9.37.0(jiti@2.6.1))(storybook@10.0.6(@testing-library/dom@10.4.1)(msw@2.11.5(@types/node@20.19.21)(typescript@5.9.3))(prettier@3.6.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(typescript@5.9.3) + flexisvg: + specifier: ^1.1.0 + version: 1.1.0 husky: specifier: ^9.1.7 version: 9.1.7 @@ -3064,6 +3067,10 @@ packages: resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} engines: {node: '>=16'} + commander@12.1.0: + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} + commander@14.0.1: resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} engines: {node: '>=20'} @@ -3811,6 +3818,11 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + flexisvg@1.1.0: + resolution: {integrity: sha512-RG+Y5xLiQ5APlONxsh8fg24/xtwOO7viVcRCbdaJV4Xcl9bV7Sq+G9o3ZOThWXfm6qrI+l5Qtmgc9sBJgJM8KQ==} + engines: {node: '>=18.0.0', pnpm: '>=8.0.0'} + hasBin: true + fn.name@1.1.0: resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} @@ -9955,6 +9967,8 @@ snapshots: commander@11.1.0: {} + commander@12.1.0: {} + commander@14.0.1: {} commander@2.20.3: {} @@ -10903,6 +10917,14 @@ snapshots: flatted@3.3.3: {} + flexisvg@1.1.0: + dependencies: + commander: 12.1.0 + jiti: 2.6.1 + prettier: 3.6.2 + svg-sprite: 2.0.4 + svgo: 3.3.2 + fn.name@1.1.0: {} follow-redirects@1.15.11: {} diff --git a/public/icons/dynamic/icon-arrow-down.svg b/public/icons/dynamic/icon-arrow-down.svg new file mode 100644 index 00000000..25d2c4aa --- /dev/null +++ b/public/icons/dynamic/icon-arrow-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-arrow-up.svg b/public/icons/dynamic/icon-arrow-up.svg new file mode 100644 index 00000000..e39a8d98 --- /dev/null +++ b/public/icons/dynamic/icon-arrow-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-bell-read.svg b/public/icons/dynamic/icon-bell-read.svg new file mode 100644 index 00000000..0f60abf8 --- /dev/null +++ b/public/icons/dynamic/icon-bell-read.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-calendar-1.svg b/public/icons/dynamic/icon-calendar-1.svg new file mode 100644 index 00000000..91adfd5b --- /dev/null +++ b/public/icons/dynamic/icon-calendar-1.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/dynamic/icon-calendar-2.svg b/public/icons/dynamic/icon-calendar-2.svg new file mode 100644 index 00000000..a693911a --- /dev/null +++ b/public/icons/dynamic/icon-calendar-2.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/public/icons/dynamic/icon-chevron-left-1.svg b/public/icons/dynamic/icon-chevron-left-1.svg new file mode 100644 index 00000000..d06f5969 --- /dev/null +++ b/public/icons/dynamic/icon-chevron-left-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-chevron-left-2.svg b/public/icons/dynamic/icon-chevron-left-2.svg new file mode 100644 index 00000000..fc6f8105 --- /dev/null +++ b/public/icons/dynamic/icon-chevron-left-2.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-chevron-right-1.svg b/public/icons/dynamic/icon-chevron-right-1.svg new file mode 100644 index 00000000..e50cbb2f --- /dev/null +++ b/public/icons/dynamic/icon-chevron-right-1.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-clock.svg b/public/icons/dynamic/icon-clock.svg new file mode 100644 index 00000000..7a6b9017 --- /dev/null +++ b/public/icons/dynamic/icon-clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/icon-title.svg b/public/icons/dynamic/icon-edit-bar.svg similarity index 100% rename from public/icons/icon-title.svg rename to public/icons/dynamic/icon-edit-bar.svg diff --git a/public/icons/icon-edit.svg b/public/icons/dynamic/icon-edit.svg similarity index 100% rename from public/icons/icon-edit.svg rename to public/icons/dynamic/icon-edit.svg diff --git a/public/icons/dynamic/icon-heart.svg b/public/icons/dynamic/icon-heart.svg new file mode 100644 index 00000000..cb4f637b --- /dev/null +++ b/public/icons/dynamic/icon-heart.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/icon-home.svg b/public/icons/dynamic/icon-home.svg similarity index 61% rename from public/icons/icon-home.svg rename to public/icons/dynamic/icon-home.svg index cfd1de24..430590c1 100644 --- a/public/icons/icon-home.svg +++ b/public/icons/dynamic/icon-home.svg @@ -1,4 +1,4 @@ - - + + diff --git a/public/icons/dynamic/icon-kebab.svg b/public/icons/dynamic/icon-kebab.svg new file mode 100644 index 00000000..ddeaa535 --- /dev/null +++ b/public/icons/dynamic/icon-kebab.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/icons/dynamic/icon-map-pin-1.svg b/public/icons/dynamic/icon-map-pin-1.svg new file mode 100644 index 00000000..11c40bd5 --- /dev/null +++ b/public/icons/dynamic/icon-map-pin-1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-map-pin-2.svg b/public/icons/dynamic/icon-map-pin-2.svg new file mode 100644 index 00000000..68c5daff --- /dev/null +++ b/public/icons/dynamic/icon-map-pin-2.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/dynamic/icon-plus.svg b/public/icons/dynamic/icon-plus.svg new file mode 100644 index 00000000..c2035bda --- /dev/null +++ b/public/icons/dynamic/icon-plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/icon-search.svg b/public/icons/dynamic/icon-search.svg similarity index 100% rename from public/icons/icon-search.svg rename to public/icons/dynamic/icon-search.svg diff --git a/public/icons/dynamic/icon-send.svg b/public/icons/dynamic/icon-send.svg new file mode 100644 index 00000000..98202d16 --- /dev/null +++ b/public/icons/dynamic/icon-send.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/public/icons/dynamic/icon-small-x-1.svg b/public/icons/dynamic/icon-small-x-1.svg new file mode 100644 index 00000000..33f1a4e7 --- /dev/null +++ b/public/icons/dynamic/icon-small-x-1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-small-x-2.svg b/public/icons/dynamic/icon-small-x-2.svg new file mode 100644 index 00000000..35043731 --- /dev/null +++ b/public/icons/dynamic/icon-small-x-2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-symbol.svg b/public/icons/dynamic/icon-symbol.svg new file mode 100644 index 00000000..53d0a7a1 --- /dev/null +++ b/public/icons/dynamic/icon-symbol.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/icons/dynamic/icon-tag.svg b/public/icons/dynamic/icon-tag.svg new file mode 100644 index 00000000..c0b2182c --- /dev/null +++ b/public/icons/dynamic/icon-tag.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/icon-user.svg b/public/icons/dynamic/icon-user-1.svg similarity index 62% rename from public/icons/icon-user.svg rename to public/icons/dynamic/icon-user-1.svg index f68c4cc0..f1048acf 100644 --- a/public/icons/icon-user.svg +++ b/public/icons/dynamic/icon-user-1.svg @@ -1,4 +1,4 @@ - - + + diff --git a/public/icons/dynamic/icon-user-2.svg b/public/icons/dynamic/icon-user-2.svg new file mode 100644 index 00000000..ac4ef26c --- /dev/null +++ b/public/icons/dynamic/icon-user-2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-users-1.svg b/public/icons/dynamic/icon-users-1.svg new file mode 100644 index 00000000..78dfa1d4 --- /dev/null +++ b/public/icons/dynamic/icon-users-1.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/dynamic/icon-users-2.svg b/public/icons/dynamic/icon-users-2.svg new file mode 100644 index 00000000..576781d9 --- /dev/null +++ b/public/icons/dynamic/icon-users-2.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/public/icons/dynamic/icon-x-1.svg b/public/icons/dynamic/icon-x-1.svg new file mode 100644 index 00000000..ccdf58d2 --- /dev/null +++ b/public/icons/dynamic/icon-x-1.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/dynamic/icon-x-2.svg b/public/icons/dynamic/icon-x-2.svg new file mode 100644 index 00000000..fe3eefe1 --- /dev/null +++ b/public/icons/dynamic/icon-x-2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/icon-calendar.svg b/public/icons/icon-calendar.svg deleted file mode 100644 index 6583bf3e..00000000 --- a/public/icons/icon-calendar.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/public/icons/icon-chevron-down.svg b/public/icons/icon-chevron-down.svg deleted file mode 100644 index bc27243d..00000000 --- a/public/icons/icon-chevron-down.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/icons/icon-chevron-up.svg b/public/icons/icon-chevron-up.svg deleted file mode 100644 index 31074b7d..00000000 --- a/public/icons/icon-chevron-up.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/icons/icon-cowbell.svg b/public/icons/icon-cowbell.svg deleted file mode 100644 index 0ba96114..00000000 --- a/public/icons/icon-cowbell.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/icons/icon-map-pin.svg b/public/icons/icon-map-pin.svg deleted file mode 100644 index e7fa1b8b..00000000 --- a/public/icons/icon-map-pin.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/icon-message.svg b/public/icons/icon-message.svg deleted file mode 100644 index ed632a1e..00000000 --- a/public/icons/icon-message.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/icons/icon-plus.svg b/public/icons/icon-plus.svg deleted file mode 100644 index 161e9133..00000000 --- a/public/icons/icon-plus.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/icon-small-x.svg b/public/icons/icon-small-x.svg deleted file mode 100644 index 57354fb0..00000000 --- a/public/icons/icon-small-x.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/icon-tag.svg b/public/icons/icon-tag.svg deleted file mode 100644 index 542c527d..00000000 --- a/public/icons/icon-tag.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/icon-unread-false.svg b/public/icons/icon-unread-false.svg deleted file mode 100644 index 2a46a1fd..00000000 --- a/public/icons/icon-unread-false.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/icon-unread-true.svg b/public/icons/icon-unread-true.svg deleted file mode 100644 index 0ba96114..00000000 --- a/public/icons/icon-unread-true.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/public/icons/icon-users.svg b/public/icons/icon-users.svg deleted file mode 100644 index 19b1f407..00000000 --- a/public/icons/icon-users.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/public/icons/icon-visibility-false.svg b/public/icons/icon-visibility-false.svg deleted file mode 100644 index 3eb7ddfe..00000000 --- a/public/icons/icon-visibility-false.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/icons/icon-visibility-true.svg b/public/icons/icon-visibility-true.svg deleted file mode 100644 index 180d156b..00000000 --- a/public/icons/icon-visibility-true.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/public/icons/icon-x.svg b/public/icons/icon-x.svg deleted file mode 100644 index 8785446e..00000000 --- a/public/icons/icon-x.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/public/icons/resizable/icon-bell-unread.svg b/public/icons/resizable/icon-bell-unread.svg new file mode 100644 index 00000000..312d03cf --- /dev/null +++ b/public/icons/resizable/icon-bell-unread.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/icons/icon-congratulate.svg b/public/icons/resizable/icon-congratulate.svg similarity index 100% rename from public/icons/icon-congratulate.svg rename to public/icons/resizable/icon-congratulate.svg diff --git a/public/icons/resizable/icon-message-read-activate.svg b/public/icons/resizable/icon-message-read-activate.svg new file mode 100644 index 00000000..f740fa51 --- /dev/null +++ b/public/icons/resizable/icon-message-read-activate.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/resizable/icon-message-read.svg b/public/icons/resizable/icon-message-read.svg new file mode 100644 index 00000000..0a99cddc --- /dev/null +++ b/public/icons/resizable/icon-message-read.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/resizable/icon-message-unread-activate.svg b/public/icons/resizable/icon-message-unread-activate.svg new file mode 100644 index 00000000..22660789 --- /dev/null +++ b/public/icons/resizable/icon-message-unread-activate.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/resizable/icon-message-unread.svg b/public/icons/resizable/icon-message-unread.svg new file mode 100644 index 00000000..d33bff8d --- /dev/null +++ b/public/icons/resizable/icon-message-unread.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/icon-plus-circle.svg b/public/icons/resizable/icon-plus-circle.svg similarity index 100% rename from public/icons/icon-plus-circle.svg rename to public/icons/resizable/icon-plus-circle.svg diff --git a/public/icons/resizable/icon-visibility-false.svg b/public/icons/resizable/icon-visibility-false.svg new file mode 100644 index 00000000..6117a12b --- /dev/null +++ b/public/icons/resizable/icon-visibility-false.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/resizable/icon-visibility-true.svg b/public/icons/resizable/icon-visibility-true.svg new file mode 100644 index 00000000..dd94ee30 --- /dev/null +++ b/public/icons/resizable/icon-visibility-true.svg @@ -0,0 +1,4 @@ + + + + diff --git a/public/icons/icon-wego-logo.svg b/public/icons/resizable/icon-wego-logo.svg similarity index 100% rename from public/icons/icon-wego-logo.svg rename to public/icons/resizable/icon-wego-logo.svg diff --git a/public/icons/sprite.svg b/public/icons/sprite.svg new file mode 100644 index 00000000..803d8422 --- /dev/null +++ b/public/icons/sprite.svg @@ -0,0 +1,448 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/sprite.svg b/public/sprite.svg deleted file mode 100644 index ce371dd8..00000000 --- a/public/sprite.svg +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/scripts/sprite/generate-sprite.cjs b/scripts/sprite/generate-sprite.cjs deleted file mode 100644 index 3a482e25..00000000 --- a/scripts/sprite/generate-sprite.cjs +++ /dev/null @@ -1,174 +0,0 @@ -// scripts/sprite/generate-sprite.cjs -const fs = require('fs'); -const path = require('path'); -const SVGSpriter = require('svg-sprite'); -const prettier = require('prettier'); - -// 색상 변환 적용 파일명 목록 -const INCLUDE_COLOR_TRANSFORM = [ - 'calendar', - 'chevron-down', - 'chevron-up', - // 'congratulate', - // 'cowbell', - 'home', - 'map-pin', - 'message', - // 'plus-circle', - 'plus', - 'search', - 'small-x', - // 'tag', - // 'title', - 'unread-false', - 'unread-true', - 'user', - 'users', - // 'visibility-false', - // 'visibility-true', - // 'wego-logo', - 'x', -]; - -const config = { - mode: { - symbol: { - dest: 'public', - sprite: 'sprite.svg', - }, - }, - shape: { - id: { - generator: (name) => { - const baseName = path.basename(name, '.svg'); - return baseName.replace(/^icon-/, ''); - }, - }, - transform: [ - function (shape, _sprite, callback) { - const filePath = shape.name || shape.id || shape.base; - - if (!filePath) { - callback(null); - return; - } - - const fileName = path.basename(filePath, '.svg').replace(/^icon-/, ''); - const shouldTransformColors = INCLUDE_COLOR_TRANSFORM.includes(fileName); - - const svgoConfig = { - plugins: [ - 'preset-default', - ...(shouldTransformColors - ? [ - { - name: 'convertColors', - params: { - currentColor: true, - }, - }, - { - name: 'removeAttrs', - params: { - attrs: '(stroke|fill):(none|black|#000000)', - }, - }, - ] - : []), - ], - }; - - const { optimize } = require('svgo'); - const result = optimize(shape.getSVG(), svgoConfig); - shape.setSVG(result.data); - callback(null); - }, - ], - }, -}; - -// TypeScript 타입 파일 생성 함수 -async function generateTypeFile(iconIds) { - const icons = iconIds.map((id) => ({ - id, - enableChangeColor: INCLUDE_COLOR_TRANSFORM.includes(id), - })); - - const typeContent = `// This file is auto-generated. Do not edit manually. - -export const ICONS = [ - ${icons.map((icon) => `{ id: '${icon.id}', enableChangeColor: ${icon.enableChangeColor} }`).join(',\n ')}, -] as const; - -export type IconId = typeof ICONS[number]['id']; -`; - - const typesDir = path.join(__dirname, '../../src/types/icons'); - const typeFilePath = path.join(typesDir, 'index.ts'); - - try { - const formatted = await prettier.format(typeContent, { - parser: 'typescript', - printWidth: 100, - tabWidth: 2, - singleQuote: true, - trailingComma: 'all', - }); - - fs.mkdirSync(typesDir, { recursive: true }); - fs.writeFileSync(typeFilePath, formatted); - console.log('✅ Type file generated:', typeFilePath); - } catch (err) { - console.error('⚠️ Type file generation failed:', err.message); - } -} - -const spriter = new SVGSpriter(config); -const iconIds = []; - -const iconsDir = path.join(__dirname, '../../public/icons'); -const files = fs.readdirSync(iconsDir); - -files.forEach((file) => { - if (file.endsWith('.svg')) { - const filePath = path.join(iconsDir, file); - const content = fs.readFileSync(filePath, 'utf8'); - const iconId = path.basename(file, '.svg').replace(/^icon-/, ''); - iconIds.push(iconId); - spriter.add(filePath, null, content); - } -}); - -spriter.compile(async (error, result) => { - if (error) { - console.error('❌ Error generating sprite:', error); - return; - } - - for (const mode in result) { - for (const resource in result[mode]) { - const outputPath = result[mode][resource].path; - const content = result[mode][resource].contents.toString(); - - try { - const formatted = await prettier.format(content, { - parser: 'html', - printWidth: 100, - tabWidth: 2, - }); - - fs.mkdirSync(path.dirname(outputPath), { recursive: true }); - fs.writeFileSync(outputPath, formatted); - } catch (err) { - console.error('⚠️ Formatting failed, saving unformatted:', err.message); - fs.mkdirSync(path.dirname(outputPath), { recursive: true }); - fs.writeFileSync(outputPath, content); - } - } - } - - console.log('✅ Sprite generated and formatted!'); - - // 타입 파일 생성 - await generateTypeFile(iconIds.sort()); -}); diff --git a/src/components/icon/index.stories.tsx b/src/components/icon/index.stories.tsx index 4a5364fa..623e2f08 100644 --- a/src/components/icon/index.stories.tsx +++ b/src/components/icon/index.stories.tsx @@ -3,9 +3,7 @@ import { useState } from 'react'; import type { Meta, StoryObj } from '@storybook/nextjs'; -import { ICONS } from '@/types/icons'; - -import { Icon } from '.'; +import { Icon, IconId, iconMetadataMap } from '.'; const meta = { title: 'Components/Icon', @@ -17,7 +15,7 @@ const meta = { argTypes: { id: { control: 'select', - options: ICONS.map((icon) => icon.id), + options: iconMetadataMap.map((icon) => icon.id), description: 'Icon identifier', }, className: { @@ -34,7 +32,7 @@ export default meta; type Story = StoryObj; // 표 형식 갤러리 -const iconData = ICONS; +const iconData = iconMetadataMap; export const IconTable: Story = { args: { @@ -52,7 +50,7 @@ export const IconTable: Story = { return ( - + {/* 색상 토글 */} @@ -114,36 +112,52 @@ export const IconTable: Story = { ID - Enable Change Color + Color Custom + Size Custom Icon Example Code - {iconData.map(({ id, enableChangeColor }) => ( - - {id} - - - {enableChangeColor ? '✅' : '❌'} - - - - - - - - {``} - - - - ))} + {iconData.map(({ id, variant }) => { + const enableChangeColor = variant === 'dynamic'; + const enableResize = true; + return ( + + {id} + + + {enableChangeColor ? '✅' : '❌'} + + + + + {enableResize ? '✅' : '❌'} + + + + + + + + {``} + + + + ); + })} diff --git a/src/components/icon/index.tsx b/src/components/icon/index.tsx index f1d52227..55d330da 100644 --- a/src/components/icon/index.tsx +++ b/src/components/icon/index.tsx @@ -1,15 +1,220 @@ +// This file is auto-generated. Do not edit manually. import { type ComponentProps } from 'react'; -import { IconId } from '@/types/icons'; +import type { IconMetadata } from 'flexisvg'; + +export type DynamicIconId = + | 'arrow-down' + | 'arrow-up' + | 'bell-read' + | 'calendar-1' + | 'calendar-2' + | 'chevron-left-1' + | 'chevron-left-2' + | 'chevron-right-1' + | 'clock' + | 'edit-bar' + | 'edit' + | 'heart' + | 'home' + | 'kebab' + | 'map-pin-1' + | 'map-pin-2' + | 'plus' + | 'search' + | 'send' + | 'small-x-1' + | 'small-x-2' + | 'symbol' + | 'tag' + | 'user-1' + | 'user-2' + | 'users-1' + | 'users-2' + | 'x-1' + | 'x-2'; +export type ResizableIconId = + | 'bell-unread' + | 'congratulate' + | 'message-read-activate' + | 'message-read' + | 'message-unread-activate' + | 'message-unread' + | 'plus-circle' + | 'visibility-false' + | 'visibility-true' + | 'wego-logo'; + +export type IconId = DynamicIconId | ResizableIconId; type IconProps = ComponentProps<'svg'> & { id: IconId; + size?: number; }; -export const Icon = ({ id, ...props }: IconProps) => { +export const Icon = ({ id, size = 24, ...props }: IconProps) => { return ( - - + + ); }; + +export const iconMetadataMap: IconMetadata[] = [ + { + id: 'arrow-down', + variant: 'dynamic', + }, + { + id: 'arrow-up', + variant: 'dynamic', + }, + { + id: 'bell-read', + variant: 'dynamic', + }, + { + id: 'calendar-1', + variant: 'dynamic', + }, + { + id: 'calendar-2', + variant: 'dynamic', + }, + { + id: 'chevron-left-1', + variant: 'dynamic', + }, + { + id: 'chevron-left-2', + variant: 'dynamic', + }, + { + id: 'chevron-right-1', + variant: 'dynamic', + }, + { + id: 'clock', + variant: 'dynamic', + }, + { + id: 'edit-bar', + variant: 'dynamic', + }, + { + id: 'edit', + variant: 'dynamic', + }, + { + id: 'heart', + variant: 'dynamic', + }, + { + id: 'home', + variant: 'dynamic', + }, + { + id: 'kebab', + variant: 'dynamic', + }, + { + id: 'map-pin-1', + variant: 'dynamic', + }, + { + id: 'map-pin-2', + variant: 'dynamic', + }, + { + id: 'plus', + variant: 'dynamic', + }, + { + id: 'search', + variant: 'dynamic', + }, + { + id: 'send', + variant: 'dynamic', + }, + { + id: 'small-x-1', + variant: 'dynamic', + }, + { + id: 'small-x-2', + variant: 'dynamic', + }, + { + id: 'symbol', + variant: 'dynamic', + }, + { + id: 'tag', + variant: 'dynamic', + }, + { + id: 'user-1', + variant: 'dynamic', + }, + { + id: 'user-2', + variant: 'dynamic', + }, + { + id: 'users-1', + variant: 'dynamic', + }, + { + id: 'users-2', + variant: 'dynamic', + }, + { + id: 'x-1', + variant: 'dynamic', + }, + { + id: 'x-2', + variant: 'dynamic', + }, + { + id: 'bell-unread', + variant: 'resizable', + }, + { + id: 'congratulate', + variant: 'resizable', + }, + { + id: 'message-read-activate', + variant: 'resizable', + }, + { + id: 'message-read', + variant: 'resizable', + }, + { + id: 'message-unread-activate', + variant: 'resizable', + }, + { + id: 'message-unread', + variant: 'resizable', + }, + { + id: 'plus-circle', + variant: 'resizable', + }, + { + id: 'visibility-false', + variant: 'resizable', + }, + { + id: 'visibility-true', + variant: 'resizable', + }, + { + id: 'wego-logo', + variant: 'resizable', + }, +]; diff --git a/src/components/layout/gnb/index.tsx b/src/components/layout/gnb/index.tsx index fb56d4ff..cc673c8f 100644 --- a/src/components/layout/gnb/index.tsx +++ b/src/components/layout/gnb/index.tsx @@ -25,7 +25,7 @@ const NAV_MENU = [ }, { path: '/schedule', - svgId: 'calendar', + svgId: 'calendar-1', }, { path: '/post-meetup', @@ -33,10 +33,10 @@ const NAV_MENU = [ }, { path: '/message', - svgId: 'message', + svgId: 'message-read', }, { path: '/mypage', - svgId: 'user', + svgId: 'user-1', }, ] as const; diff --git a/src/components/layout/header/index.tsx b/src/components/layout/header/index.tsx index 3510ae02..ff113993 100644 --- a/src/components/layout/header/index.tsx +++ b/src/components/layout/header/index.tsx @@ -10,7 +10,7 @@ export const Header = () => { - + diff --git a/src/components/pages/meetup/meetup-descriptions/description-sections/description-setting/index.tsx b/src/components/pages/meetup/meetup-descriptions/description-sections/description-setting/index.tsx index c1c1ca2f..e29583c1 100644 --- a/src/components/pages/meetup/meetup-descriptions/description-sections/description-setting/index.tsx +++ b/src/components/pages/meetup/meetup-descriptions/description-sections/description-setting/index.tsx @@ -11,11 +11,11 @@ export const DescriptionSetting = ({ location, date, time }: Props) => { - + {location} - + {date} - {time} diff --git a/src/components/pages/meetup/meetup-members/index.tsx b/src/components/pages/meetup/meetup-members/index.tsx index 12c54a8a..2c5ee61d 100644 --- a/src/components/pages/meetup/meetup-members/index.tsx +++ b/src/components/pages/meetup/meetup-members/index.tsx @@ -82,7 +82,7 @@ export const MeetupMembers = ({ members }: Props) => { onClick={onShowMoreClick} > {showMore ? '접기' : '더보기'} - + )} diff --git a/src/components/pages/post-meetup/fields/address-field/index.tsx b/src/components/pages/post-meetup/fields/address-field/index.tsx index c3944587..92cee659 100644 --- a/src/components/pages/post-meetup/fields/address-field/index.tsx +++ b/src/components/pages/post-meetup/fields/address-field/index.tsx @@ -20,7 +20,7 @@ export const MeetupAddressField = ({ field }: Props) => { className='bg-mono-white focus:border-mint-500 rounded-2xl border border-gray-300' frontIcon={ { className='bg-mono-white focus:border-mint-500 rounded-2xl border border-gray-300' frontIcon={ { className='bg-mono-white focus:border-mint-500 rounded-2xl border border-gray-300' frontIcon={ { aria-label='이미지 삭제 버튼' onClick={() => onRemoveImageClick(url)} > - + ))} diff --git a/src/components/pages/post-meetup/fields/tags-field/index.tsx b/src/components/pages/post-meetup/fields/tags-field/index.tsx index db2911b7..bd5f436c 100644 --- a/src/components/pages/post-meetup/fields/tags-field/index.tsx +++ b/src/components/pages/post-meetup/fields/tags-field/index.tsx @@ -32,7 +32,7 @@ export const MeetupTagsField = ({ field }: Props) => { #태그 - + diff --git a/src/components/pages/post-meetup/fields/title-field/index.tsx b/src/components/pages/post-meetup/fields/title-field/index.tsx index 52d315f2..8c53ce4e 100644 --- a/src/components/pages/post-meetup/fields/title-field/index.tsx +++ b/src/components/pages/post-meetup/fields/title-field/index.tsx @@ -21,7 +21,7 @@ export const MeetupTitleField = ({ field }: Props) => { className='bg-mono-white focus:border-mint-500 rounded-2xl border border-gray-300' frontIcon={ - + - - + + { type='button' onClick={close} > - + ); }; diff --git a/src/types/icons/index.ts b/src/types/icons/index.ts deleted file mode 100644 index 808c17f8..00000000 --- a/src/types/icons/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -// This file is auto-generated. Do not edit manually. - -export const ICONS = [ - { id: 'calendar', enableChangeColor: true }, - { id: 'chevron-down', enableChangeColor: true }, - { id: 'chevron-up', enableChangeColor: true }, - { id: 'congratulate', enableChangeColor: false }, - { id: 'cowbell', enableChangeColor: false }, - { id: 'edit', enableChangeColor: false }, - { id: 'home', enableChangeColor: true }, - { id: 'map-pin', enableChangeColor: true }, - { id: 'message', enableChangeColor: true }, - { id: 'plus', enableChangeColor: true }, - { id: 'plus-circle', enableChangeColor: false }, - { id: 'search', enableChangeColor: true }, - { id: 'small-x', enableChangeColor: true }, - { id: 'tag', enableChangeColor: false }, - { id: 'title', enableChangeColor: false }, - { id: 'unread-false', enableChangeColor: true }, - { id: 'unread-true', enableChangeColor: true }, - { id: 'user', enableChangeColor: true }, - { id: 'users', enableChangeColor: true }, - { id: 'visibility-false', enableChangeColor: false }, - { id: 'visibility-true', enableChangeColor: false }, - { id: 'wego-logo', enableChangeColor: false }, - { id: 'x', enableChangeColor: true }, -] as const; - -export type IconId = (typeof ICONS)[number]['id'];
- {``} -
+ {``} +
{location}
{date} - {time}
#태그