diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index bbbf993..d43cd93 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,4 +5,4 @@ # the repo. Unless a later match takes precedence, # @global-owner1 and @global-owner2 will be requested for # review when someone opens a pull request. -* @HyunsDev @nijuy @Hanna922 \ No newline at end of file +* @nijuy @Hanna922 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..ba8765a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,13 @@ +# ISSUE โœ… : + +## ๐Ÿ“– Summary + +๋ฒ„๊ทธ๋ฅผ ๊ฐ„๋‹จํžˆ ์š”์•ฝํ•ด์ฃผ์„ธ์š”. + +## Error Script + +์—๋Ÿฌ ๋‚ด์šฉ ์ „์ฒด๋ฅผ ์ฒจ๋ถ€ํ•ด์ฃผ์„ธ์š”. + +## Photo + +๋ฒ„๊ทธ ์žฌํ˜„ ์Šคํฌ๋ฆฐ์ƒท์„ ์ฒจ๋ถ€ํ•ด์ฃผ์„ธ์š”. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..e309137 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,5 @@ +# ISSUE โœ… : + +## ๐Ÿ“– Summary + +์ด์Šˆ๋ฅผ ๊ฐ„๋‹จํžˆ ์š”์•ฝํ•ด์ฃผ์„ธ์š”. diff --git a/.npmignore b/.npmignore index 98c3c98..18fc59e 100644 --- a/.npmignore +++ b/.npmignore @@ -25,5 +25,5 @@ dist-ssr .yarn storybook-static package.tgz -icons +iconsAsset .storybook \ No newline at end of file diff --git a/.storybook/main.ts b/.storybook/main.ts index 28bd15d..5645640 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -13,7 +13,7 @@ const config: StorybookConfig = { options: {}, }, docs: { - autodocs: 'tag', + autodocs: true, }, }; export default config; diff --git a/README.md b/README.md index 4fea036..b6afc5a 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,39 @@ YDS๋Š” ์ˆญ์‹ค๋Œ€ํ•™๊ต ๋™์•„๋ฆฌ ์œ ์–ด์Šˆ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๋””์ž์ธ ์‹œ์Šค YDS ๋ฌธ์„œ๋Š” ๋…ธ์…˜ ํŽ˜์ด์ง€์—์„œ ๊ด€๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ์ปดํฌ๋„ŒํŠธ ์ •๋ณด์™€ ์‚ฌ์šฉ ์˜ˆ์‹œ ๋“ฑ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +[YDS Storybook](http://yds-react-storybook.s3-website.ap-northeast-2.amazonaws.com/?path=/docs/foundation-iconcontext--docs) + ## ๐Ÿ–Œ ํ”ผ๊ทธ๋งˆ [YDS Figma](https://www.figma.com/community/file/1146974544001355129) -## ๐Ÿ›  ์„ค์น˜ ๋ฐฉ๋ฒ• +## ๐Ÿ›  ์‚ฌ์šฉ ๋ฐฉ๋ฒ• + +1. YDS ํŒจํ‚ค์ง€ ๋ฐ styled-components๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. + +``` +npm install @yourssu/design-system-react styled-components + +yarn add @yourssu/design-system-react styled-components + +pnpm install @yourssu/design-system-react styled-components +``` + +2. Root Component์— YDSWrapper๋ฅผ ๊ฐ์‹ธ์ค๋‹ˆ๋‹ค. -๊ฐœ๋ฐœ ์ค‘ +```jsx +ReactDOM.createRoot(document.getElementById("root")!).render( + + + + + +); +``` ## ๐Ÿ“ฑ YDS๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐœ๋ฐœํ•œ ํ”„๋กœ๋•ํŠธ -๊ฐœ๋ฐœ ์ค‘ +[Soomsil-Web](https://github.com/yourssu/Soomsil-Web) ## ๐Ÿ’ป ํƒ€ ๋ฒ„์ „ ์ €์žฅ์†Œ diff --git a/icons/convert.mjs b/iconsAsset/convert.mjs similarity index 94% rename from icons/convert.mjs rename to iconsAsset/convert.mjs index 4b5d10f..cb09b7d 100644 --- a/icons/convert.mjs +++ b/iconsAsset/convert.mjs @@ -9,7 +9,7 @@ import prettier from 'prettier'; import { DOMParser, XMLSerializer } from 'xmldom'; const __dirname = path.resolve(); -const ICONS_DIR = path.join(__dirname, './icons/static'); +const ICONS_DIR = path.join(__dirname, './iconsAsset/static'); const ICONS_COMPONENTS_DIR = path.join(__dirname, './src/style/foundation/icons/generated'); const ICONS_INDEX_PATH = path.join(__dirname, './src/style/foundation/icons/generated/index.ts'); const ICONS_STORIES_PATH = path.join(__dirname, './src/style/foundation/icons/icons.stories.tsx'); @@ -52,8 +52,8 @@ function camelizeElementAttributes(elem) { } const SVGComponentTemplate = (name, viewBox, svg) => `/** - * ์ด ํŒŒ์ผ์€ icons/convert.js์— ์˜ํ•ด ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. - * ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹  icons/convert.js๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”. + * ์ด ํŒŒ์ผ์€ iconsAsset/convert.js์— ์˜ํ•ด ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + * ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹  iconsAsset/convert.js๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”. */ import { memo, forwardRef } from 'react'; @@ -69,8 +69,8 @@ export const ${name} = memo(forwardRef((props, ref) => `; const StoryTemplate = (icons) => `/** - * ์ด ํŒŒ์ผ์€ icons/convert.js์— ์˜ํ•ด ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. - * ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹  icons/convert.js๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”. + * ์ด ํŒŒ์ผ์€ iconsAsset/convert.js์— ์˜ํ•ด ์ž๋™ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. + * ์ง์ ‘ ์ˆ˜์ •ํ•˜๋Š” ๋Œ€์‹  iconsAsset/convert.js๋ฅผ ์ˆ˜์ •ํ•˜์„ธ์š”. */ import { Meta, StoryObj } from '@storybook/react'; diff --git a/icons/static/ic_adbadge_filled.svg b/iconsAsset/static/ic_adbadge_filled.svg similarity index 100% rename from icons/static/ic_adbadge_filled.svg rename to iconsAsset/static/ic_adbadge_filled.svg diff --git a/icons/static/ic_adbadge_line.svg b/iconsAsset/static/ic_adbadge_line.svg similarity index 100% rename from icons/static/ic_adbadge_line.svg rename to iconsAsset/static/ic_adbadge_line.svg diff --git a/icons/static/ic_arrow_down_line.svg b/iconsAsset/static/ic_arrow_down_line.svg similarity index 100% rename from icons/static/ic_arrow_down_line.svg rename to iconsAsset/static/ic_arrow_down_line.svg diff --git a/icons/static/ic_arrow_left_line.svg b/iconsAsset/static/ic_arrow_left_line.svg similarity index 100% rename from icons/static/ic_arrow_left_line.svg rename to iconsAsset/static/ic_arrow_left_line.svg diff --git a/icons/static/ic_arrow_right_line.svg b/iconsAsset/static/ic_arrow_right_line.svg similarity index 100% rename from icons/static/ic_arrow_right_line.svg rename to iconsAsset/static/ic_arrow_right_line.svg diff --git a/icons/static/ic_arrow_up_line.svg b/iconsAsset/static/ic_arrow_up_line.svg similarity index 100% rename from icons/static/ic_arrow_up_line.svg rename to iconsAsset/static/ic_arrow_up_line.svg diff --git a/icons/static/ic_bell_filled.svg b/iconsAsset/static/ic_bell_filled.svg similarity index 100% rename from icons/static/ic_bell_filled.svg rename to iconsAsset/static/ic_bell_filled.svg diff --git a/icons/static/ic_bell_line.svg b/iconsAsset/static/ic_bell_line.svg similarity index 100% rename from icons/static/ic_bell_line.svg rename to iconsAsset/static/ic_bell_line.svg diff --git a/icons/static/ic_bellmute_line.svg b/iconsAsset/static/ic_bellmute_line.svg similarity index 100% rename from icons/static/ic_bellmute_line.svg rename to iconsAsset/static/ic_bellmute_line.svg diff --git a/icons/static/ic_blockuser_line.svg b/iconsAsset/static/ic_blockuser_line.svg similarity index 100% rename from icons/static/ic_blockuser_line.svg rename to iconsAsset/static/ic_blockuser_line.svg diff --git a/icons/static/ic_board_filled.svg b/iconsAsset/static/ic_board_filled.svg similarity index 100% rename from icons/static/ic_board_filled.svg rename to iconsAsset/static/ic_board_filled.svg diff --git a/icons/static/ic_board_line.svg b/iconsAsset/static/ic_board_line.svg similarity index 100% rename from icons/static/ic_board_line.svg rename to iconsAsset/static/ic_board_line.svg diff --git a/icons/static/ic_book_filled.svg b/iconsAsset/static/ic_book_filled.svg similarity index 100% rename from icons/static/ic_book_filled.svg rename to iconsAsset/static/ic_book_filled.svg diff --git a/icons/static/ic_book_line.svg b/iconsAsset/static/ic_book_line.svg similarity index 100% rename from icons/static/ic_book_line.svg rename to iconsAsset/static/ic_book_line.svg diff --git a/icons/static/ic_calendar_filled.svg b/iconsAsset/static/ic_calendar_filled.svg similarity index 100% rename from icons/static/ic_calendar_filled.svg rename to iconsAsset/static/ic_calendar_filled.svg diff --git a/icons/static/ic_calendar_line.svg b/iconsAsset/static/ic_calendar_line.svg similarity index 100% rename from icons/static/ic_calendar_line.svg rename to iconsAsset/static/ic_calendar_line.svg diff --git a/icons/static/ic_camera_filled.svg b/iconsAsset/static/ic_camera_filled.svg similarity index 100% rename from icons/static/ic_camera_filled.svg rename to iconsAsset/static/ic_camera_filled.svg diff --git a/icons/static/ic_camera_line.svg b/iconsAsset/static/ic_camera_line.svg similarity index 100% rename from icons/static/ic_camera_line.svg rename to iconsAsset/static/ic_camera_line.svg diff --git a/icons/static/ic_cameracircle_line.svg b/iconsAsset/static/ic_cameracircle_line.svg similarity index 100% rename from icons/static/ic_cameracircle_line.svg rename to iconsAsset/static/ic_cameracircle_line.svg diff --git a/icons/static/ic_check_line.svg b/iconsAsset/static/ic_check_line.svg similarity index 100% rename from icons/static/ic_check_line.svg rename to iconsAsset/static/ic_check_line.svg diff --git a/icons/static/ic_checkcircle_filled.svg b/iconsAsset/static/ic_checkcircle_filled.svg similarity index 100% rename from icons/static/ic_checkcircle_filled.svg rename to iconsAsset/static/ic_checkcircle_filled.svg diff --git a/icons/static/ic_checkcircle_line.svg b/iconsAsset/static/ic_checkcircle_line.svg similarity index 100% rename from icons/static/ic_checkcircle_line.svg rename to iconsAsset/static/ic_checkcircle_line.svg diff --git a/icons/static/ic_clip_line.svg b/iconsAsset/static/ic_clip_line.svg similarity index 100% rename from icons/static/ic_clip_line.svg rename to iconsAsset/static/ic_clip_line.svg diff --git a/icons/static/ic_comment_filled.svg b/iconsAsset/static/ic_comment_filled.svg similarity index 100% rename from icons/static/ic_comment_filled.svg rename to iconsAsset/static/ic_comment_filled.svg diff --git a/icons/static/ic_comment_line.svg b/iconsAsset/static/ic_comment_line.svg similarity index 100% rename from icons/static/ic_comment_line.svg rename to iconsAsset/static/ic_comment_line.svg diff --git a/icons/static/ic_dotbadge_line.svg b/iconsAsset/static/ic_dotbadge_line.svg similarity index 100% rename from icons/static/ic_dotbadge_line.svg rename to iconsAsset/static/ic_dotbadge_line.svg diff --git a/icons/static/ic_dots_horizontal_line.svg b/iconsAsset/static/ic_dots_horizontal_line.svg similarity index 100% rename from icons/static/ic_dots_horizontal_line.svg rename to iconsAsset/static/ic_dots_horizontal_line.svg diff --git a/icons/static/ic_dots_vertical_line.svg b/iconsAsset/static/ic_dots_vertical_line.svg similarity index 100% rename from icons/static/ic_dots_vertical_line.svg rename to iconsAsset/static/ic_dots_vertical_line.svg diff --git a/icons/static/ic_download_line.svg b/iconsAsset/static/ic_download_line.svg similarity index 100% rename from icons/static/ic_download_line.svg rename to iconsAsset/static/ic_download_line.svg diff --git a/icons/static/ic_emojiadd_line.svg b/iconsAsset/static/ic_emojiadd_line.svg similarity index 100% rename from icons/static/ic_emojiadd_line.svg rename to iconsAsset/static/ic_emojiadd_line.svg diff --git a/icons/static/ic_eyeclosed_line.svg b/iconsAsset/static/ic_eyeclosed_line.svg similarity index 100% rename from icons/static/ic_eyeclosed_line.svg rename to iconsAsset/static/ic_eyeclosed_line.svg diff --git a/icons/static/ic_eyeopen_line.svg b/iconsAsset/static/ic_eyeopen_line.svg similarity index 100% rename from icons/static/ic_eyeopen_line.svg rename to iconsAsset/static/ic_eyeopen_line.svg diff --git a/icons/static/ic_food_filled.svg b/iconsAsset/static/ic_food_filled.svg similarity index 100% rename from icons/static/ic_food_filled.svg rename to iconsAsset/static/ic_food_filled.svg diff --git a/icons/static/ic_food_line.svg b/iconsAsset/static/ic_food_line.svg similarity index 100% rename from icons/static/ic_food_line.svg rename to iconsAsset/static/ic_food_line.svg diff --git a/icons/static/ic_foodcalendar_filled.svg b/iconsAsset/static/ic_foodcalendar_filled.svg similarity index 100% rename from icons/static/ic_foodcalendar_filled.svg rename to iconsAsset/static/ic_foodcalendar_filled.svg diff --git a/icons/static/ic_foodcalendar_line.svg b/iconsAsset/static/ic_foodcalendar_line.svg similarity index 100% rename from icons/static/ic_foodcalendar_line.svg rename to iconsAsset/static/ic_foodcalendar_line.svg diff --git a/icons/static/ic_ground_filled.svg b/iconsAsset/static/ic_ground_filled.svg similarity index 100% rename from icons/static/ic_ground_filled.svg rename to iconsAsset/static/ic_ground_filled.svg diff --git a/icons/static/ic_ground_line.svg b/iconsAsset/static/ic_ground_line.svg similarity index 100% rename from icons/static/ic_ground_line.svg rename to iconsAsset/static/ic_ground_line.svg diff --git a/icons/static/ic_heart_line.svg b/iconsAsset/static/ic_heart_line.svg similarity index 100% rename from icons/static/ic_heart_line.svg rename to iconsAsset/static/ic_heart_line.svg diff --git a/icons/static/ic_home_filled.svg b/iconsAsset/static/ic_home_filled.svg similarity index 100% rename from icons/static/ic_home_filled.svg rename to iconsAsset/static/ic_home_filled.svg diff --git a/icons/static/ic_home_line.svg b/iconsAsset/static/ic_home_line.svg similarity index 100% rename from icons/static/ic_home_line.svg rename to iconsAsset/static/ic_home_line.svg diff --git a/icons/static/ic_list_line.svg b/iconsAsset/static/ic_list_line.svg similarity index 100% rename from icons/static/ic_list_line.svg rename to iconsAsset/static/ic_list_line.svg diff --git a/icons/static/ic_lock_filled.svg b/iconsAsset/static/ic_lock_filled.svg similarity index 100% rename from icons/static/ic_lock_filled.svg rename to iconsAsset/static/ic_lock_filled.svg diff --git a/icons/static/ic_lock_line.svg b/iconsAsset/static/ic_lock_line.svg similarity index 100% rename from icons/static/ic_lock_line.svg rename to iconsAsset/static/ic_lock_line.svg diff --git a/icons/static/ic_new_filled.svg b/iconsAsset/static/ic_new_filled.svg similarity index 100% rename from icons/static/ic_new_filled.svg rename to iconsAsset/static/ic_new_filled.svg diff --git a/icons/static/ic_new_line.svg b/iconsAsset/static/ic_new_line.svg similarity index 100% rename from icons/static/ic_new_line.svg rename to iconsAsset/static/ic_new_line.svg diff --git a/icons/static/ic_notice_filled.svg b/iconsAsset/static/ic_notice_filled.svg similarity index 100% rename from icons/static/ic_notice_filled.svg rename to iconsAsset/static/ic_notice_filled.svg diff --git a/icons/static/ic_notice_line.svg b/iconsAsset/static/ic_notice_line.svg similarity index 100% rename from icons/static/ic_notice_line.svg rename to iconsAsset/static/ic_notice_line.svg diff --git a/icons/static/ic_pen_filled.svg b/iconsAsset/static/ic_pen_filled.svg similarity index 100% rename from icons/static/ic_pen_filled.svg rename to iconsAsset/static/ic_pen_filled.svg diff --git a/icons/static/ic_pen_line.svg b/iconsAsset/static/ic_pen_line.svg similarity index 100% rename from icons/static/ic_pen_line.svg rename to iconsAsset/static/ic_pen_line.svg diff --git a/icons/static/ic_person_filled.svg b/iconsAsset/static/ic_person_filled.svg similarity index 100% rename from icons/static/ic_person_filled.svg rename to iconsAsset/static/ic_person_filled.svg diff --git a/icons/static/ic_person_line.svg b/iconsAsset/static/ic_person_line.svg similarity index 100% rename from icons/static/ic_person_line.svg rename to iconsAsset/static/ic_person_line.svg diff --git a/icons/static/ic_personcircle_line.svg b/iconsAsset/static/ic_personcircle_line.svg similarity index 100% rename from icons/static/ic_personcircle_line.svg rename to iconsAsset/static/ic_personcircle_line.svg diff --git a/icons/static/ic_picture_filled.svg b/iconsAsset/static/ic_picture_filled.svg similarity index 100% rename from icons/static/ic_picture_filled.svg rename to iconsAsset/static/ic_picture_filled.svg diff --git a/icons/static/ic_picture_line.svg b/iconsAsset/static/ic_picture_line.svg similarity index 100% rename from icons/static/ic_picture_line.svg rename to iconsAsset/static/ic_picture_line.svg diff --git a/icons/static/ic_pin_filled.svg b/iconsAsset/static/ic_pin_filled.svg similarity index 100% rename from icons/static/ic_pin_filled.svg rename to iconsAsset/static/ic_pin_filled.svg diff --git a/icons/static/ic_pin_line.svg b/iconsAsset/static/ic_pin_line.svg similarity index 100% rename from icons/static/ic_pin_line.svg rename to iconsAsset/static/ic_pin_line.svg diff --git a/icons/static/ic_playcircle_filled.svg b/iconsAsset/static/ic_playcircle_filled.svg similarity index 100% rename from icons/static/ic_playcircle_filled.svg rename to iconsAsset/static/ic_playcircle_filled.svg diff --git a/icons/static/ic_playcircle_line.svg b/iconsAsset/static/ic_playcircle_line.svg similarity index 100% rename from icons/static/ic_playcircle_line.svg rename to iconsAsset/static/ic_playcircle_line.svg diff --git a/icons/static/ic_plus_line.svg b/iconsAsset/static/ic_plus_line.svg similarity index 100% rename from icons/static/ic_plus_line.svg rename to iconsAsset/static/ic_plus_line.svg diff --git a/icons/static/ic_rank_filled.svg b/iconsAsset/static/ic_rank_filled.svg similarity index 100% rename from icons/static/ic_rank_filled.svg rename to iconsAsset/static/ic_rank_filled.svg diff --git a/icons/static/ic_rank_line.svg b/iconsAsset/static/ic_rank_line.svg similarity index 100% rename from icons/static/ic_rank_line.svg rename to iconsAsset/static/ic_rank_line.svg diff --git a/icons/static/ic_recomment_line.svg b/iconsAsset/static/ic_recomment_line.svg similarity index 100% rename from icons/static/ic_recomment_line.svg rename to iconsAsset/static/ic_recomment_line.svg diff --git a/icons/static/ic_refresh_line.svg b/iconsAsset/static/ic_refresh_line.svg similarity index 100% rename from icons/static/ic_refresh_line.svg rename to iconsAsset/static/ic_refresh_line.svg diff --git a/icons/static/ic_savecircle_filled.svg b/iconsAsset/static/ic_savecircle_filled.svg similarity index 100% rename from icons/static/ic_savecircle_filled.svg rename to iconsAsset/static/ic_savecircle_filled.svg diff --git a/icons/static/ic_savecircle_line.svg b/iconsAsset/static/ic_savecircle_line.svg similarity index 100% rename from icons/static/ic_savecircle_line.svg rename to iconsAsset/static/ic_savecircle_line.svg diff --git a/icons/static/ic_schoolcalendar_filled.svg b/iconsAsset/static/ic_schoolcalendar_filled.svg similarity index 100% rename from icons/static/ic_schoolcalendar_filled.svg rename to iconsAsset/static/ic_schoolcalendar_filled.svg diff --git a/icons/static/ic_schoolcalendar_line.svg b/iconsAsset/static/ic_schoolcalendar_line.svg similarity index 100% rename from icons/static/ic_schoolcalendar_line.svg rename to iconsAsset/static/ic_schoolcalendar_line.svg diff --git a/icons/static/ic_search_line.svg b/iconsAsset/static/ic_search_line.svg similarity index 100% rename from icons/static/ic_search_line.svg rename to iconsAsset/static/ic_search_line.svg diff --git a/icons/static/ic_setting_line.svg b/iconsAsset/static/ic_setting_line.svg similarity index 100% rename from icons/static/ic_setting_line.svg rename to iconsAsset/static/ic_setting_line.svg diff --git a/icons/static/ic_share_line.svg b/iconsAsset/static/ic_share_line.svg similarity index 100% rename from icons/static/ic_share_line.svg rename to iconsAsset/static/ic_share_line.svg diff --git a/icons/static/ic_sharecircle_filled.svg b/iconsAsset/static/ic_sharecircle_filled.svg similarity index 100% rename from icons/static/ic_sharecircle_filled.svg rename to iconsAsset/static/ic_sharecircle_filled.svg diff --git a/icons/static/ic_sharecircle_line.svg b/iconsAsset/static/ic_sharecircle_line.svg similarity index 100% rename from icons/static/ic_sharecircle_line.svg rename to iconsAsset/static/ic_sharecircle_line.svg diff --git a/icons/static/ic_star_filled.svg b/iconsAsset/static/ic_star_filled.svg similarity index 100% rename from icons/static/ic_star_filled.svg rename to iconsAsset/static/ic_star_filled.svg diff --git a/icons/static/ic_star_line.svg b/iconsAsset/static/ic_star_line.svg similarity index 100% rename from icons/static/ic_star_line.svg rename to iconsAsset/static/ic_star_line.svg diff --git a/icons/static/ic_thumb_down_filled.svg b/iconsAsset/static/ic_thumb_down_filled.svg similarity index 100% rename from icons/static/ic_thumb_down_filled.svg rename to iconsAsset/static/ic_thumb_down_filled.svg diff --git a/icons/static/ic_thumb_down_line.svg b/iconsAsset/static/ic_thumb_down_line.svg similarity index 100% rename from icons/static/ic_thumb_down_line.svg rename to iconsAsset/static/ic_thumb_down_line.svg diff --git a/icons/static/ic_thumb_up_filled.svg b/iconsAsset/static/ic_thumb_up_filled.svg similarity index 100% rename from icons/static/ic_thumb_up_filled.svg rename to iconsAsset/static/ic_thumb_up_filled.svg diff --git a/icons/static/ic_thumb_up_line.svg b/iconsAsset/static/ic_thumb_up_line.svg similarity index 100% rename from icons/static/ic_thumb_up_line.svg rename to iconsAsset/static/ic_thumb_up_line.svg diff --git a/icons/static/ic_timecalendar_filled.svg b/iconsAsset/static/ic_timecalendar_filled.svg similarity index 100% rename from icons/static/ic_timecalendar_filled.svg rename to iconsAsset/static/ic_timecalendar_filled.svg diff --git a/icons/static/ic_timecalendar_line.svg b/iconsAsset/static/ic_timecalendar_line.svg similarity index 100% rename from icons/static/ic_timecalendar_line.svg rename to iconsAsset/static/ic_timecalendar_line.svg diff --git a/icons/static/ic_trashcan_filled.svg b/iconsAsset/static/ic_trashcan_filled.svg similarity index 100% rename from icons/static/ic_trashcan_filled.svg rename to iconsAsset/static/ic_trashcan_filled.svg diff --git a/icons/static/ic_trashcan_line.svg b/iconsAsset/static/ic_trashcan_line.svg similarity index 100% rename from icons/static/ic_trashcan_line.svg rename to iconsAsset/static/ic_trashcan_line.svg diff --git a/icons/static/ic_warningcircle_filled.svg b/iconsAsset/static/ic_warningcircle_filled.svg similarity index 100% rename from icons/static/ic_warningcircle_filled.svg rename to iconsAsset/static/ic_warningcircle_filled.svg diff --git a/icons/static/ic_warningcircle_line.svg b/iconsAsset/static/ic_warningcircle_line.svg similarity index 100% rename from icons/static/ic_warningcircle_line.svg rename to iconsAsset/static/ic_warningcircle_line.svg diff --git a/icons/static/ic_x_line.svg b/iconsAsset/static/ic_x_line.svg similarity index 100% rename from icons/static/ic_x_line.svg rename to iconsAsset/static/ic_x_line.svg diff --git a/icons/static/ic_xcircle_filled.svg b/iconsAsset/static/ic_xcircle_filled.svg similarity index 100% rename from icons/static/ic_xcircle_filled.svg rename to iconsAsset/static/ic_xcircle_filled.svg diff --git a/package.json b/package.json index 2a4da16..7cad6ea 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,12 @@ { "name": "@yourssu/design-system-react", "private": false, - "version": "0.1.0", + "version": "1.0.0", "description": "Yourssu Design System for React", "keywords": [ "yourssu", "design system", - "react", - "design system" + "react" ], "repository": "yourssu/YDS-React", "license": "MIT", @@ -29,7 +28,7 @@ "preview": "vite preview", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", - "convert-icon": "node ./icons/convert.mjs" + "convert-icon": "node ./iconsAsset/convert.mjs" }, "peerDependencies": { "react": "^18.2.0", diff --git a/src/components/Badge/Badge.type.ts b/src/components/Badge/Badge.type.ts index 108ce74..62a5bf9 100644 --- a/src/components/Badge/Badge.type.ts +++ b/src/components/Badge/Badge.type.ts @@ -1,7 +1,10 @@ import { SemanticBGColor } from '@/style'; export interface BadgeProps extends React.HTMLAttributes { + /** ๋ฐฐ๊ฒฝ ์ƒ‰์ƒ */ color?: SemanticBGColor; + /** Badge ์•ˆ์— ๋“ค์–ด๊ฐˆ ํ…์ŠคํŠธ */ children?: React.ReactNode; + /** ํ…์ŠคํŠธ ์™ผ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ leftIcon?: React.ReactNode; } diff --git a/src/components/BoxButton/BoxButton.stories.tsx b/src/components/BoxButton/BoxButton.stories.tsx index 8f716a7..3086289 100644 --- a/src/components/BoxButton/BoxButton.stories.tsx +++ b/src/components/BoxButton/BoxButton.stories.tsx @@ -3,12 +3,50 @@ import { Meta, StoryObj } from '@storybook/react'; import { IcGroundLine } from '@/style'; import { BoxButton } from './BoxButton'; +import { Stories, Primary as PrimaryBlock, Controls, Title } from '@storybook/blocks'; const meta: Meta = { title: 'Atoms/BoxButton', component: BoxButton, parameters: { layout: 'centered', + docs: { + page: () => ( + <> + + <PrimaryBlock /> + <Controls /> + <h2> Size์— ๋”ฐ๋ฅธ ์†์„ฑ </h2> + <h3> extraLarge </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `height = 56`, `typo = button1`, `iconSize = medium(24*24)`, `horizontal Padding = 16` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h3> large </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `height = 48`, `typo = button2`, `iconSize = medium(24*24)`, `horizontal Padding = 16` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h3> medium </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `height = 40`, `typo = button2`, `iconSize = medium(24*24)`, `horizontal Padding = 12` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h3> small </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `height = 32`, `typo = button4`, `iconSize = small(16*16)`, `horizontal Padding = 12` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h2> ์†์„ฑ ์šฐ์„ ์ˆœ์œ„ </h2> + <span>{'์†์„ฑ์ด ์ถฉ๋Œํ•  ๋•Œ๋Š” isDisabled > isWarned ์ˆœ์œผ๋กœ ์šฐ์„ ๋ฉ๋‹ˆ๋‹ค.'}</span> + <Stories /> + </> + ), + }, }, }; diff --git a/src/components/BoxButton/BoxButton.style.ts b/src/components/BoxButton/BoxButton.style.ts index 371f270..626d232 100644 --- a/src/components/BoxButton/BoxButton.style.ts +++ b/src/components/BoxButton/BoxButton.style.ts @@ -10,9 +10,9 @@ import { interface StyledBoxButtonProps { $size: BoxButtonSize; $variant: BoxButtonVariant; - $isWarned: BoxButtonProps['isWarned']; - $rounding: BoxButtonRounding; - $width: BoxButtonProps['width']; + $rounding?: BoxButtonRounding; + $isWarned?: BoxButtonProps['isWarned']; + $width?: BoxButtonProps['width']; } const getNormalStyle = ($variant: BoxButtonVariant) => { diff --git a/src/components/BoxButton/BoxButton.type.ts b/src/components/BoxButton/BoxButton.type.ts index dec54fa..e6caaad 100644 --- a/src/components/BoxButton/BoxButton.type.ts +++ b/src/components/BoxButton/BoxButton.type.ts @@ -3,13 +3,22 @@ export type BoxButtonRounding = 4 | 8; export type BoxButtonVariant = 'filled' | 'tinted' | 'line'; export interface BoxButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { + /** BoxButton์˜ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ size: BoxButtonSize; - rounding: BoxButtonRounding; - isDisabled: HTMLButtonElement['disabled']; - isWarned: boolean; + /** BoxButton์˜ ๋ชจ์–‘์„ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ variant: BoxButtonVariant; + /** BoxButton์˜ ๋ชจ์„œ๋ฆฌ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ + rounding: BoxButtonRounding; + /** BoxButton์˜ ๋น„ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ, ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ์—๋Š” pressed ํšจ๊ณผ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. */ + isDisabled?: HTMLButtonElement['disabled']; + /** BoxButton์˜ ๊ฒฝ๊ณ  ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ + isWarned?: boolean; + /** BoxButton์˜ ์™ผ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ leftIcon?: React.ReactNode; + /** BoxButton์˜ ๋‚ด์šฉ */ children?: React.ReactNode; + /** BoxButton์˜ ์˜ค๋ฅธ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ rightIcon?: React.ReactNode; + /** BoxButton์˜ width */ width?: string | number; } diff --git a/src/components/CheckBox/CheckBox.stories.tsx b/src/components/CheckBox/CheckBox.stories.tsx index cc189d7..c523f1b 100644 --- a/src/components/CheckBox/CheckBox.stories.tsx +++ b/src/components/CheckBox/CheckBox.stories.tsx @@ -1,12 +1,44 @@ import { Meta, StoryObj } from '@storybook/react'; import { CheckBox } from './CheckBox'; +import { Stories, Primary as PrimaryBlock, Controls, Title } from '@storybook/blocks'; const meta: Meta<typeof CheckBox> = { title: 'Atoms/CheckBox', component: CheckBox, parameters: { layout: 'centered', + docs: { + page: () => ( + <> + <Title /> + <PrimaryBlock /> + <Controls /> + <h2> Size์— ๋”ฐ๋ฅธ ์†์„ฑ </h2> + <h3> large </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `iconSize = medium(24*24)`, `typo = button3`, `CheckBox icon๊ณผ label ์‚ฌ์ด ์—ฌ๋ฐฑ = 8` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h3> medium </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `iconSize = small(20*20)`, `typo = button3`, `CheckBox icon๊ณผ label ์‚ฌ์ด ์—ฌ๋ฐฑ = 8` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h3> small </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `iconSize = extraSmall(16*16)`, `typo = button4`, `CheckBox icon๊ณผ label ์‚ฌ์ด ์—ฌ๋ฐฑ = 4` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.' + } + </span> + <h2> ์†์„ฑ ์šฐ์„ ์ˆœ์œ„ </h2> + <span>{'์†์„ฑ์ด ์ถฉ๋Œํ•  ๋•Œ๋Š” isDisabled > isSelected ์ˆœ์œผ๋กœ ์šฐ์„ ๋ฉ๋‹ˆ๋‹ค.'}</span> + <Stories /> + </> + ), + }, }, }; diff --git a/src/components/CheckBox/CheckBox.type.ts b/src/components/CheckBox/CheckBox.type.ts index ae016b5..a4f9f8c 100644 --- a/src/components/CheckBox/CheckBox.type.ts +++ b/src/components/CheckBox/CheckBox.type.ts @@ -1,8 +1,12 @@ export type CheckBoxSize = 'small' | 'medium' | 'large'; export interface CheckBoxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> { + /** CheckBox์˜ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ size?: CheckBoxSize; + /** CheckBox์˜ ์„ ํƒ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ isSelected?: HTMLInputElement['checked']; + /** CheckBox์˜ ๋น„ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ isDisabled?: HTMLInputElement['disabled']; + /** CheckBox์˜ ๋‚ด์šฉ */ children?: React.ReactNode; } diff --git a/src/components/ListItem/ListItem.type.ts b/src/components/ListItem/ListItem.type.ts index 9d42e76..acadd64 100644 --- a/src/components/ListItem/ListItem.type.ts +++ b/src/components/ListItem/ListItem.type.ts @@ -1,7 +1,12 @@ export interface ListItemProps extends React.HTMLAttributes<HTMLLIElement> { + /** ListItem์˜ ์„ ํƒ ์—ฌ๋ถ€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์†์„ฑ */ isPressed?: boolean; + /** ListItem์˜ width */ width?: string | number; + /** ListItem์˜ ๋‚ด์šฉ */ children?: React.ReactNode; + /** ListItem์˜ ์™ผ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ leftIcon?: React.ReactNode; + /** ListItem์˜ ์˜ค๋ฅธ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ rightIcon?: React.ReactNode; } diff --git a/src/components/PlainButton/PlainButton.stories.tsx b/src/components/PlainButton/PlainButton.stories.tsx index 2e8eb52..c6a0bda 100644 --- a/src/components/PlainButton/PlainButton.stories.tsx +++ b/src/components/PlainButton/PlainButton.stories.tsx @@ -3,12 +3,40 @@ import { Meta, StoryObj } from '@storybook/react'; import { IcGroundLine } from '@/style'; import { PlainButton } from './PlainButton'; +import { Stories, Primary as PrimaryBlock, Controls, Title } from '@storybook/blocks'; const meta: Meta<typeof PlainButton> = { title: 'Atoms/PlainButton', component: PlainButton, parameters: { layout: 'centered', + docs: { + page: () => ( + <> + <Title /> + <PrimaryBlock /> + <Controls /> + <h2> Size์— ๋”ฐ๋ฅธ ์†์„ฑ </h2> + <h3> large </h3> + <span> + { + '์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `iconSize = medium(24*24)` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. text๋Š” ๋ณด์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.' + } + </span> + <h3> medium </h3> + <span> + {'์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `typo = button3`, `iconSize = small(20*20)` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.'} + </span> + <h3> small </h3> + <span> + {'์ด ์˜ต์…˜์„ ์„ ํƒํ•˜๋ฉด `typo = button4`, `iconSize = extraSmall(16*16)` ์œผ๋กœ ์„ค์ •๋ฉ๋‹ˆ๋‹ค.'} + </span> + <h2> ์†์„ฑ ์šฐ์„ ์ˆœ์œ„ </h2> + <span>{'์†์„ฑ์ด ์ถฉ๋Œํ•  ๋•Œ๋Š” isDisabled > isWarned > isPointed ์ˆœ์œผ๋กœ ์šฐ์„ ๋ฉ๋‹ˆ๋‹ค.'}</span> + <Stories /> + </> + ), + }, }, }; diff --git a/src/components/PlainButton/PlainButton.type.ts b/src/components/PlainButton/PlainButton.type.ts index 65e9fdd..f5e52c2 100644 --- a/src/components/PlainButton/PlainButton.type.ts +++ b/src/components/PlainButton/PlainButton.type.ts @@ -1,10 +1,16 @@ export type PlainButtonSize = 'small' | 'medium' | 'large'; export interface PlainButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> { + /** PlainButton์˜ ํฌ๊ธฐ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ size: PlainButtonSize; + /** PlainButton์˜ Pointed ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ isPointed: boolean; + /** PlainButton์˜ ๊ฒฝ๊ณ  ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ์†์„ฑ */ isWarned: boolean; + /** PlainButton์˜ ์™ผ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ leftIcon?: React.ReactNode; + /** PlainButton์˜ ๋‚ด์šฉ */ children?: React.ReactNode; + /** PlainButton์˜ ์˜ค๋ฅธ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ */ rightIcon?: React.ReactNode; } diff --git a/src/components/Test/Test.stories.tsx b/src/components/Test/Test.stories.tsx deleted file mode 100644 index 32eaeac..0000000 --- a/src/components/Test/Test.stories.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Meta, StoryObj } from '@storybook/react'; - -import { Test } from '..'; - -const meta: Meta<typeof Test> = { - title: 'Component/Test', - component: Test, - parameters: { - layout: 'centered', - }, -}; -export default meta; - -type Story = StoryObj<typeof Test>; - -export const Primary: Story = { - args: { - children: 'Hello, YDS!', - }, -}; diff --git a/src/components/Test/Test.style.tsx b/src/components/Test/Test.style.tsx deleted file mode 100644 index 59a9789..0000000 --- a/src/components/Test/Test.style.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { styled } from 'styled-components'; - -interface StyledTestProps { - $color: string; -} -export const StyledTest = styled.div<StyledTestProps>` - color: ${(props) => props.$color}; - width: 100px; - height: 100px; - display: flex; - justify-content: center; - align-items: center; - background-color: ${({ theme }) => theme.color.bgNormal}; - border: solid 1px ${({ theme }) => theme.color.borderNormal}; - - ${({ theme }) => theme.typo.body1}; -`; diff --git a/src/components/Test/Test.tsx b/src/components/Test/Test.tsx deleted file mode 100644 index 175b8e5..0000000 --- a/src/components/Test/Test.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React, { forwardRef } from 'react'; - -import { StyledTest } from './Test.style'; - -export interface TestProps extends React.ComponentPropsWithRef<'div'> { - color?: string; - children?: React.ReactNode; -} -export const Test = forwardRef<HTMLDivElement, TestProps>( - ({ color = 'black', children, ...rest }, ref) => { - return ( - <StyledTest ref={ref} $color={color} {...rest}> - {children} - </StyledTest> - ); - } -); - -Test.displayName = 'Test'; diff --git a/src/components/Test/index.ts b/src/components/Test/index.ts deleted file mode 100644 index b15a4ec..0000000 --- a/src/components/Test/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Test } from './Test'; -export type { TestProps } from './Test'; diff --git a/src/components/TextField/SimpleTextField/SimpleTextField.stories.tsx b/src/components/TextField/SimpleTextField/SimpleTextField.stories.tsx new file mode 100644 index 0000000..1d65986 --- /dev/null +++ b/src/components/TextField/SimpleTextField/SimpleTextField.stories.tsx @@ -0,0 +1,129 @@ +import { useState } from 'react'; + +import { Stories, Primary as PrimaryBlock, Controls, Title } from '@storybook/blocks'; +import { Meta, StoryObj } from '@storybook/react'; + +import { SimpleTextField } from './SimpleTextField'; + +const meta: Meta<typeof SimpleTextField> = { + title: 'Atoms/TextField/SimpleTextField', + component: SimpleTextField, + parameters: { + layout: 'centered', + docs: { + page: () => ( + <> + <Title /> + <PrimaryBlock /> + <Controls /> + <h2> ์ฃผ์˜์‚ฌํ•ญ </h2> + <ol> + <li> + TextField์˜ ์ข…๋ฅ˜์— ๋”ฐ๋ผ suffix, searchPrefix ์†์„ฑ ๊ฐ’์ด ์ผ๋ถ€ ์ •ํ•ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. + <br /> + <br /> + <table> + <tr> + <th>์ข…๋ฅ˜</th> + <th>suffix</th> + <th>searchPrefix</th> + </tr> + <tr> + <td>SimpleTextField</td> + <td>IcXLine</td> + <td>์„ค์ • ๋ถˆ๊ฐ€</td> + </tr> + <tr> + <td>SuffixTextField</td> + <td>์‚ฌ์šฉ์ž๊ฐ€ ์„ค์ •ํ•œ ๊ฐ’</td> + <td>์„ค์ • ๋ถˆ๊ฐ€</td> + </tr> + <tr> + <td>SearchTextField</td> + <td>IcXLine</td> + <td>IcSearchLine</td> + </tr> + <tr> + <td>PasswordTextField</td> + <td>IcEyeclosedLine ๋˜๋Š” IcEyeopenLine</td> + <td>์„ค์ • ๋ถˆ๊ฐ€</td> + </tr> + </table> + </li> + <br /> + <li> + boolean ํƒ€์ž… ์†์„ฑ์˜ ์šฐ์„ ์ˆœ์œ„๋Š” ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. + <br /> + disabled > isNegative > isPositive + </li> + </ol> + <br /> + <Stories /> + </> + ), + }, + }, +}; +export default meta; + +const TextFieldStory = ({ ...textFieldProps }) => { + const [value, setValue] = useState(''); + const onChange = (e: React.ChangeEvent<HTMLInputElement>) => { + setValue(e.target.value); + }; + const onClickClearButton = () => { + setValue(''); + }; + + const newProps = { ...textFieldProps, value, onChange, onClickClearButton }; + return <SimpleTextField {...newProps} />; +}; + +type Story = StoryObj<typeof SimpleTextField>; +export const Primary: Story = { + args: { + fieldLabel: 'ํ•„๋“œ ๋ผ๋ฒจ', + helperLabel: '๋„์›€๋ง ํ…์ŠคํŠธ', + placeholder: 'ํ”Œ๋ ˆ์ด์Šค ํ™€๋”', + disabled: false, + isPositive: false, + isNegative: false, + width: '350px', + }, + render: TextFieldStory, +}; + +export const Disabled: Story = { + args: { + fieldLabel: 'ํ•„๋“œ ๋ผ๋ฒจ', + helperLabel: '๋„์›€๋ง ํ…์ŠคํŠธ', + placeholder: 'ํ”Œ๋ ˆ์ด์Šค ํ™€๋”', + disabled: true, + width: '350px', + }, + render: TextFieldStory, +}; + +export const Positive: Story = { + args: { + fieldLabel: 'ํ•„๋“œ ๋ผ๋ฒจ', + helperLabel: '๋„์›€๋ง ํ…์ŠคํŠธ', + placeholder: 'ํ”Œ๋ ˆ์ด์Šค ํ™€๋”', + disabled: false, + isPositive: true, + width: '350px', + }, + render: TextFieldStory, +}; + +export const Negative: Story = { + args: { + fieldLabel: 'ํ•„๋“œ ๋ผ๋ฒจ', + helperLabel: '๋„์›€๋ง ํ…์ŠคํŠธ', + placeholder: 'ํ”Œ๋ ˆ์ด์Šค ํ™€๋”', + disabled: false, + isNegative: true, + width: '350px', + }, + render: TextFieldStory, +}; diff --git a/src/components/TextField/SimpleTextField/SimpleTextField.tsx b/src/components/TextField/SimpleTextField/SimpleTextField.tsx new file mode 100644 index 0000000..a49bf1c --- /dev/null +++ b/src/components/TextField/SimpleTextField/SimpleTextField.tsx @@ -0,0 +1,25 @@ +import { IcXLine, IconContext } from '@/style'; + +import { TextField } from '../TextField'; + +import { SimpleTextFieldProps } from './SimpleTextField.type'; + +export const SimpleTextField = ({ onClickClearButton, ...props }: SimpleTextFieldProps) => { + return ( + <TextField + suffix={ + <IconContext.Provider + value={{ + color: '#0f0f0f', + size: '1rem', + }} + > + <div className="suffix-icon clear-icon" onClick={onClickClearButton}> + <IcXLine /> + </div> + </IconContext.Provider> + } + {...props} + /> + ); +}; diff --git a/src/components/TextField/SimpleTextField/SimpleTextField.type.ts b/src/components/TextField/SimpleTextField/SimpleTextField.type.ts new file mode 100644 index 0000000..bb0ec8d --- /dev/null +++ b/src/components/TextField/SimpleTextField/SimpleTextField.type.ts @@ -0,0 +1,6 @@ +import { TextFieldProps } from '../TextField.type'; + +export interface SimpleTextFieldProps extends TextFieldProps { + /** x ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ */ + onClickClearButton?: () => void; +} diff --git a/src/components/TextField/TextField.style.ts b/src/components/TextField/TextField.style.ts new file mode 100644 index 0000000..2deae6d --- /dev/null +++ b/src/components/TextField/TextField.style.ts @@ -0,0 +1,105 @@ +import { css, styled } from 'styled-components'; + +import { TextFieldProps } from './TextField.type'; + +interface StyledTextFieldProps { + $isNegative?: TextFieldProps['isNegative']; + $isPositive?: TextFieldProps['isPositive']; + $isFocused?: TextFieldProps['isFocused']; + $isTyping?: TextFieldProps['isTyping']; + $isDisabled?: TextFieldProps['disabled']; + $searchPrefix?: TextFieldProps['searchPrefix']; + $width?: TextFieldProps['width']; +} + +export const StyledTextFieldWrapper = styled.div<StyledTextFieldProps>` + width: ${({ $width }) => $width}; + height: 46px; + display: flex; + align-items: center; + + background: ${({ theme }) => theme.color.inputFieldElevated}; + border: 1px solid ${({ theme }) => theme.color.inputFieldElevated}; + border-radius: 8px; + user-select: none; + + margin: 8px 0 0 0; + padding: 12px 16px; + + .suffix-icon { + visibility: hidden; + cursor: pointer; + } + + input:focus + .suffix-icon, + input:active + .suffix-icon { + visibility: visible; + display: flex; + align-items: center; + } + + ${({ $isDisabled, $isPositive, $isNegative, theme }) => + !$isDisabled && + ($isNegative + ? css` + border: 1px solid ${theme.color.textWarned}; + ` + : $isPositive && + css` + border: 1px solid ${theme.color.textPointed}; + `)} + + ${({ $isDisabled }) => + $isDisabled && + css` + input:focus + .suffix-icon, + input:active + .suffix-icon { + display: none; + } + `} +`; + +export const StyledTextField = styled.input<StyledTextFieldProps>` + width: 100%; + margin-left: ${({ $searchPrefix }) => $searchPrefix && '4px'}; + + background-color: transparent; + border: none; + outline: none; + ${({ theme }) => theme.typo.body1}; + + caret-color: ${({ theme }) => theme.color.textPointed}; + + &:disabled { + cursor: not-allowed; + color: ${({ theme }) => theme.color.textDisabled}; + } + + &::placeholder { + color: ${({ theme, disabled }) => + disabled ? theme.color.textDisabled : theme.color.textTertiary}; + } +`; + +export const StyledFieldLabel = styled.label<StyledTextFieldProps>` + ${({ theme }) => theme.typo.subtitle3}; + color: ${({ theme, $isDisabled }) => + $isDisabled ? theme.color.textDisabled : theme.color.textSecondary}; +`; + +export const StyledHelperLabel = styled.div<StyledTextFieldProps>` + ${({ theme }) => theme.typo.caption1}; + width: 100%; + padding: 8px 0 0 8px; + word-break: break-all; + + color: ${({ $isDisabled, theme }) => + $isDisabled ? theme.color.textDisabled : theme.color.textTertiary}; + + ${({ $isDisabled, $isNegative, theme }) => + !$isDisabled && + $isNegative && + css` + color: ${theme.color.textWarned}; + `}; +`; diff --git a/src/components/TextField/TextField.tsx b/src/components/TextField/TextField.tsx new file mode 100644 index 0000000..25c50ae --- /dev/null +++ b/src/components/TextField/TextField.tsx @@ -0,0 +1,43 @@ +import { + StyledFieldLabel, + StyledHelperLabel, + StyledTextField, + StyledTextFieldWrapper, +} from './TextField.style'; +import { TextFieldProps } from './TextField.type'; + +export const TextField = ({ + isNegative, + isPositive, + isFocused, + isTyping, + fieldLabel, + helperLabel, + suffix, + searchPrefix, + width, + ...props +}: TextFieldProps) => { + return ( + <StyledFieldLabel $isDisabled={props.disabled}> + {fieldLabel} + <StyledTextFieldWrapper + $isNegative={isNegative} + $isPositive={isPositive} + $isFocused={isFocused} + $isTyping={isTyping} + $isDisabled={props.disabled} + $width={width} + > + {searchPrefix} + <StyledTextField {...props} /> + {suffix} + </StyledTextFieldWrapper> + {helperLabel && ( + <StyledHelperLabel $isNegative={isNegative} $isDisabled={props.disabled}> + {helperLabel} + </StyledHelperLabel> + )} + </StyledFieldLabel> + ); +}; diff --git a/src/components/TextField/TextField.type.ts b/src/components/TextField/TextField.type.ts new file mode 100644 index 0000000..40f1bec --- /dev/null +++ b/src/components/TextField/TextField.type.ts @@ -0,0 +1,21 @@ +export interface TextFieldProps extends React.InputHTMLAttributes<HTMLInputElement> { + /** ์ž…๋ ฅ๋œ ๋‚ด์šฉ์ด ์กฐ๊ฑด์— ์–ด๊ธ‹๋‚˜๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ์†์„ฑ */ + isNegative?: boolean; + /** ์ž…๋ ฅ๋œ ๋‚ด์šฉ์ด ์กฐ๊ฑด์— ๋ถ€ํ•ฉํ•˜๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ์†์„ฑ */ + isPositive?: boolean; + /** TextField์— ํฌ์ปค์Šค๊ฐ€ ์žกํ˜€์žˆ๋Š”์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ์†์„ฑ */ + isFocused?: boolean; + /** isFocused=true์ผ ๋•Œ, ์ž…๋ ฅ๋œ ๋‚ด์šฉ์ด ํ•œ ๊ธ€์ž ์ด์ƒ์ธ์ง€ ๋‚˜ํƒ€๋‚ด๋Š” ์†์„ฑ */ + isTyping?: boolean; + + /** TextField์— ๋ฌด์—‡์„ ์ž…๋ ฅํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ธฐ์ž…ํ•˜๋Š” ์†์„ฑ */ + fieldLabel?: string; + /** TextField ์•„๋ž˜์— ๋“ค์–ด๊ฐ€๋Š” ๋„์›€๋ง ํ…์ŠคํŠธ */ + helperLabel?: string; + /** TextField ๋‚ด๋ถ€ ์˜ค๋ฅธ์ชฝ์— ๋“ค์–ด๊ฐˆ ์•„์ด์ฝ˜ (๋˜๋Š” ํ…์ŠคํŠธ) */ + suffix?: React.ReactNode; + /** TextField ๋‚ด๋ถ€ ์™ผ์ชฝ์— ๋“ค์–ด๊ฐˆ ๊ฒ€์ƒ‰ ์•„์ด์ฝ˜ */ + searchPrefix?: React.ReactNode; + /** TextField์˜ width */ + width?: number | string; +} diff --git a/src/components/TextField/index.ts b/src/components/TextField/index.ts new file mode 100644 index 0000000..a2cc4f0 --- /dev/null +++ b/src/components/TextField/index.ts @@ -0,0 +1,2 @@ +export { SimpleTextField } from './SimpleTextField/SimpleTextField'; +export type { SimpleTextFieldProps } from './SimpleTextField/SimpleTextField.type'; diff --git a/src/components/Toast/HookSource.md b/src/components/Toast/HookSource.md new file mode 100644 index 0000000..680d789 --- /dev/null +++ b/src/components/Toast/HookSource.md @@ -0,0 +1,19 @@ +```typescript +import { ToastDuration, useToast, Toast } from '@yourssu/design-system-react'; + +const ToastWrapper = () => { + const toastProps = { + children: 'ํ™”๋ฉด์— ๋„์šธ ๋ฉ”์‹œ์ง€', + duration: 'long' as ToastDuration, + }; + + const { showToast, isShowToast } = useToast(); + + return ( + <div> + <button onClick={() => { showToast(toastProps.duration); }}> ๋ฒ„ํŠผ </button> + {isShowToast && <Toast {...toastProps} />} + </div> + ); +}; +``` diff --git a/src/components/Toast/Toast.stories.tsx b/src/components/Toast/Toast.stories.tsx index 5721217..7791ce1 100644 --- a/src/components/Toast/Toast.stories.tsx +++ b/src/components/Toast/Toast.stories.tsx @@ -1,7 +1,16 @@ +import { + Stories, + Primary as PrimaryBlock, + Controls, + Title, + Description, + Markdown, +} from '@storybook/blocks'; import { Meta, StoryObj } from '@storybook/react'; import { useToast } from '@/hooks/useToast'; +import HookSource from './HookSource.md?raw'; import { Toast } from './Toast'; import { ToastDuration } from './Toast.type'; @@ -10,13 +19,36 @@ const meta: Meta<typeof Toast> = { component: Toast, parameters: { layout: 'centered', + docs: { + page: () => ( + <> + <Title /> + <PrimaryBlock /> + <Controls /> + <h2> ์ฃผ์˜์‚ฌํ•ญ </h2> + <ol> + <li>Toast์˜ width๋Š” Toast ๋ฅผ ๊ฐ์‹ธ๋Š” ์ปดํฌ๋„ŒํŠธ์˜ width์— ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.</li> + <li> + Toast์˜ ์œ„์น˜๋Š” position: relative ์†์„ฑ์ด ์„ค์ •๋œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์— ์˜ํ•ด + ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. + </li> + </ol> + <br /> + <Title>useToast + Toast ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ Custom Hook์ž…๋‹ˆ๋‹ค. + {HookSource} +
+ + + ), + }, }, }; export default meta; const ToastStory = ({ ...toastProps }) => { return ( -
+
{ return (