-
Notifications
You must be signed in to change notification settings - Fork 0
Dropdown 컴포넌트 구현 #100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Dropdown 컴포넌트 구현 #100
Conversation
|
PR 제목을 수정해주세요 |
|
PR 제목 수정 완료했습니다 |
ecb7991 to
d65f2ee
Compare
d65f2ee to
a349beb
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-csyflggkxx.chromatic.com/ |
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
|
Warning Rate limit exceeded@Bangdayeon has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 40 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (4)
Walkthrough드롭다운 컴포넌트를 새로 구현했습니다. Tailwind Variants 기반 스타일링 모듈과 함께, 상태 관리, 키보드 상호작용, 접근성 속성을 지원하는 forwardRef 기반 React 컴포넌트를 추가했습니다. Pre-merge checks and finishing touches✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
a349beb to
538d649
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-bygdsohpth.chromatic.com/ |
|
수정 사항
|
538d649 to
bba101e
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-sfbktynzty.chromatic.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (9)
src/components/Dropdown/useDropdown.ts (2)
10-18: 모바일 외부 클릭 누락 + ESC 키 미처리모바일 터치(또는 펜) 입력이 닫힘 처리되지 않고, ESC 키로 닫기 동작도 없습니다. pointerdown/keydown 리스너로 보완하세요. 또한 effect 내부에서
close()참조 대신setIsOpen(false)를 직접 호출하면 deps 경고를 피할 수 있습니다.- useEffect(() => { - const handleClickOutside = (e: MouseEvent) => { - if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { - close(); - } - }; - document.addEventListener('mousedown', handleClickOutside); - return () => document.removeEventListener('mousedown', handleClickOutside); - }, []); + useEffect(() => { + const onPointerDown = (e: PointerEvent) => { + if (dropdownRef.current && !dropdownRef.current.contains(e.target as Node)) { + setIsOpen(false); + } + }; + const onKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Escape') setIsOpen(false); + }; + document.addEventListener('pointerdown', onPointerDown); + document.addEventListener('keydown', onKeyDown); + return () => { + document.removeEventListener('pointerdown', onPointerDown); + document.removeEventListener('keydown', onKeyDown); + }; + }, []);
1-1: toggle/close 메모이제이션으로 핸들러 안정화prop으로 내려보낼 가능성을 고려하면
useCallback으로 고정해두는 편이 안전합니다.-import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef, useState, useCallback } from 'react'; - const toggle = () => setIsOpen(prev => !prev); - const close = () => setIsOpen(false); + const toggle = useCallback(() => setIsOpen(prev => !prev), []); + const close = useCallback(() => setIsOpen(false), []);Also applies to: 7-8
src/components/Dropdown/DropdownMenu.tsx (3)
15-21: Tailwind 클래스 오타 및 충돌 수정 필요
in-w-max는 유효하지 않은 유틸리티이고,border와border-none이 상충합니다. 메뉴가 다른 요소 아래 깔리는 문제도 방지하려면 z-index를 지정하세요.- const baseStyle = clsx( - 'absolute block in-w-max text-gray-900 bg-white border my-1 rounded-md shadow-md border-none', - 'max-h-40 overflow-y-auto', - 'overflow-hidden whitespace-nowrap text-ellipsis' - ); + const baseStyle = clsx( + 'absolute block min-w-max text-gray-900 bg-white my-1 rounded-md shadow-md z-10', + 'max-h-40 overflow-y-auto', + 'ring-1 ring-gray-200' + );
20-25: 항목 패딩이 이중 정의됨
menuStyle에 패딩이 있고sizes에도 패딩이 있어 중복됩니다.sizes만 사용하도록 정리하세요. 또한 항목 텍스트 말줄임은 li에 적용하는 편이 맞습니다.- const menuStyle = 'px-4 py-2 transition-colors hover:bg-gray-200 cursor-pointer'; + const menuStyle = 'transition-colors hover:bg-gray-200 cursor-pointer truncate';Also applies to: 27-27
6-6: 타입 순환 의존성 완화 제안
DropdownMenu가Dropdown에서 타입을 가져오면 구조가 강하게 결합됩니다.Dropdown.types.ts(또는types.ts)로DropdownOption을 분리해 양방향 참조를 없애는 것을 권장합니다.src/components/Dropdown/Dropdown.stories.tsx (2)
39-43: 스토리 args 타입 간소화
ComponentProps<typeof Dropdown>로 간단히 표현하면React제네릭 추론 없이도 명확합니다. 이에 따라 import도 정리 가능합니다.-import React, { useState } from 'react'; +import { useState, type ComponentProps } from 'react'; @@ -function InteractiveDropdown( - args: typeof Dropdown extends React.ComponentType<infer P> ? P : never -) { +function InteractiveDropdown(args: ComponentProps<typeof Dropdown>) {Also applies to: 2-2
7-13: 데모 텍스트 오탈자"Banaaaana"는 문서 품질 측면에서 오타로 보입니다.
- { value: 'banana', label: '🍌 Banaaaana' }, + { value: 'banana', label: '🍌 Banana' },src/components/Dropdown/Dropdown.tsx (2)
33-39: 패딩 클래스 중복 제거
buttonStyle에 패딩이 있고sizes에도 패딩이 있어 중복입니다.buttonStyle에서 패딩을 제거하고sizes로만 제어하세요.- const buttonStyle = - 'px-4 py-2 text-gray-900 max-w-60 rounded-md transition-colors hover:cursor-pointer'; + const buttonStyle = + 'text-gray-900 max-w-60 rounded-md transition-colors hover:cursor-pointer';
59-64: ARIA 연결 보완(권장)버튼에
aria-controls를 부여해 메뉴 요소와 연결하면 보조기기 호환성이 좋아집니다.useId()로 id를 생성해DropdownMenu의ul에 전달하는 방식을 추천합니다. (동시 PR로DropdownMenu에idprop 추가 필요)예시 변경(개략):
- Dropdown.tsx:
import { useId } from 'react'추가,const menuId = useId();생성, 버튼에aria-controls={isOpen ? menuId : undefined}설정,<DropdownMenu id={menuId} ... />전달- DropdownMenu.tsx:
DropdownMenuProps에id?: string추가,<ul id={id} role="menu">로 반영원하시면 관련 패치까지 한 번에 만들어 드리겠습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/Dropdown/Dropdown.stories.tsx(1 hunks)src/components/Dropdown/Dropdown.tsx(1 hunks)src/components/Dropdown/DropdownMenu.tsx(1 hunks)src/components/Dropdown/useDropdown.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/components/Dropdown/DropdownMenu.tsx (1)
src/components/Dropdown/Dropdown.tsx (1)
DropdownOption(9-12)
src/components/Dropdown/Dropdown.stories.tsx (1)
src/components/Dropdown/Dropdown.tsx (2)
DropdownOption(9-12)Dropdown(22-67)
src/components/Dropdown/Dropdown.tsx (2)
src/components/Dropdown/useDropdown.ts (1)
useDropdown(3-20)src/components/Dropdown/DropdownMenu.tsx (1)
DropdownMenu(14-44)
bba101e to
568f845
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-tryjpztisc.chromatic.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (5)
src/components/Dropdown/DropdownMenu.tsx (5)
38-41: Space 키 호환성 보강일부 환경에서 Space 키가
"Spacebar"로 보고됩니다. 아래처럼 분기 추가를 권장합니다.- if (e.key === 'Enter' || e.key === ' ') { + if (e.key === 'Enter' || e.key === ' ' || e.key === 'Spacebar') {
16-19: 텍스트 말줄임 처리 위치 수정 (ul → li)현재
text-ellipsis가ul에 적용돼 항목별 말줄임이 동작하지 않습니다. 스크롤은 컨테이너(ul), 말줄임은 항목(li)에 적용하세요.const baseStyle = clsx( - 'absolute block min-w-max text-gray-900 bg-white my-1 rounded-md shadow-md border-none z-10', - 'max-h-40 overflow-y-auto', - 'overflow-hidden whitespace-nowrap text-ellipsis' + 'absolute block min-w-max text-gray-900 bg-white my-1 rounded-md shadow-md border-none z-10', + 'max-h-40 overflow-y-auto overflow-x-hidden' ); - const menuStyle = 'transition-colors hover:bg-gray-200 cursor-pointer'; + const menuStyle = 'transition-colors hover:bg-gray-200 cursor-pointer truncate';Also applies to: 20-21, 27-27
29-49: 로빙 탭인덱스 및 화살표 키 탐색 추가 제안현재 모든 항목이
tabIndex=0으로 탭 정지가 과도합니다. 메뉴 패턴에 맞춰 로빙 탭인덱스(하나만 0, 나머지 -1)와 ArrowUp/Down, Home/End 포커스 이동을 추가하세요. Enter/Space 활성화는 기존대로 li에서 처리 유지 권장.export function DropdownMenu({ options, onOptionClick, size }: DropdownMenuProps) { const baseStyle = clsx( @@ - return ( - <ul className={baseStyle} role="menu"> - {options.map(option => ( - <li + const listRef = React.useRef<HTMLUListElement>(null); + const handleMenuKeyDown = (e: React.KeyboardEvent<HTMLUListElement>) => { + const items = listRef.current?.querySelectorAll<HTMLLIElement>('li[role="menuitem"]'); + if (!items || items.length === 0) return; + const arr = Array.from(items); + const currentIndex = arr.findIndex(el => el === document.activeElement); + let next = currentIndex; + if (e.key === 'ArrowDown') { e.preventDefault(); next = (currentIndex + 1 + arr.length) % arr.length; } + if (e.key === 'ArrowUp') { e.preventDefault(); next = (currentIndex - 1 + arr.length) % arr.length; } + if (e.key === 'Home') { e.preventDefault(); next = 0; } + if (e.key === 'End') { e.preventDefault(); next = arr.length - 1; } + if (next !== currentIndex && next >= 0) arr[next].focus(); + }; + + return ( + <ul ref={listRef} className={baseStyle} role="menu" onKeyDown={handleMenuKeyDown}> + {options.map((option, index) => ( + <li className={menuClasses} key={option.value} onClick={() => onOptionClick(option)} role="menuitem" - tabIndex={0} + tabIndex={index === 0 ? 0 : -1} onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onOptionClick(option); } }} > {option.label} </li> ))} </ul> ); }
20-21: 포커스 가시성 보강키보드 사용자용 포커스 스타일을 추가하세요.
- const menuStyle = 'transition-colors hover:bg-gray-200 cursor-pointer'; + const menuStyle = 'transition-colors hover:bg-gray-200 cursor-pointer focus:outline-none focus-visible:bg-gray-200 focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-blue-500';
8-12: 메뉴 레이블링 옵션 추가 제안 (a11y)트리거와의 연결(aria-labelledby) 또는 자체 라벨(aria-label)을 prop으로 받을 수 있도록 확장하면 스크린 리더 경험이 개선됩니다.
interface DropdownMenuProps { options: DropdownOption[]; onOptionClick: (option: DropdownOption) => void; size: 'sm' | 'md' | 'lg'; + ariaLabel?: string; + labelledById?: string; } @@ -export function DropdownMenu({ options, onOptionClick, size }: DropdownMenuProps) { +export function DropdownMenu({ options, onOptionClick, size, ariaLabel, labelledById }: DropdownMenuProps) { @@ - <ul className={baseStyle} role="menu"> + <ul className={baseStyle} role="menu" aria-label={ariaLabel} aria-labelledby={labelledById}>검증 요청:
- 트리거 버튼 측에서
aria-haspopup="menu"와aria-expanded가 설정돼 있는지 확인 부탁드립니다.Also applies to: 30-30
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/Dropdown/Dropdown.stories.tsx(1 hunks)src/components/Dropdown/Dropdown.tsx(1 hunks)src/components/Dropdown/DropdownMenu.tsx(1 hunks)src/components/Dropdown/useDropdown.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- src/components/Dropdown/useDropdown.ts
- src/components/Dropdown/Dropdown.stories.tsx
- src/components/Dropdown/Dropdown.tsx
🧰 Additional context used
🧬 Code graph analysis (1)
src/components/Dropdown/DropdownMenu.tsx (1)
src/components/Dropdown/Dropdown.tsx (1)
DropdownOption(9-12)
🔇 Additional comments (1)
src/components/Dropdown/DropdownMenu.tsx (1)
30-37: 이전 피드백 반영 LGTM: role 및 기본 키보드 활성화 정상
ul role="menu",li role="menuitem"으로 수정했고, 클릭 활성화도 적절합니다. 잘 반영되었습니다.
568f845 to
862f955
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-lrmihnqzyy.chromatic.com/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
src/components/Dropdown/useDropdown.ts (1)
10-27: 드롭다운이 닫혀있을 때도 이벤트 리스너가 활성 상태입니다.현재 구현은 드롭다운의 열림 여부와 관계없이 항상 document 레벨 이벤트 리스너를 등록합니다. 페이지에 여러 드롭다운이 있는 경우 불필요한 이벤트 처리가 누적될 수 있습니다.
isOpen상태가true일 때만 리스너를 등록하도록 최적화를 고려해보세요.다음과 같이 리팩토링할 수 있습니다:
useEffect(() => { + if (!isOpen) return; + // 모바일 외부 클릭 처리 const onPointerDown = (e: PointerEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { setIsOpen(false); } }; // ESC 키 처리 const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') setIsOpen(false); }; document.addEventListener('pointerdown', onPointerDown); document.addEventListener('keydown', onKeyDown); return () => { document.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('keydown', onKeyDown); }; - }, [ref]); + }, [ref, isOpen]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/components/Dropdown/Dropdown.stories.tsx(1 hunks)src/components/Dropdown/Dropdown.tsx(1 hunks)src/components/Dropdown/useDropdown.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/components/Dropdown/Dropdown.tsx
- src/components/Dropdown/Dropdown.stories.tsx
🔇 Additional comments (2)
src/components/Dropdown/useDropdown.ts (2)
6-8: useCallback 메모이제이션 적절함.toggle 및 close 함수를 useCallback으로 메모이제이션하여 불필요한 재생성을 방지한 것은 좋은 패턴입니다.
12-16: 리뷰 댓글은 부정확합니다. 현재 구현이 올바르게 작동하고 있습니다.코드를 검증한 결과:
ref 위치가 올바름: Dropdown.tsx 43줄의
<div ref={ref}>가 토글 버튼과 드롭다운 메뉴를 모두 감싸고 있습니다.이벤트 처리 로직이 정상 작동: useDropdown.ts 13줄의
ref.current.contains(e.target as Node)체크로 인해:
- 버튼 클릭 시: 버튼이 ref 컨테이너 내부에 있으므로
contains()반환값이 TRUE → 드롭다운이 닫히지 않음- 외부 클릭 시:
contains()반환값이 FALSE → 드롭다운이 닫힘결과: 토글 버튼 클릭 시 드롭다운이 즉시 닫히지 않으며, 버튼의
onClick={toggle}핸들러가 정상적으로 작동합니다.Likely an incorrect or invalid review comment.
862f955 to
839d8ed
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-hwnbwlbant.chromatic.com/ |
|
문서로 정리한 기본 컴포넌트 구현 방식을 따르는지 확인부탁드립니다 |
839d8ed to
8280261
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-jccgierqyb.chromatic.com/ |
8280261 to
1f7e109
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
🧹 Nitpick comments (3)
src/components/basics/Dropdown/useDropdown.ts (1)
10-27: 리스너 최적화를 고려해보세요.현재 구현은 드롭다운이 닫혀있을 때도 전역 리스너가 계속 활성화되어 있습니다.
isOpen상태에 따라 조건부로 리스너를 등록하면 불필요한 이벤트 처리를 줄일 수 있습니다.🔎 최적화 제안
useEffect(() => { + if (!isOpen) return; + // 모바일 외부 클릭 처리 const onPointerDown = (e: PointerEvent) => { if (ref.current && !ref.current.contains(e.target as Node)) { setIsOpen(false); } }; // ESC 키 처리 const onKeyDown = (e: KeyboardEvent) => { if (e.key === 'Escape') setIsOpen(false); }; document.addEventListener('pointerdown', onPointerDown); document.addEventListener('keydown', onKeyDown); return () => { document.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('keydown', onKeyDown); }; - }, [ref]); + }, [ref, isOpen]);src/components/basics/Dropdown/Dropdown.tsx (2)
22-28: 중복된 기본값 처리를 단순화하세요.
defaultSelected는 이미 파라미터에서options[0]로 기본값이 설정되어 있는데, Line 27에서 다시?? options[0] ?? null로 체크하고 있습니다. 이는 불필요한 중복입니다.🔎 단순화 제안
const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(function Dropdown( { options, defaultSelected = options[0], size = 'sm', onSelect, ...rest }, ref ) { const { isOpen, toggle, close } = useDropdown(ref as React.RefObject<HTMLDivElement>); - const [selected, setSelected] = useState<DropdownOption | null>( - defaultSelected ?? options[0] ?? null - ); + const [selected, setSelected] = useState<DropdownOption>(defaultSelected);
48-70: 불필요한 div 래퍼를 제거하세요.Line 50의 빈
<div>는 아무런 역할을 하지 않으므로 제거할 수 있습니다.🔎 수정 제안
{isOpen && options.length > 0 && ( <ul className={contentStyle()} role="menu"> - <div className=""> - {options.map(option => ( - <li - className={listStyle({ size })} - key={option.value} - onClick={() => handleOptionClick(option)} - role="menuItem" - tabIndex={0} - onKeyDown={e => { - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - handleOptionClick(option); - } - }} - > - {option.label} - </li> - ))} - </div> + {options.map(option => ( + <li + className={listStyle({ size })} + key={option.value} + onClick={() => handleOptionClick(option)} + role="menuItem" + tabIndex={0} + onKeyDown={e => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + handleOptionClick(option); + } + }} + > + {option.label} + </li> + ))} </ul> )}
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/components/basics/Dropdown/Dropdown.styles.tssrc/components/basics/Dropdown/Dropdown.tsxsrc/components/basics/Dropdown/useDropdown.tssrc/stories/Dropdown.stories.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
src/stories/Dropdown.stories.tsx (1)
src/components/basics/Dropdown/Dropdown.tsx (1)
DropdownOption(9-12)
src/components/basics/Dropdown/Dropdown.tsx (2)
src/components/basics/Dropdown/useDropdown.ts (1)
useDropdown(3-29)src/components/basics/Dropdown/Dropdown.styles.ts (2)
contentStyle(3-5)listStyle(7-16)
🪛 GitHub Actions: CI
src/stories/Dropdown.stories.tsx
[error] 2-2: ESLint: storybook/no-renderer-packages - Do not import renderer package "@storybook/react" directly. Use a framework package instead. Command: 'pnpm exec eslint "src/**/*.{js,jsx,ts,tsx}" --max-warnings=0'
🪛 GitHub Check: ci
src/stories/Dropdown.stories.tsx
[failure] 2-2:
Do not import renderer package "@storybook/react" directly. Use a framework package instead (e.g. @storybook/nextjs, @storybook/react-vite, @storybook/nextjs-vite, @storybook/react-webpack5, @storybook/react-native-web-vite)
🔇 Additional comments (2)
src/components/basics/Dropdown/Dropdown.tsx (1)
38-47:colorprop과 Button의variant관계를 명확히 하세요.Line 45에서
Button의variant가"primary"로 하드코딩되어 있습니다. 정의되어 있지만 사용되지 않는colorprop이 Button의 스타일을 제어하기 위한 것인지 확인이 필요합니다.만약
colorprop이 Button의 색상을 제어해야 한다면, 이를variant나 다른 Button prop에 매핑해야 합니다.src/stories/Dropdown.stories.tsx (1)
2-2: import 문은 올바릅니다. Storybook 8.x에서 Next.js를 사용할 때, 타입Meta와StoryObj는@storybook/react에서 import하는 것이 표준입니다.@storybook/nextjs는 프레임워크 설정과 렌더링을 위한 것이며, 타입 정의는@storybook/react에서 제공합니다.Likely an incorrect or invalid review comment.
1f7e109 to
b27e952
Compare
|
🚀 storybook url: https://689bfce92a7bd08f5aa1edbe-bhbzvqnqav.chromatic.com/ |
|
다른 컴포넌트들과 같이 형식을 맞췄습니다. 접근성 등이 미완성이나, mvp에서 dropdown이 들어가지 않기 때문에 큰 문제가 없으면 머지해도 좋을 것 같습니다. @Seong-Myeong @Goder-0 |
| onSelect(option); | ||
| close(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| onSelect(option); | |
| close(); | |
| onSelect(option); |
on close()
현재 close()가 부모와 자식에서 모두 호출되어 동일 상태 업데이트가 두 번 일어납니다. 닫기 책임은 부모에만 두고 자식에서는 선택 이벤트만 전달하는 게 좋습니다.
src/components/Dropdown/Dropdown.tsx
Outdated
| import React, { useState } from 'react'; | ||
|
|
||
| import { DropdownMenu } from './DropdownMenu'; | ||
| import { useDropdown } from './usdDropdown'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
파일명 오타로 보입니다.
| import { useDropdown } from './usdDropdown'; | |
| import { useDropdown } from './useDropdown'; |
| ]; | ||
|
|
||
| const meta = { | ||
| title: 'Components/Dropdown', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당부분 경로 수정해야합니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Bangdayeon 해당부분 진행되고 머지해주세요
관련 이슈
PR 설명
✅
useDropdown.tsdropdown의 상태를 관리isOpenbooleantoggle() => voidclose() => voidprops|type| 설명ref|React.RefObject<HTMLDivElement>| 드롭다운 DOM 요소 참조를 위한 ref. 외부 클릭 감지를 위해 사용✅
Dropdown.tsxoptionsDropdownOption[]defaultSelectedDropdownOptionoptions[0]onSelect(option: DropdownOption) => voidsize"sm" | "md" | "lg"