[Feat] 어드민 공통 컴포넌트 제작#6
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✅ Files skipped from review due to trivial changes (1)
📝 WalkthroughWalkthrough공통 어드민 UI 컴포넌트와 재-내보내기 구조를 추가했고, 전역 스타일과 class merge 설정을 정리했습니다. App은 렌더링을 중단하도록 바뀌었고, 아이콘 빌드 스크립트는 자동 JSX 런타임과 외부 Prettier 설정을 사용합니다. Changes공통 컴포넌트 및 스타일 기반
Sequence Diagram(s)sequenceDiagram
participant Sidebar
participant SegmentedControl
participant PageHeader
Sidebar->>Sidebar: onNavigate(item.key)
SegmentedControl->>SegmentedControl: onValueChange(item.value)
PageHeader->>PageHeader: onAction()
관련 이슈: 제안 라벨: enhancement, frontend, components 제안 리뷰어: 관련 파일 작업 이력 또는 CODEOWNERS 확인 필요 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
CI 결과
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
src/components/common/Logo.tsx (1)
24-27: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win로고 전체에 접근 가능한 이름 없음
HeaderDesktopLogo와AdminWordmark모두aria-hidden="true"로 숨겨져 있어 스크린 리더 사용자에게는 로고가 전혀 노출되지 않습니다. 컨테이너div에role="img"와aria-label(예: "KUSITMS 관리자")을 추가하거나, 실제 링크/버튼으로 감싸는 경우 그쪽에 접근 가능한 이름을 부여하는 것이 좋습니다.As per path instructions, "**/*.{ts,tsx}: 타입 안정성, React 상태/효과 사용, 접근성, 테스트 필요성을 검토한다."
♿ 접근성 개선 제안
return ( - <div className={cn('inline-flex items-center', className)}> + <div className={cn('inline-flex items-center', className)} role="img" aria-label="KUSITMS 관리자 로고"> <HeaderDesktopLogo className={markSizeClassName[size]} aria-hidden="true" /> <AdminWordmark className={wordmarkSizeClassName[size]} aria-hidden="true" /> </div> )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/Logo.tsx` around lines 24 - 27, The logo wrapper in Logo should expose an accessible name because both HeaderDesktopLogo and AdminWordmark are hidden from screen readers. Update the outer div in the Logo component to provide an accessible role and label, or place the logo inside a link/button and give that element the name; use the existing className/size handling to keep the visual layout unchanged.Source: Path instructions
src/components/common/SegmentedControl.tsx (2)
27-44: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win버튼 요소도 라이브러리 컴포넌트 우선 사용 가이드 대상
여기도 순수
<button>을 사용 중입니다. PageHeader.tsx와 동일한 가이드라인 위반 소지가 있습니다.As per coding guidelines, "Use
@kusitms.com/uicomponents first, thenshadcn/ui, then Base UI when selecting or importing UI components in the KUSITMS admin panel."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/SegmentedControl.tsx` around lines 27 - 44, The SegmentedControl tab trigger is using a raw button element, which should be replaced per the UI component priority guideline. Update the tab item rendering in SegmentedControl to use the appropriate component from `@kusitms.com/ui` first (or the next allowed library option if no direct equivalent exists), and keep the same role, aria-selected, click handling, and styling behavior currently applied to the button.Source: Coding guidelines
22-46: 🎯 Functional Correctness | 🔵 Trivial | ⚖️ Poor tradeoff탭 패턴 키보드 내비게이션 누락
role="tablist"/role="tab"마크업은 있으나 화살표 키로 탭 간 이동하는 로직과 rovingtabIndex관리가 없습니다. WAI-ARIA Tabs 패턴을 완전히 따르려면 키보드 내비게이션이 필요합니다.As per path instructions, "**/*.{ts,tsx}: 타입 안정성, React 상태/효과 사용, 접근성, 테스트 필요성을 검토한다."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/SegmentedControl.tsx` around lines 22 - 46, The SegmentedControl tab UI uses role="tablist"/role="tab" but is missing WAI-ARIA tabs keyboard support and roving focus management. Update SegmentedControl to handle arrow-key navigation between items, manage focus with tabIndex so only the active (or focused) tab is tabbable, and keep the selected state in sync via value/onValueChange. Use the existing items map, isActive logic, and onValueChange handler to wire the behavior without changing the public API.Source: Path instructions
src/components/common/Sidebar.tsx (2)
71-110: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win신규 공통 컴포넌트 테스트 부재
Logo,PageHeader,SegmentedControl,Sidebar모두 활성 상태 분기, 콜백 배선 등 검증할 로직이 있음에도 테스트가 없습니다.Sidebar의activeKey분기 로직만이라도 렌더링/상호작용 테스트를 추가하는 것을 권장합니다.As per path instructions, "**/*.{ts,tsx}: 타입 안정성, React 상태/효과 사용, 접근성, 테스트 필요성을 검토한다."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/Sidebar.tsx` around lines 71 - 110, `Sidebar`에는 `activeKey`에 따른 활성 상태 렌더링과 `onNavigate`/`onLogout` 콜백 연결을 검증하는 테스트가 없어 회귀를 잡기 어렵습니다. `Sidebar`와 `SidebarNavButton`의 상호작용을 대상으로, 주어진 `activeKey`에 맞는 항목이 활성으로 표시되는지와 클릭 시 `onNavigate(item.key)` 및 로그아웃 버튼 클릭 시 `onLogout`이 호출되는지 렌더링/이벤트 테스트를 추가하세요.Source: Path instructions
47-62: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win네이티브
<button>반복 사용
SidebarNavButton과 로그아웃 버튼 모두 순수 HTML<button>입니다. PageHeader/SegmentedControl과 같은 가이드라인 위반이 반복되므로 공통@kusitms.com/uiButton 컴포넌트가 있는지 확인 후 재사용을 검토해 주세요.As per coding guidelines, "Use
@kusitms.com/uicomponents first, thenshadcn/ui, then Base UI when selecting or importing UI components in the KUSITMS admin panel."Also applies to: 99-106
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/Sidebar.tsx` around lines 47 - 62, The sidebar currently uses native HTML button elements for SidebarNavButton and the logout action, which violates the UI component selection guideline. Update the Sidebar component to use the shared Button component from `@kusitms.com/ui` wherever possible, keeping the same behavior, active styling, icons, and click handlers. Check the SidebarNavButton helper and the logout button rendering path, and only fall back to lower-level primitives if the shared Button cannot support the required variants.Source: Coding guidelines
src/components/common/PageHeader.tsx (1)
25-32: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win네이티브
<button>대신 라이브러리 컴포넌트 사용 검토액션 버튼이 순수 HTML
<button>으로 구현되어 있습니다.@kusitms.com/ui(우선), 없으면shadcn/ui, 그다음 Base UI 순으로 버튼 컴포넌트를 사용하는 것이 가이드라인에 부합합니다. 디자인 시스템에 해당 스타일의 버튼이 없다면 무시해도 됩니다.As per coding guidelines, "Use
@kusitms.com/uicomponents first, thenshadcn/ui, then Base UI when selecting or importing UI components in the KUSITMS admin panel."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/common/PageHeader.tsx` around lines 25 - 32, The action button in PageHeader is using a native HTML button instead of the preferred design-system component. Update the button inside PageHeader to use the appropriate UI library component, checking `@kusitms.com/ui` first, then shadcn/ui, then Base UI, and preserve the existing props and styling/behavior. If no matching design-system button exists for this style, leave it as-is.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/components/common/PageHeader.tsx`:
- Around line 14-19: The PageHeader wrapper is using a hardcoded RGBA border
color instead of a design token. Update the className in PageHeader to replace
border-[rgba(112,115,124,0.16)] with the appropriate border token from
`@kusitms.com/tokens`, keeping the existing layout classes and cn usage intact.
In `@src/components/common/Sidebar.tsx`:
- Around line 74-81: The Sidebar component is using the same hardcoded border
color value twice instead of design tokens. Update the border classes in Sidebar
so they use the shared `@kusitms.com/tokens` color token rather than
rgba(112,115,124,0.16), and if this value is reused elsewhere, extract it into a
common token-based utility/class to keep Sidebar and related components
consistent.
---
Nitpick comments:
In `@src/components/common/Logo.tsx`:
- Around line 24-27: The logo wrapper in Logo should expose an accessible name
because both HeaderDesktopLogo and AdminWordmark are hidden from screen readers.
Update the outer div in the Logo component to provide an accessible role and
label, or place the logo inside a link/button and give that element the name;
use the existing className/size handling to keep the visual layout unchanged.
In `@src/components/common/PageHeader.tsx`:
- Around line 25-32: The action button in PageHeader is using a native HTML
button instead of the preferred design-system component. Update the button
inside PageHeader to use the appropriate UI library component, checking
`@kusitms.com/ui` first, then shadcn/ui, then Base UI, and preserve the existing
props and styling/behavior. If no matching design-system button exists for this
style, leave it as-is.
In `@src/components/common/SegmentedControl.tsx`:
- Around line 27-44: The SegmentedControl tab trigger is using a raw button
element, which should be replaced per the UI component priority guideline.
Update the tab item rendering in SegmentedControl to use the appropriate
component from `@kusitms.com/ui` first (or the next allowed library option if no
direct equivalent exists), and keep the same role, aria-selected, click
handling, and styling behavior currently applied to the button.
- Around line 22-46: The SegmentedControl tab UI uses role="tablist"/role="tab"
but is missing WAI-ARIA tabs keyboard support and roving focus management.
Update SegmentedControl to handle arrow-key navigation between items, manage
focus with tabIndex so only the active (or focused) tab is tabbable, and keep
the selected state in sync via value/onValueChange. Use the existing items map,
isActive logic, and onValueChange handler to wire the behavior without changing
the public API.
In `@src/components/common/Sidebar.tsx`:
- Around line 71-110: `Sidebar`에는 `activeKey`에 따른 활성 상태 렌더링과
`onNavigate`/`onLogout` 콜백 연결을 검증하는 테스트가 없어 회귀를 잡기 어렵습니다. `Sidebar`와
`SidebarNavButton`의 상호작용을 대상으로, 주어진 `activeKey`에 맞는 항목이 활성으로 표시되는지와 클릭 시
`onNavigate(item.key)` 및 로그아웃 버튼 클릭 시 `onLogout`이 호출되는지 렌더링/이벤트 테스트를 추가하세요.
- Around line 47-62: The sidebar currently uses native HTML button elements for
SidebarNavButton and the logout action, which violates the UI component
selection guideline. Update the Sidebar component to use the shared Button
component from `@kusitms.com/ui` wherever possible, keeping the same behavior,
active styling, icons, and click handlers. Check the SidebarNavButton helper and
the logout button rendering path, and only fall back to lower-level primitives
if the shared Button cannot support the required variants.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 41eb928b-2002-4c7a-80aa-a7b7857261b5
⛔ Files ignored due to path filters (37)
public/icons.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/hero.pngis excluded by!**/*.png,!**/*.pngsrc/assets/icons/generated/AddIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/AdminWordmark.tsxis excluded by!**/generated/**src/assets/icons/generated/BlogIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/CancelIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/CheckIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/ChevronDownIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/CompanyIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/DashboardIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/DeleteIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/ErrorIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/IntroductionIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/LogoutIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/MeetupIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/MentoringIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/ReviewIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/UploadIcon.tsxis excluded by!**/generated/**src/assets/icons/generated/index.tsis excluded by!**/generated/**src/assets/icons/svg-preserve/admin-wordmark.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/add.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/blog.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/cancel.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/check.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/chevron-down.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/company.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/dashboard.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/delete.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/error.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/introduction.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/logout.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/meetup.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/mentoring.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/review.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/icons/svg/upload.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/react.svgis excluded by!**/*.svg,!**/*.svgsrc/assets/vite.svgis excluded by!**/*.svg,!**/*.svg
📒 Files selected for processing (12)
.husky/pre-commitscripts/build-icons.tssrc/App.csssrc/App.tsxsrc/components/common/Logo.tsxsrc/components/common/PageHeader.tsxsrc/components/common/SegmentedControl.tsxsrc/components/common/Sidebar.tsxsrc/components/common/index.tssrc/components/index.tssrc/index.csssrc/lib/utils.ts
💤 Files with no reviewable changes (1)
- src/App.css
CI 결과
|
CI 결과
|
KyeongJooni
left a comment
There was a problem hiding this comment.
고생하셨습니다!! 코멘트 남겼으니 확인부탁드립니다 👍
There was a problem hiding this comment.
사이드바, 세그먼트 컨트롤, 페이지헤더 분기처리 유닛 테스트 작성 필요할 것 같습니다!!
| <button | ||
| type="button" | ||
| onClick={onAction} | ||
| className="bg-brand-primary text-label-14sb text-fill-normal h-10 rounded-[8px] px-4 py-2 transition-colors hover:brightness-95" | ||
| > |
There was a problem hiding this comment.
디자인 시스템에 버튼이 있는것으로 알고 있는데 디자인 시스템에서 import 해서 사용하는게 어떨까요??
There was a problem hiding this comment.
디자인 시스템에 있는 버튼은 어드민 페이지에서 사용되는 버튼 스펙과 불일치하여 커스텀 했습니다!
CI 결과
|
#️⃣연관된 이슈
🚧 Work in Progress
📌 주요 변경사항
📝작업 내용
Logo(s/l 사이즈),Sidebar(메뉴 7종+로그아웃),SegmentedControl(active/default),PageHeader(제목+액션 버튼) — 라우팅/API 호출과 분리된 콜백 prop 기반 설계pnpm icons:build로 생성한 아이콘 컴포넌트jsxRuntime미지정으로 불필요한Reactimport가 생성돼 빌드가 깨지던 문제cn()유틸리티 수정: tailwind-merge가 커스텀 타이포그래피 클래스를 색상 클래스와 같은 그룹으로 오인해 삭제하던 충돌 해결h1규칙 충돌 해결tsc -b/pnpm lint/pnpm build/icons:check/gen:index:check통과📸 스크린샷 (선택)
💬리뷰 요구사항(선택)
App.tsx는 아직 실제 레이아웃에 조립하지 않은 빈 상태 — 페이지 조립은 별도 작업으로 분리Summary by CodeRabbit