Skip to content

[Feat/#57] feat(web): migrate Dropdown#68

Merged
seungdeok merged 2 commits into
mainfrom
feat/#57
Sep 24, 2025
Merged

[Feat/#57] feat(web): migrate Dropdown#68
seungdeok merged 2 commits into
mainfrom
feat/#57

Conversation

@seungdeok

@seungdeok seungdeok commented Sep 23, 2025

Copy link
Copy Markdown
Member

📝 PR 유형

  • 🚀 feature 기능 추가
  • 🐞 버그 발생
  • 🔨 리팩토링
  • 📋 문서작성
  • 🌍 빌드 설정 및 문제
  • ETC

📝 PR 설명

Dropdown 컴포넌트 마이그레이션 작업입니다.

관련된 이슈 넘버

close #57

✅ 작업 목록

  • Dropdown 컴포넌트 마이그레이션(pure css -> pandacss)
  • Dropdown storybook

MR하기 전에 확인해주세요

  • local code lint 검사를 진행하셨나요?
  • loca ci test를 진행하셨나요?

📚 논의사항

📚 ETC

Summary by CodeRabbit

  • New Features
    • 새 드롭다운 컴포넌트 추가: 라벨 및 항목 목록, 선택 상태 표시, 열림/닫힘 제어, 키보드·마우스 상호작용, 비활성 항목 처리, 포털 기반 팝업, 외부 콜백 지원.
  • Documentation
    • 드롭다운용 Storybook 스토리 추가: 기본 예제, 라벨/항목 컨트롤, 중앙 정렬 미리보기 및 자동 문서화 설정.
  • Chores
    • UI용 Radix UI 드롭다운 종속성 추가.

@seungdeok seungdeok requested a review from widse September 23, 2025 14:24
@seungdeok seungdeok self-assigned this Sep 23, 2025
@coderabbitai

coderabbitai Bot commented Sep 23, 2025

Copy link
Copy Markdown

Walkthrough

Radix UI의 DropdownMenu가 의존성으로 추가되었고, 이를 사용하는 신규 Dropdown 컴포넌트와 타입 정의(DropdownProps), 그리고 Storybook 스토리(Base)가 프로젝트에 추가되었습니다. 컴포넌트는 열림 상태와 선택 상태를 내부 관리하고 선택/열림 변경 콜백을 노출합니다.

Changes

Cohort / File(s) Summary
Dependency update
apps/web/package.json
@radix-ui/react-dropdown-menu@^2.1.16 의존성 추가
Dropdown component & types
apps/web/src/shared/components/Dropdown/Dropdown.tsx, apps/web/src/shared/components/Dropdown/Dropdown.type.ts
신규 Dropdown 컴포넌트 추가 (내부 open/selected 상태, onOpenChange/onClick 콜백), DropdownProps 타입 정의
Storybook story
apps/web/src/shared/components/Dropdown/Dropdown.stories.tsx
Dropdown의 Storybook 기본 스토리(meta, Base) 추가 (args, render 포함)

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor U as 사용자
    participant T as Dropdown (Trigger)
    participant R as Radix DropdownMenu
    participant C as 컴포넌트 콜백 (onOpenChange/onClick)

    U->>T: 클릭/토글
    T->>R: open 요청
    R-->>T: open 상태 변경 이벤트
    T-->>C: onOpenChange(open)?

    U->>R: 항목 선택
    R->>T: 선택 이벤트(value)
    T->>T: 선택값 업데이트
    T-->>C: onClick({label, value})?

    note over R,T: ESC 또는 외부 클릭 시 닫힘 처리
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–30 minutes

Suggested reviewers

  • widse

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed 제목 '[Feat/#57] feat(web): migrate Dropdown'은 변경의 핵심인 Dropdown 컴포넌트 마이그레이션을 명확히 나타내며 관련 이슈 번호를 포함해 한눈에 목적을 파악할 수 있습니다. 다만 접두어에 'Feat'와 'feat'가 중복되어 형식적 일관성이 약간 떨어지지만 내용 자체는 적절합니다.
Linked Issues Check ✅ Passed 링크된 이슈 #57의 목표가 DropDown 컴포넌트 이관인 점을 고려할 때 PR은 컴포넌트 파일, 타입 정의, Storybook 스토리 및 Radix 의존성 추가를 포함하여 해당 목표를 충족하며 이슈 닫기(close #57) 표기도 포함되어 있어 코딩 관련 요구사항을 잘 만족합니다. 추가적인 구현 요구사항이나 미이행 항목은 발견되지 않습니다.
Out of Scope Changes Check ✅ Passed 변경 내역은 Dropdown 마이그레이션과 직접 관련된 파일들과 의존성 추가(@radix-ui/react-dropdown-menu)에 국한되어 있으며 리포지터리의 다른 기능이나 불필요한 영역을 건드리는 범위 밖 변경은 확인되지 않습니다. 따라서 범위 외 변경은 없습니다.
Description Check ✅ Passed PR 설명은 저장소 템플릿 구조를 따르고 있으며 PR 유형, 간단한 설명, 관련 이슈 번호, 작업 목록 및 사전 확인 항목이 적절히 기재되어 있어 대부분의 필수 정보가 포함되어 있습니다. 논의사항과 ETC 섹션은 비어 있지만 필수적이지 않으므로 설명은 전반적으로 충분합니다.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#57

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown

📚 Storybook is ready for review!
🔗 Preview: https://68ceb72871701a8b3beb1d8f-yfpzksawxu.chromatic.com/

@github-actions

Copy link
Copy Markdown

📚 Storybook is ready for review!
🔗 Preview: https://68ceb72871701a8b3beb1d8f-pnlepujkml.chromatic.com/

@github-actions

Copy link
Copy Markdown

📚 Storybook is ready for review!
🔗 Preview: https://68ceb72871701a8b3beb1d8f-jnpdnxlmbh.chromatic.com/

@github-actions

Copy link
Copy Markdown

📚 Storybook is ready for review!
🔗 Preview: https://68ceb72871701a8b3beb1d8f-zroafmtska.chromatic.com/

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (6)
apps/web/src/shared/components/Dropdown/Dropdown.type.ts (2)

7-7: 정의된 className prop가 컴포넌트에서 사용되지 않음

Dropdown.tsx에서 className을 받아 적용하지 않습니다. API 표면에 존재하는 prop는 실제로 사용되도록 배선해 주세요.


9-9: 이벤트 명칭 정합성: onClick → onSelect 권장

Radix DropdownMenu.Item은 선택 이벤트로 onSelect를 권장합니다. 외부 콜백 명도 onSelect(또는 onValueChange)로 맞추면 의미가 명확해집니다.

적용 시 Dropdown.tsx의 내부 핸들러/바인딩도 함께 업데이트해야 합니다.

apps/web/src/shared/components/Dropdown/Dropdown.tsx (2)

8-10: className prop 수용 및 루트 트리거에 전달

DropdownProps에 className이 정의되어 있으나 미사용입니다. 트리거 버튼에 합쳐 적용해 커스터마이징 포인트를 노출하세요.

다음과 같이 전달을 제안합니다:

-export const Dropdown = ({ label, items, onOpenChange, onClick }: DropdownProps) => {
+export const Dropdown = ({ label, items, className, onOpenChange, onClick }: DropdownProps) => {
   const [isOpen, setIsOpen] = useState(false);

그리고 트리거 버튼 쪽:

-        <button
+        <button
           type="button"
-          className={css({ ... })}
+          className={[css({ /* 기존 스타일 */ }), className].filter(Boolean).join(" ")}

86-116: 렌더 루프 내부 css(...) 호출 최소화

itemBaseClass는 정적 스타일입니다. 루프 외부로 hoist하면 재연산을 줄일 수 있습니다. 선택 상태용 itemSelectedClass만 조건부로 합치면 됩니다.

apps/web/src/shared/components/Dropdown/Dropdown.stories.tsx (2)

21-49: items 컨트롤 타입 부적합: select 대신 object 권장

배열+객체 구조는 select보다 object 컨트롤이 적합합니다. 현재 options에 단일 옵션 배열만 제공되어 컨트롤 이점이 거의 없습니다.

다음과 같이 조정해 보세요:

-    items: {
-      control: "select",
-      options: [ [ /* 샘플 아이템들 */ ] ],
-      description: "dropdown의 아이템을 지정",
-    },
+    items: {
+      control: "object",
+      description: "dropdown의 아이템을 지정",
+    },

또한 onOpenChange, onClick(또는 onSelect)에는 action을 연결하면 데모 시 유용합니다:

+    onOpenChange: { action: "onOpenChange" },
+    onClick: { action: "onClick" }, // onSelect로 이름 변경 시 같이 수정

81-82: render 타이핑 단순화 가능

StoryObj 타입 추론이 되므로 render의 매개변수에 별도 DropdownProps 주석은 생략해도 됩니다. 유지해도 무방합니다.

-  render: (args: DropdownProps) => <Dropdown {...args} />,
+  render: (args) => <Dropdown {...args} />,
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7ee564d and 61c5bf5.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • apps/web/package.json (1 hunks)
  • apps/web/src/shared/components/Dropdown/Dropdown.stories.tsx (1 hunks)
  • apps/web/src/shared/components/Dropdown/Dropdown.tsx (1 hunks)
  • apps/web/src/shared/components/Dropdown/Dropdown.type.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
apps/web/src/shared/components/Dropdown/Dropdown.stories.tsx (2)
apps/web/src/shared/components/Dropdown/Dropdown.tsx (1)
  • Dropdown (8-137)
apps/web/src/shared/components/Dropdown/Dropdown.type.ts (1)
  • DropdownProps (1-10)
apps/web/src/shared/components/Dropdown/Dropdown.tsx (1)
apps/web/src/shared/components/Dropdown/Dropdown.type.ts (1)
  • DropdownProps (1-10)
🔇 Additional comments (1)
apps/web/package.json (1)

21-21: 확인: @radix-ui/react-dropdown-menu@2.1.16 및 다른 Radix 패키지의 peerDependencies가 React 19를 허용합니다
npm view 결과 react/react-dom에 ^19 포함 — React 19/Next 15과 호환되므로 별도 수정 불필요.

Comment on lines +26 to +27
<DropdownMenu.Trigger asChild className={css({})}>
<div

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Trigger 자식 요소는 button 사용 권장 (접근성/키보드 상호작용 개선)

asChild를 쓰는 경우 Trigger의 자식은 button 요소 사용이 권장됩니다. 현재 div를 사용하고 있어 접근성(역할/키보드) 면에서 불리할 수 있습니다.

다음과 같이 수정을 제안합니다:

-      <DropdownMenu.Trigger asChild className={css({})}>
-        <div
+      <DropdownMenu.Trigger asChild>
+        <button
+          type="button"
           className={css({
             border: "1px solid rgba(0, 0, 0, 0.2)",
             padding: "11px 20px",
             minWidth: "170px",
             display: "flex",
             flexDirection: "row",
             alignItems: "center",
             justifyContent: "space-between",
             gap: "10px",
           })}
           style={{ borderRadius: isOpen ? "4px 4px 0 0" : "4px" }}
         >
           ...
-        </div>
+        </button>
       </DropdownMenu.Trigger>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<DropdownMenu.Trigger asChild className={css({})}>
<div
<DropdownMenu.Trigger asChild>
<button
type="button"
className={css({
border: "1px solid rgba(0, 0, 0, 0.2)",
padding: "11px 20px",
minWidth: "170px",
display: "flex",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
gap: "10px",
})}
style={{ borderRadius: isOpen ? "4px 4px 0 0" : "4px" }}
>
...
</button>
</DropdownMenu.Trigger>
🤖 Prompt for AI Agents
In apps/web/src/shared/components/Dropdown/Dropdown.tsx around lines 26-27, the
DropdownMenu.Trigger is using asChild with a div child which harms accessibility
and keyboard interaction; replace the div with a semantic button element
(type="button") that forwards props and retains existing styling/classes, ensure
any aria attributes/handlers are passed through, and keep visual/layout styles
identical so keyboard focus and assistive tech work correctly.

Comment thread apps/web/src/shared/components/Dropdown/Dropdown.tsx
@seungdeok seungdeok merged commit 656a4eb into main Sep 24, 2025
4 checks passed
@seungdeok seungdeok deleted the feat/#57 branch September 24, 2025 14:24
@coderabbitai coderabbitai Bot mentioned this pull request Oct 6, 2025
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[DropDown] fireeren-component to Time-align Code 이관

2 participants