Skip to content

Commit

Permalink
Merge pull request #181 from boostcampwm-2024/feature/fe/#112-storybook
Browse files Browse the repository at this point in the history
[FE][Fix][Docs] #112 : Dropdown ์ˆœํ™˜ ์ฐธ์กฐ ๋ฒ„๊ทธ ์ˆ˜์ • ๋ฐ ์Šคํ† ๋ฆฌ๋ถ ์ถ”๊ฐ€
  • Loading branch information
effozen authored Nov 18, 2024
2 parents 557873c + 2361010 commit 795b38d
Show file tree
Hide file tree
Showing 20 changed files with 436 additions and 369 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
## ๐Ÿ— ๋งํฌ ์•ˆ๋‚ด

<p>
<a href="https://www.notion.so/127b1b2b649180e88f70d6a4648924a0?pvs=4">ํŒ€ ๋…ธ์…˜</a> |
<a href="https://ddara-docs.vercel.app/">ํŒ€ ์œ„ํ‚ค</a> |
<a href="https://www.notion.so/127b1b2b649180e88f70d6a4648924a0?pvs=4">ํŒ€ ๋…ธ์…˜</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=90-1897">๊ธฐํš์„œ</a> |
<a href="https://www.figma.com/design/r9nl4Jcz9VXIMbrpf50wY6/PickMeUp?node-id=87-929">๋””์ž์ธ</a>
<!-- <br />
Expand Down
45 changes: 27 additions & 18 deletions frontend/src/component/common/dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,42 @@
import { createContext, ReactNode, useMemo, useState } from 'react';
import { ReactNode } from 'react';
import { DropdownTrigger } from '@/component/common/dropdown/DropdownTrigger.tsx';
import { DropdownItem } from '@/component/common/dropdown/DropdownItem.tsx';
import { DropdownMenu } from '@/component/common/dropdown/DropdownMenu.tsx';
import { ToggleProvider } from '@/component/common/dropdown/DropdownContext.tsx';

interface IDropdownProps {
/** ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐˆ ์ปจํ…์ธ  */
children: ReactNode;
}

export interface IToggleContext {
isOpen: boolean;
toggle: () => void;
}

export const ToggleContext = createContext<IToggleContext>({
isOpen: false,
toggle: () => {},
});
/**
* ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
*
* @param {ReactNode} children - ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐˆ ์ปจํ…์ธ 
* @return {JSX.Element} ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ
*
* @remarks
* - ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
*
* @example
* ```tsx
* <Dropdown>
* <Dropdown.Trigger>
* <MdMenu className="h-6 w-6" />
* <span>๋ฉ”๋‰ด</span>
* </Dropdown.Trigger>
* <Dropdown.Menu>
* <Dropdown.Item>๋ฉ”๋‰ด ํ•ญ๋ชฉ 1</Dropdown.Item>
* <Dropdown.Item>๋ฉ”๋‰ด ํ•ญ๋ชฉ 2</Dropdown.Item>
* </Dropdown.Menu>
* </Dropdown>
* ```
*/

// Todo : ๋“œ๋ž๋‹ค์šด ์™ธ๋ถ€์—์„œ ํด๋ฆญ์‹œ ์ฐฝ ๋‹ซํžˆ๊ฒŒ ์„ค์ •
export const Dropdown = (props: IDropdownProps) => {
const [isOpen, setIsOpen] = useState(false);

const toggle = () => setIsOpen(prevIsOpen => !prevIsOpen);

const toggleContextValue = useMemo(() => ({ isOpen, toggle }), [isOpen]);

return (
<aside className="relative flex w-fit flex-col">
<ToggleContext.Provider value={toggleContextValue}>{props.children}</ToggleContext.Provider>
<ToggleProvider>{props.children}</ToggleProvider>
</aside>
);
};
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/component/common/dropdown/DropdownContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { createContext, ReactNode, useMemo, useState } from 'react';

export interface IToggleContext {
isOpen: boolean;
toggle: () => void;
}

interface IToggleProviderProps {
children: ReactNode;
}

export const ToggleContext = createContext<IToggleContext>({
isOpen: false,
toggle: () => {},
});

export const ToggleProvider = (props: IToggleProviderProps) => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(prevIsOpen => !prevIsOpen);
const toggleContextValue = useMemo(() => ({ isOpen, toggle }), [isOpen]);

return (
<ToggleContext.Provider value={toggleContextValue}>{props.children}</ToggleContext.Provider>
);
};
24 changes: 22 additions & 2 deletions frontend/src/component/common/dropdown/DropdownItem.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { ReactNode } from 'react';

interface IDropdownItemProps {
/** ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ๋‚ด์šฉ */
children: ReactNode;
/** ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜ */
onClick?: React.MouseEventHandler<HTMLButtonElement>;
}

/**
* ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์˜ ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
*
* @param {ReactNode} children - ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ๋‚ด์šฉ
* @param {React.MouseEventHandler<HTMLButtonElement>} onClick - ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ์‹คํ–‰ํ•  ํ•จ์ˆ˜
* @return {JSX.Element} ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ
*
* @remarks
* - ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์˜ ์•„์ดํ…œ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฒ„ํŠผ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ๋Š” ํด๋ฆญ ์‹œ onClick ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
*
* @example
* ```tsx
* <Dropdown.Item onClick={handleOnClick}>์•„์ดํ…œ</Dropdown.Item>
* ```
*/

export const DropdownItem = (props: IDropdownItemProps) => {
// undefined๋Š” react์—์„œ ๋žœ๋”๋ง ํ•˜์ง€ ์•Š์Œ
return (
<li className="px-3 py-1.5 text-base">
<li className="list-none px-3 py-1.5 text-base">
<button
type="button"
className="flex w-full items-center justify-between whitespace-nowrap bg-transparent"
Expand Down
23 changes: 22 additions & 1 deletion frontend/src/component/common/dropdown/DropdownMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
import { ReactNode, useContext, useRef, useEffect } from 'react';
import classNames from 'classnames';
import { ToggleContext } from '@/component/common/dropdown/Dropdown.tsx';
import { ToggleContext } from '@/component/common/dropdown/DropdownContext';

interface IDropdownMenuProps {
/** ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด๊ฐ€ ์—ด๋ ค์žˆ๋Š”์ง€ ์—ฌ๋ถ€ */
children: ReactNode | ReactNode[];
}

/**
* ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
*
* @param {ReactNode} children - ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด์— ๋“ค์–ด๊ฐˆ ์ปจํ…์ธ 
* @return {JSX.Element} ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ปดํฌ๋„ŒํŠธ
*
* @remarks
* - ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
*
* @example
* ```tsx
* <Dropdown.Menu>
* <Dropdown.Item>๋ฉ”๋‰ด ํ•ญ๋ชฉ 1</Dropdown.Item>
* <Dropdown.Item>๋ฉ”๋‰ด ํ•ญ๋ชฉ 2</Dropdown.Item>
* </Dropdown.Menu>
* ```
*/

export const DropdownMenu = (props: IDropdownMenuProps) => {
const { isOpen, toggle } = useContext(ToggleContext);
const ref = useRef<HTMLUListElement | null>(null);
Expand Down Expand Up @@ -55,6 +75,7 @@ export const DropdownMenu = (props: IDropdownMenuProps) => {
'shadow-2xl',
'w-fit',
'bg-white',
'list-none',
)}
>
{props.children}
Expand Down
23 changes: 22 additions & 1 deletion frontend/src/component/common/dropdown/DropdownTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
import { ReactNode, useContext } from 'react';
import classNames from 'classnames';
import { ToggleContext } from '@/component/common/dropdown/Dropdown.tsx';
import { ToggleContext } from '@/component/common/dropdown/DropdownContext';

interface IDropdownTriggerProps {
/** ๋ฒ„ํŠผ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐˆ ์ปจํ…์ธ  */
children: ReactNode;
}

/**
* ๋“œ๋กญ๋‹ค์šด์—์„œ ๋ฉ”๋‰ด๋ฅผ ์—ด๊ณ  ๋‹ซ๋Š” ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ์ž…๋‹ˆ๋‹ค.
*
* @param {ReactNode} children - ๋ฒ„ํŠผ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐˆ ์ปจํ…์ธ 
* @return {JSX.Element} ๋“œ๋กญ๋‹ค์šด ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ
*
* @remarks
* - ๋“œ๋กญ๋‹ค์šด ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋“œ๋กญ๋‹ค์šด ๋ฉ”๋‰ด๋ฅผ ์—ด๊ณ  ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ๋Š” ๋“œ๋กญ๋‹ค์šด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์‚ฌ์šฉ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
* - ๋“œ๋กญ๋‹ค์šด ํŠธ๋ฆฌ๊ฑฐ ์ปดํฌ๋„ŒํŠธ๋Š” ๋ฒ„ํŠผ ์—ญํ• ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
*
* @example
* ```tsx
* <Dropdown.Trigger>
* <MdMenu className="h-6 w-6" />
* <span>๋ฉ”๋‰ด</span>
* </Dropdown.Trigger>
* ```
*/

export const DropdownTrigger = (props: IDropdownTriggerProps) => {
const { toggle } = useContext(ToggleContext);

Expand Down
Loading

0 comments on commit 795b38d

Please sign in to comment.