diff --git a/README.md b/README.md index 996b615a..0dc5703b 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ ## πŸ— 링크 μ•ˆλ‚΄

- νŒ€ λ…Έμ…˜ | νŒ€ μœ„ν‚€ | + νŒ€ λ…Έμ…˜ | κΈ°νšμ„œ | λ””μžμΈ ) +

- .sb-addon { - width: 100%; - display: flex; - align-items: center; - position: relative; - background-color: #EEF3F8; - border-radius: 5px; - border: 1px solid rgba(0, 0, 0, 0.05); - background: #EEF3F8; - height: 180px; - margin-bottom: 48px; - overflow: hidden; - } - - .sb-addon-text { - padding-left: 48px; - max-width: 240px; - } - - .sb-addon-text h4 { - padding-top: 0px; - } - - .sb-addon-img { - position: absolute; - left: 345px; - top: 0; - height: 100%; - width: 200%; - overflow: hidden; - } - - .sb-addon-img img { - width: 650px; - transform: rotate(-15deg); - margin-left: 40px; - margin-top: -72px; - box-shadow: 0 0 1px rgba(255, 255, 255, 0); - backface-visibility: hidden; - } - - @media screen and (max-width: 800px) { - .sb-addon-img { - left: 300px; - } - } - - @media screen and (max-width: 600px) { - .sb-section { - flex-direction: column; - } - - .sb-features-grid { - grid-template-columns: repeat(1, 1fr); - } - - .sb-socials { - grid-template-columns: repeat(2, 1fr); - } - - .sb-addon { - height: 280px; - align-items: flex-start; - padding-top: 32px; - overflow: hidden; - } - - .sb-addon-text { - padding-left: 24px; - } - - .sb-addon-img { - right: 0; - left: 0; - top: 130px; - bottom: 0; - overflow: hidden; - height: auto; - width: 124%; - } + - .sb-addon-img img { - width: 1200px; - transform: rotate(-12deg); - margin-left: 0; - margin-top: 48px; - margin-bottom: -40px; - margin-left: -24px; - } - } - `} - +
+


+ + +## 🌱 νŒ€μ› μ†Œκ°œ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
J060_김주원J174_μ΄λ™μœ¨J210_μž„μž¬λ„J234_μ •ν˜œμΈ
FEFEFEFull Stack (FE + BE)
@juwon5272@leedongyull@effozen@happyhyep
+ +
+ +## ⛏ 기술 μŠ€νƒ + +μΆ”ν›„ μΆ”κ°€ μ˜ˆμ •μž…λ‹ˆλ‹€. + +[//]: # () +
diff --git a/frontend/src/stories/common/modal/Modal.stories.tsx b/frontend/src/stories/common/modal/Modal.stories.tsx new file mode 100644 index 00000000..4fb7b29b --- /dev/null +++ b/frontend/src/stories/common/modal/Modal.stories.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { Modal } from '@/component/common/modal/Modal'; +import { useModal } from '@/hooks/useModal'; +import { fn } from '@storybook/test'; + +export default { + title: 'Components/common/modal/Modal', + component: Modal, + tags: ['autodocs'], +} as Meta; + +const LoginModalTemplate: Story = () => { + const { isOpen, onOpen, onClose } = useModal(); + + return ( +
+ + + + + + + + +
+ ); +}; + +const RegisterModalTemplate: Story = () => { + const { isOpen, onOpen, onClose } = useModal(); + + return ( +
+ + + + + + + + + + + +
+ ); +}; + +export const LoginModal = LoginModalTemplate.bind({}); +LoginModal.parameters = { + docs: { + description: { + story: '둜그인 λͺ¨λ‹¬ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ Œλ”λ§ν•©λ‹ˆλ‹€.', + }, + }, + backgrounds: { + default: 'gray', + values: [{ name: 'gray', value: '#f3f4f6' }], + }, +}; + +export const RegisterModal = RegisterModalTemplate.bind({}); +RegisterModal.parameters = { + docs: { + description: { + story: 'νšŒμ›κ°€μž… λͺ¨λ‹¬ μ»΄ν¬λ„ŒνŠΈλ₯Ό λ Œλ”λ§ν•©λ‹ˆλ‹€.', + }, + }, + backgrounds: { + default: 'gray', + values: [{ name: 'gray', value: '#f3f4f6' }], + }, +}; diff --git a/frontend/src/stories/common/modal/ModalFooter.stories.tsx b/frontend/src/stories/common/modal/ModalFooter.stories.tsx new file mode 100644 index 00000000..767fca48 --- /dev/null +++ b/frontend/src/stories/common/modal/ModalFooter.stories.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { ModalFooter } from '@/component/common/modal/ModalFooter'; +import { fn } from '@storybook/test'; + +export default { + title: 'Components/common/modal/ModalFooter', + component: ModalFooter, + parameters: { layout: 'centered' }, + tags: ['autodocs'], +} as Meta; + +const Template: Story = args => ; + +export const OneButton = Template.bind({}); +OneButton.args = { + text: 'νšŒμ›κ°€μž…', + onClick: fn(), +}; + +export const TwoButton = Template.bind({}); +TwoButton.args = { + text: '둜그인', + onClick: fn(), + text2: 'νšŒμ›κ°€μž…', + onClick2: fn(), +}; diff --git a/frontend/src/stories/common/modal/ModalHeader.stories.tsx b/frontend/src/stories/common/modal/ModalHeader.stories.tsx new file mode 100644 index 00000000..ca09941b --- /dev/null +++ b/frontend/src/stories/common/modal/ModalHeader.stories.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { ModalHeader } from '@/component/common/modal/ModalHeader'; +import { fn } from '@storybook/test'; + +export default { + title: 'Components/common/modal/ModalHeader', + component: ModalHeader, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, +} as Meta; + +const Template: Story = args => ; + +export const DefaultHeader = Template.bind({}); +DefaultHeader.args = { + content: 'Login', + onClose: fn(), +}; diff --git a/frontend/src/stories/common/modal/ModalInput.stories.tsx b/frontend/src/stories/common/modal/ModalInput.stories.tsx new file mode 100644 index 00000000..8a4968f7 --- /dev/null +++ b/frontend/src/stories/common/modal/ModalInput.stories.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Meta, Story } from '@storybook/react'; +import { ModalInput } from '@/component/common/modal/ModalInput'; +import { fn } from '@storybook/test'; + +export default { + title: 'Components/common/modal/ModalInput', + component: ModalInput, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], +} as Meta; + +const Template: Story = args => ; + +export const DefaultInput = Template.bind({}); +DefaultInput.args = { + title: 'ID', + name: 'id', + placeholder: 'μ‚¬μš©ν•  IDλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”.', + value: '', + onChange: fn(), +}; + +export const NoTitle = Template.bind({}); +NoTitle.args = { + title: '', + name: 'confirmPw', + placeholder: 'λΉ„λ°€λ²ˆν˜Έλ₯Ό ν•œ 번 더 μž…λ ₯ν•΄μ£Όμ„Έμš”.', + value: '', + onChange: fn(), +}; diff --git a/frontend/src/stories/dropdown/Dropdown.stories.tsx b/frontend/src/stories/dropdown/Dropdown.stories.tsx new file mode 100644 index 00000000..e81e031d --- /dev/null +++ b/frontend/src/stories/dropdown/Dropdown.stories.tsx @@ -0,0 +1,64 @@ +// Dropdown.stories.tsx +import type { Meta, StoryObj } from '@storybook/react'; +import { Dropdown } from '@/component/common/dropdown/Dropdown.tsx'; +import { MdLocationOn, MdMenu } from 'react-icons/md'; +import classNames from 'classnames'; +import { DropdownItem } from '@/component/common/dropdown/DropdownItem.tsx'; + +const meta: Meta = { + title: 'Components/Common/Dropdown/Dropdown', + component: Dropdown, + parameters: { + layout: 'fullscreen', // 쀑앙 μ •λ ¬ λ ˆμ΄μ•„μ›ƒ + }, + tags: ['autodocs'], + decorators: [ + Story => ( +
+ +
+ ), + ], + argTypes: { + // 'children'에 λŒ€ν•œ 컨트둀 λΉ„ν™œμ„±ν™” + children: { control: false }, + }, +}; + +export default meta; +type Story = StoryObj; + +const textMarkerUser = [ + 'text-marker-user1', + 'text-marker-user2', + 'text-marker-user3', + 'text-marker-user4', + 'text-marker-user5', +]; + +export const Default: Story = { + render: () => ( + + + + + + {['μ‚¬μš©μž 1', 'μ‚¬μš©μž 2', 'μ‚¬μš©μž 3', 'μ‚¬μš©μž 4', 'μ‚¬μš©μž 5'].map((e, i) => { + return ( + + {e} + + {/* μ•„μ΄μ½˜ 색 λ³€κ²½ 둜직 μ°ΎκΈ°, ν˜„μž¬λŠ” μ•„μ΄μ½˜μƒ‰μ΄ 반영이 μ•ˆλ¨ μˆ˜μ •ν•  사 */} + + ); + })} + + + ), +}; diff --git a/frontend/src/stories/dropdown/DropdownItem.stories.tsx b/frontend/src/stories/dropdown/DropdownItem.stories.tsx new file mode 100644 index 00000000..d623f021 --- /dev/null +++ b/frontend/src/stories/dropdown/DropdownItem.stories.tsx @@ -0,0 +1,42 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { fn } from '@storybook/test'; + +import { DropdownItem } from '@/component/common/dropdown/DropdownItem.tsx'; +import { ToggleProvider } from '@/component/common/dropdown/DropdownContext.tsx'; +import { MdLocationOn } from 'react-icons/md'; +import classNames from 'classnames'; + +const meta = { + title: 'Components/Common/Dropdown/DropdownItem', + component: DropdownItem, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + decorators: [ + Story => ( + + + + ), + ], + argTypes: { + // 'children'에 λŒ€ν•œ 컨트둀 λΉ„ν™œμ„±ν™” + children: { control: false }, + }, + args: { onClick: fn() }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + μ‚¬μš©μž 1 + + ), + }, +}; diff --git a/frontend/src/stories/dropdown/DropdownMenu.stories.tsx b/frontend/src/stories/dropdown/DropdownMenu.stories.tsx new file mode 100644 index 00000000..f2089419 --- /dev/null +++ b/frontend/src/stories/dropdown/DropdownMenu.stories.tsx @@ -0,0 +1,91 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { DropdownMenu } from '@/component/common/dropdown/DropdownMenu.tsx'; +import { DropdownItem } from '@/component/common/dropdown/DropdownItem.tsx'; +import { MdLocationOn } from 'react-icons/md'; +import { ToggleContext } from '@/component/common/dropdown/DropdownContext.tsx'; +import classNames from 'classnames'; + +const meta = { + title: 'Components/Common/Dropdown/DropdownMenu', + component: DropdownMenu, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + decorators: [ + Story => ( + {}, + }} + > +
+ +
+
+ ), + ], + argTypes: { + // 'children'에 λŒ€ν•œ 컨트둀 λΉ„ν™œμ„±ν™” + children: { + control: false, + }, + }, + args: {}, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + children: ['μ‚¬μš©μž 1', 'μ‚¬μš©μž 2', 'μ‚¬μš©μž 3', 'μ‚¬μš©μž 4', 'μ‚¬μš©μž 5'].map((e, i) => { + const textMarkerUser = [ + 'text-marker-user1', + 'text-marker-user2', + 'text-marker-user3', + 'text-marker-user4', + 'text-marker-user5', + ]; + + return ( + + {e} + + {/* μ•„μ΄μ½˜ 색 λ³€κ²½ 둜직 μ°ΎκΈ°, ν˜„μž¬λŠ” μ•„μ΄μ½˜μƒ‰μ΄ 반영이 μ•ˆλ¨ μˆ˜μ •ν•  사 */} + + ); + }), + }, +}; + +export const Secondary: Story = { + args: { + children: ['μ‚¬μš©μž 1', 'μ‚¬μš©μž 2'].map((e, i) => { + const textMarkerUser = [ + 'text-marker-user1', + 'text-marker-user2', + 'text-marker-user3', + 'text-marker-user4', + 'text-marker-user5', + ]; + + return ( + + {e} + + {/* μ•„μ΄μ½˜ 색 λ³€κ²½ 둜직 μ°ΎκΈ°, ν˜„μž¬λŠ” μ•„μ΄μ½˜μƒ‰μ΄ 반영이 μ•ˆλ¨ μˆ˜μ •ν•  사 */} + + ); + }), + }, +}; diff --git a/frontend/src/stories/dropdown/DropdownTrigger.stories.tsx b/frontend/src/stories/dropdown/DropdownTrigger.stories.tsx new file mode 100644 index 00000000..f9e01886 --- /dev/null +++ b/frontend/src/stories/dropdown/DropdownTrigger.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { DropdownTrigger } from '@/component/common/dropdown/DropdownTrigger.tsx'; +import { ToggleProvider } from '@/component/common/dropdown/DropdownContext.tsx'; +import { MdMenu, MdMoreVert } from 'react-icons/md'; + +const meta = { + title: 'Components/Common/Dropdown/DropdownTrigger', + component: DropdownTrigger, + parameters: { + layout: 'centered', + }, + tags: ['autodocs'], + decorators: [ + Story => ( + + + + ), + ], + argTypes: { + // 'children'에 λŒ€ν•œ 컨트둀 λΉ„ν™œμ„±ν™” + children: { control: false }, + }, + args: {}, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const MenuButton: Story = { + args: { + // 'children'에 React μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό 직접 전달 + children: , + }, +}; + +export const DotButton: Story = { + args: { + // 'children'에 React μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό 직접 전달 + children: , + }, +}; diff --git a/frontend/src/stories/Button.stories.ts b/frontend/src/stories/example/Button.stories.ts similarity index 100% rename from frontend/src/stories/Button.stories.ts rename to frontend/src/stories/example/Button.stories.ts diff --git a/frontend/src/stories/Button.tsx b/frontend/src/stories/example/Button.tsx similarity index 100% rename from frontend/src/stories/Button.tsx rename to frontend/src/stories/example/Button.tsx diff --git a/frontend/src/stories/Header.stories.ts b/frontend/src/stories/example/Header.stories.ts similarity index 100% rename from frontend/src/stories/Header.stories.ts rename to frontend/src/stories/example/Header.stories.ts diff --git a/frontend/src/stories/Header.tsx b/frontend/src/stories/example/Header.tsx similarity index 100% rename from frontend/src/stories/Header.tsx rename to frontend/src/stories/example/Header.tsx diff --git a/frontend/src/stories/Page.stories.ts b/frontend/src/stories/example/Page.stories.ts similarity index 100% rename from frontend/src/stories/Page.stories.ts rename to frontend/src/stories/example/Page.stories.ts diff --git a/frontend/src/stories/Page.tsx b/frontend/src/stories/example/Page.tsx similarity index 100% rename from frontend/src/stories/Page.tsx rename to frontend/src/stories/example/Page.tsx diff --git a/frontend/src/stories/button.css b/frontend/src/stories/example/button.css similarity index 100% rename from frontend/src/stories/button.css rename to frontend/src/stories/example/button.css diff --git a/frontend/src/stories/header.css b/frontend/src/stories/example/header.css similarity index 100% rename from frontend/src/stories/header.css rename to frontend/src/stories/example/header.css diff --git a/frontend/src/stories/page.css b/frontend/src/stories/example/page.css similarity index 100% rename from frontend/src/stories/page.css rename to frontend/src/stories/example/page.css