Skip to content

✨Feat: course-button 공통 컴포넌트 #54

Merged
skyblue1232 merged 4 commits intodevelopfrom
feat/#30/course-button
Oct 26, 2025
Merged

✨Feat: course-button 공통 컴포넌트 #54
skyblue1232 merged 4 commits intodevelopfrom
feat/#30/course-button

Conversation

@skyblue1232
Copy link
Copy Markdown
Contributor

@skyblue1232 skyblue1232 commented Oct 25, 2025

🔥 작업 내용

  • 코스 버튼 공통 컴포넌트

🤔 추후 작업 사항

  • ex) 소셜 로그인 연동 (카카오, 구글)
  • 맵(Course Setting)뷰 만들기

🔗 이슈

PR Point (To Reviewer)

  • ex) 로그인 입력 검증 로직 적절한지 확인 부탁드립니다.
  • CommonButton.tsx 에서 컴포넌트 생성 잘 됐는지 확인해주세요!
  • 캡쳐한 부분은 그냥 잘 되는지 테스트 하려고 띄워본 겁니다

📸 피그마 스크린샷 or 기능 GIF

(작업 내역 스크린샷)

image

Summary by CodeRabbit

  • 새로운 기능
    • 여행 코스 카테고리 선택 페이지가 추가되었습니다. 세로 레이아웃에서 9개 버튼으로 각 카테고리를 선택하고 토글할 수 있습니다.
    • 재사용 가능한 버튼 컴포넌트가 도입되어 활성/비활성 상태에 따른 시각적 구분과 일관된 스타일을 제공합니다.
    • 버튼 그룹은 반응형 레이아웃과 접근성을 고려해 구성되어 다양한 화면에서 사용성이 향상되었습니다.

@skyblue1232 skyblue1232 self-assigned this Oct 25, 2025
@skyblue1232 skyblue1232 added the feat 새로운 기능 추가 / 퍼블리싱 label Oct 25, 2025
@skyblue1232 skyblue1232 linked an issue Oct 25, 2025 that may be closed by this pull request
@vercel
Copy link
Copy Markdown

vercel bot commented Oct 25, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
af-fe Ready Ready Preview Comment Oct 26, 2025 5:23am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 25, 2025

Walkthrough

새로운 재사용 버튼 컴포넌트 CommonButton이 추가되고, 이를 사용하는 페이지 컴포넌트 CourseSettingPreview가 기본 익스포트로 추가되었습니다. 페이지는 9개 코스 버튼을 렌더링하며 로컬 상태 active: string | null로 단일 선택 토글을 구현합니다.

Changes

Cohort / File(s) 요약
공통 버튼 컴포넌트
src/shared/components/button/CommonButton.tsx
CommonButton 컴포넌트 추가. label 필수 프로퍼티와 선택적 variant/className을 받으며, class-variance-authority 기반 buttonStyledefault/active 변형을 적용하여 버튼 렌더링 및 props 포워딩
맵 페이지 컴포넌트
src/pages/map/index.tsx
기본 익스포트 CourseSettingPreview 추가. Tailwind 레이아웃으로 9개 CommonButton 렌더링, 로컬 상태 active로 클릭 시 해당 id 토글(같으면 null) 처리

Sequence Diagram(s)

sequenceDiagram
    participant User as 사용자
    participant Page as CourseSettingPreview
    participant Button as CommonButton

    User->>Page: 페이지 열람
    Page->>Button: 9개 버튼 렌더링 (label, variant, onClick)
    note right of Page #E8F8F5: 로컬 상태 active: null

    User->>Button: 버튼 클릭(id)
    Button->>Page: onClick -> toggleActive(id)
    alt id !== active
        Page->>Page: setActive(id)
        Page->>Button: 해당 버튼 variant="active"
    else id === active
        Page->>Page: setActive(null)
        Page->>Button: 모든 버튼 variant="default"
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • 주의할 파일/영역:
    • src/shared/components/button/CommonButton.tsx의 VariantProps 및 cva 타입 선언
    • CommonButton의 props 포워딩 및 className 합성(cn) 일관성
    • src/pages/map/index.tsx의 클릭 토글 로직(동일 id 클릭 시 null 처리)
    • 접근성(버튼 역할, 키보드 포커스) 및 Tailwind 반응형 클래스

Suggested reviewers

  • KongMezu
  • jjangminii

Poem

🐇 아홉 길 위에 버튼이 줄지어,
톡 하면 하나가 반짝이네.
또 톡 하면 조용히 사라져,
코스 하나 고르면 껑충뛰는 마음 —
작은 토끼가 축하해요 ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Linked Issues Check ❓ Inconclusive 연결 이슈 #30의 주요 요구 사항은 CommonButton 컴포넌트 생성 및 구현이었습니다. 풀 리퀘스트에서 CommonButton 컴포넌트가 src/shared/components/button/CommonButton.tsx에 생성되었고, 변형(variant) 및 상태 관리를 지원하는 기본 기능이 구현되었습니다. 하지만 이슈의 TODO 체크리스트에 명시된 "버튼 크기에 따른 분기 처리"는 이번 변경 사항에서 구현된 것으로 보이지 않으며, 요구 사항의 주요 특징인 "스크롤 가능"에 대한 명확한 구현 여부가 제공된 정보에서 확인되지 않습니다. CommonButton의 기본 구현은 완료되었으나, 이슈에 명시된 전체 요구 사항(특히 스크롤 가능 기능과 버튼 크기별 분기 처리)이 모두 충족되었는지 확인이 필요합니다. 제공된 코드 요약만으로는 이러한 세부 요구 사항의 구현 여부를 명확히 판단할 수 없으므로, 구현 코드의 자세한 검토가 필요합니다.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed 풀 리퀘스트 제목 "✨Feat: course-button 공통 컴포넌트"는 주요 변경 사항인 코스 버튼 공통 컴포넌트의 생성을 명확하게 설명하고 있습니다. 제목은 간결하고 구체적이어서 팀원들이 변경 내용을 쉽게 이해할 수 있습니다. 다만 이모지(✨)의 포함은 노이즈로 볼 수 있지만, 핵심 메시지는 명확하고 관련성이 높습니다.
Out of Scope Changes Check ✅ Passed 풀 리퀘스트의 주요 변경 사항은 CommonButton 컴포넌트의 생성으로, 이는 이슈 #30의 범위 내에 있습니다. 추가로 CourseSettingPreview 컴포넌트가 src/pages/map/index.tsx에 생성되었는데, 저자는 이를 CommonButton의 동작을 테스트하기 위한 임시 컴포넌트로 명시했습니다("캡쳐한 부분은 그냥 잘 되는지 테스트 하려고 띄워본 겁니다"). 이는 합리적인 범위 내의 테스트 코드이며, 주요 목표를 벗어나는 변경 사항이 아닙니다.
Description Check ✅ Passed 풀 리퀘스트 설명은 제공된 템플릿의 주요 섹션을 모두 포함하고 있습니다. 작업 내용, 이슈 링크(close #30), PR Point(검토자를 위한 요청 사항), 피그마 스크린샷이 포함되어 있으며, 추후 작업 사항도 명시되어 있습니다. 일부 템플릿 예시 텍스트("ex)" 접두사)가 남아있지만, 실제 작업 내용은 명확하게 작성되었으며 핵심 정보가 충분합니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#30/course-button

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f6cdf8 and ccf4ee0.

📒 Files selected for processing (1)
  • src/shared/components/button/CommonButton.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/shared/components/button/CommonButton.tsx
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy

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

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@github-actions github-actions bot added the comment 필요한 주석 추가 및 변경 label Oct 25, 2025
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 193cbc6 and 6db377e.

📒 Files selected for processing (2)
  • src/pages/map/index.tsx (1 hunks)
  • src/shared/components/button/CommonButton.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/shared/components/button/CommonButton.tsx (1)
src/shared/lib/utils.ts (1)
  • cn (71-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (3)
src/shared/components/button/CommonButton.tsx (1)

10-28: 버튼 스타일 정의 잘 구현되었습니다

cva를 사용한 variant 기반 스타일 정의가 깔끔하고 확장 가능하게 구현되었습니다. defaultactive variant가 명확하게 구분되어 있습니다.

src/pages/map/index.tsx (2)

4-17: 상태 관리와 버튼 구성이 잘 구현되었습니다

useState를 활용한 active 상태 관리가 적절하고, 버튼 배열의 구조(id, label)가 명확합니다. 한글 레이블도 사용자 친화적입니다.


24-31: 토글 로직이 정확하게 구현되었습니다

Line 29의 onClick 핸들러에서 이미 활성화된 버튼을 다시 클릭하면 null로 설정하고, 그렇지 않으면 해당 id로 설정하는 토글 로직이 정확합니다. variant prop도 상태에 따라 올바르게 전환됩니다.

Copy link
Copy Markdown
Contributor

@KongMezu KongMezu left a comment

Choose a reason for hiding this comment

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

새벽까지 수고하셨습니다! 간단한 리뷰 달아드렸으니 수정해보심 좋을거 같습니다!


const buttonStyle = cva(
`
text-center rounded-[2rem] text-title-md tracking-[0.015em]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Tracking 부분도
다 폰트 유틸리티로 넣어놔서 다시 안넣어도 될 거 같습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

넵 수정했습니다!!

Copy link
Copy Markdown
Contributor

@jjangminii jjangminii left a comment

Choose a reason for hiding this comment

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

버튼 이름 오타만 해결해주시고 코멘트 하나 남겼는데 어떻게 생각하시는지 궁금합니다-!

Comment on lines +4 to +8
interface CummonButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonStyle> {
label: string;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

image

이게 나중에 그룹으로 묶여서 radio 버튼처럼 작동할것 같은데 따로 그룹 속성은 없어도 괜찮을까요? 따로 Optional로 추가해도 좋을 것 같아요

Copy link
Copy Markdown
Contributor

@KongMezu KongMezu Oct 26, 2025

Choose a reason for hiding this comment

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

Optional로 확장성을 고려하는 건 좋은 방법인 것 같아요!
다만, 저는 CommonButton에서 버튼 자체는 표시나 클릭 이벤트 역할에 집중하고,
이지선다 정도가 아니라 옵션이 많다보니, 선택 상태 관리 같은 로직은 별도의 그룹 컴포넌트에서 담당하는 게
역할 분리가 더 명확하고 유지보수 면에서도 좋을 것 같습니다..!

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

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 (2)
src/pages/map/index.tsx (2)

7-17: 버튼 데이터 구조화 제안

현재 버튼 데이터가 컴포넌트 내부에 하드코딩되어 있습니다. 재사용성과 유지보수성을 위해 다음을 고려해보세요:

  1. 상수 파일로 분리 (예: src/constants/courseCategories.ts)
  2. 명시적 TypeScript 인터페이스 정의

예시:

// src/constants/courseCategories.ts
export interface CourseCategory {
  id: string;
  label: string;
}

export const COURSE_CATEGORIES: CourseCategory[] = [
  { id: 'family', label: '가족여행' },
  { id: 'friends', label: '우정여행' },
  // ...
];
+import { COURSE_CATEGORIES } from '@/constants/courseCategories';
 import CommonButton from '@/shared/components/button/CommonButton';
 import { useState } from 'react';

 export default function CourseSettingPreview() {
   const [active, setActive] = useState<string | null>(null);

-  const buttons = [
-    { id: 'family', label: '가족여행' },
-    { id: 'friends', label: '우정여행' },
-    ...
-  ];

   return (
     // ...
     <div className="flex flex-wrap justify-center gap-4 max-w-[400px]">  
-      {buttons.map(({ id, label }) => (
+      {COURSE_CATEGORIES.map(({ id, label }) => (
         <CommonButton

20-20: 임시 주석 제거 필요

머지 전에 임시 주석을 제거해주세요.

-    // 스타일은 다 수정할 거에요 버튼만 봐주세요~  // CommonButton.tsx 저것만 확인해주세요
     <div className="flex flex-col items-center gap-6 py-10">
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6db377e and 1635186.

📒 Files selected for processing (1)
  • src/pages/map/index.tsx (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (3)
src/pages/map/index.tsx (3)

1-1: 이전 리뷰의 오타가 수정되었습니다!

이전 리뷰에서 지적된 CummonButtonCommonButton 오타가 올바르게 수정되었습니다.


4-5: 컴포넌트 역할 및 명명 확인 필요

PR 목적과 이슈 #30에서는 "CourseButton" 공통 컴포넌트 생성을 언급하고 있으나, 이 파일의 컴포넌트명은 CourseSettingPreview입니다.

이 파일은 CommonButton 컴포넌트를 사용하는 프리뷰/데모 페이지로 보이며, 실제 공통 컴포넌트는 src/shared/components/button/CommonButton.tsx에 있는 것으로 추정됩니다.

PR 설명에 이 구조를 명확히 하시면 리뷰어가 이해하기 쉬울 것 같습니다.


25-30: 컴포넌트 사용 로직이 올바르게 수정되었습니다

CommonButton 컴포넌트 사용이 올바르게 수정되었고, 토글 로직도 적절합니다. 클릭 시 활성 상태를 토글하는 동작이 정확하게 구현되었습니다.

// 스타일은 다 수정할 거에요 버튼만 봐주세요~ // CommonButton.tsx 저것만 확인해주세요
<div className="flex flex-col items-center gap-6 py-10">
<h1 className="text-title-lg text-gray-700 mb-4">코스 버튼 임시 화면</h1>
<div className="flex flex-wrap justify-center gap-4 max-w-[400px]">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

화면 전체 너비 요구사항과 불일치

이슈 #30의 요구사항에는 "CourseButton은 화면에 꽉 차게 표시되되 스크롤 가능하도록 동작해야 함"이라고 명시되어 있으나, 현재 max-w-[400px]로 제한되어 있습니다.

요구사항에 맞게 전체 너비를 사용하도록 수정이 필요합니다.

-      <div className="flex flex-wrap justify-center gap-4 max-w-[400px]">  
+      <div className="flex flex-wrap justify-center gap-4 w-full px-4">  

또는 화면을 꽉 채우고 스크롤이 필요한 경우:

-      <div className="flex flex-wrap justify-center gap-4 max-w-[400px]">  
+      <div className="flex flex-wrap justify-center gap-4 w-full max-h-screen overflow-y-auto px-4">  
📝 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
<div className="flex flex-wrap justify-center gap-4 max-w-[400px]">
<div className="flex flex-wrap justify-center gap-4 w-full px-4">
🤖 Prompt for AI Agents
In src/pages/map/index.tsx around line 23, the container currently constrains
CourseButton width with max-w-[400px], which violates issue #30 requiring
CourseButton to fill the viewport width and be scrollable; remove the max-w
restriction and make the container use full width (e.g., w-full) and enable
scrolling as needed (horizontal or vertical) by adding an appropriate overflow
utility (e.g., overflow-auto or overflow-x-auto) so the buttons stretch to the
screen width while still allowing scroll when content exceeds viewport.

Copy link
Copy Markdown
Contributor

@KongMezu KongMezu left a comment

Choose a reason for hiding this comment

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

추가 코멘트 남겨뒀습니다!

Comment on lines +4 to +8
interface CummonButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonStyle> {
label: string;
}
Copy link
Copy Markdown
Contributor

@KongMezu KongMezu Oct 26, 2025

Choose a reason for hiding this comment

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

Optional로 확장성을 고려하는 건 좋은 방법인 것 같아요!
다만, 저는 CommonButton에서 버튼 자체는 표시나 클릭 이벤트 역할에 집중하고,
이지선다 정도가 아니라 옵션이 많다보니, 선택 상태 관리 같은 로직은 별도의 그룹 컴포넌트에서 담당하는 게
역할 분리가 더 명확하고 유지보수 면에서도 좋을 것 같습니다..!

Copy link
Copy Markdown
Contributor

@KongMezu KongMezu left a comment

Choose a reason for hiding this comment

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

피드백 반영 확인했습니다! 수고하셨습니다!

@skyblue1232 skyblue1232 merged commit 07d6602 into develop Oct 26, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comment 필요한 주석 추가 및 변경 feat 새로운 기능 추가 / 퍼블리싱

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 공통 컴포넌트 - CourseButton

3 participants