-
Notifications
You must be signed in to change notification settings - Fork 1
[DESIGN] 종소리 설정에 아코디언 UI 적용 #359
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
Conversation
WalkthroughNotificationBadge 컴포넌트와 Storybook 스토리가 추가되었고, TimerCreationContent의 BELL 섹션이 배지와 아코디언(확장/축소) 패널, 벨 추가/삭제 로직을 포함하도록 재구성되었으며, Tailwind 설정에 색상 토큰 Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as 사용자
participant T as TimerCreationContent
participant S as 로컬상태
participant B as NotificationBadge
U->>T: 벨 확장 버튼 클릭
T->>S: isBellExpanded 토글
T->>T: 재렌더
T->>B: props.count = bells.length
B-->>T: 배지 렌더(0이면 숨김, >99면 "99+")
alt 확장된 상태
U->>T: 벨 입력 후 Add 클릭
T->>S: bells[]에 항목 추가
T->>T: 리스트 및 배지 재렌더
U->>T: 벨 항목 Delete 클릭
T->>S: bells[]에서 항목 제거
T->>T: 리스트 및 배지 재렌더
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 1
🧹 Nitpick comments (9)
src/components/NotificationBadge/NotificationBadge.tsx (3)
12-17: count 방어적 처리(음수/NaN 클램프) 권장.외부에서 음수나 NaN이 유입될 경우 표시가 비정상일 수 있습니다. 0으로 클램프하고, 99+ 로직은 클램프된 값 기준으로 수행하는 편이 안전합니다.
적용 예시:
- if (count === 0) { + const safeCount = Number.isFinite(count) ? Math.max(0, count) : 0; + if (safeCount === 0) { return null; } - const displayCount = count > 99 ? '99+' : count; + const displayCount = safeCount > 99 ? '99+' : safeCount;
19-26: 배지 접근성(a11y) 속성 추가 제안.보조기기가 읽을 수 있도록 role/aria를 부여하면 좋습니다.
적용 예시:
return ( <span className={clsx( 'inline-flex h-4 min-w-[16px] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold leading-none text-white', className, )} + role="status" + aria-live="polite" + aria-label={`알림 ${displayCount}개`} > {displayCount} </span> );
21-23: 디자인 토큰 사용 일관성.배경색을 tailwind 기본(red-500) 대신 프로젝트 토큰(예: semantic.error)로 통일하면 테마 변경에 유리합니다.
적용 예시:
- '... bg-red-500 ...' + '... bg-semantic-error ...'src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (6)
435-438: 토글 핸들러는 함수형 업데이트로 안정화하세요.현재 클로저 의존 패턴은 불필요한 재생성을 유발합니다.
적용 예시:
-const handleBellExpandButtonClick = useCallback(() => { - setIsBellExpanded(!isBellExpanded); -}, [isBellExpanded]); +const handleBellExpandButtonClick = useCallback(() => { + setIsBellExpanded((prev) => !prev); +}, []);
675-681: 아코디언 토글 버튼에 a11y 속성과 회전 애니메이션을 추가하세요.type="button"으로 폼 제출 방지, aria-expanded/controls 제공, 아이콘 회전으로 상태 인디케이션 강화.
적용 예시:
-<button - className="h-full" - onClick={() => handleBellExpandButtonClick()} -> - <DTExpand className="h-full rounded-full p-[8px] text-default-black transition-colors duration-300 hover:bg-default-disabled/hover" /> -</button> +<button + type="button" + className="h-full" + onClick={handleBellExpandButtonClick} + aria-expanded={isBellExpanded} + aria-controls="bell-settings-panel" + aria-label={isBellExpanded ? '종소리 설정 접기' : '종소리 설정 펼치기'} +> + <DTExpand + className={clsx( + 'h-full rounded-full p-[8px] text-default-black transition-colors duration-300 hover:bg-default-disabled/hover', + 'transition-transform', + { 'rotate-180': isBellExpanded }, + )} + /> +</button>
685-685: 패널에 id/role 추가로 접근성 보강.적용 예시:
-{isBellExpanded && ( - <div className="flex w-full flex-col space-y-[8px] rounded-[12px] bg-default-dim2 p-[8px]"> +{isBellExpanded && ( + <div + id="bell-settings-panel" + role="region" + aria-label="종소리 설정 영역" + className="flex w-full flex-col space-y-[8px] rounded-[12px] bg-default-dim2 p-[8px]" + >
703-719: 분 입력 NaN/빈값 처리 보강.Number(e.target.value)가 NaN일 수 있으므로 기존 값 유지가 안전합니다. inputMode도 지정해주세요.
적용 예시:
- <input - type="number" + <input + type="number" + inputMode="numeric" min={0} max={59} className="w-[52px] rounded-[4px] border border-default-border p-[8px]" value={bellInput.min} - onChange={(e) => - setBellInput((prev) => ({ - ...prev, - min: Math.max( - 0, - Math.min(59, Number(e.target.value)), - ), - })) - } + onChange={(e) => { + const next = Number(e.target.value); + setBellInput((prev) => ({ + ...prev, + min: Number.isNaN(next) ? prev.min : Math.max(0, Math.min(59, next)), + })); + }} placeholder="분" />
722-739: 초 입력도 동일한 NaN/빈값 처리.적용 예시:
- <input - type="number" + <input + type="number" + inputMode="numeric" min={0} max={59} className="w-[52px] rounded-[4px] border border-default-border p-[8px]" value={bellInput.sec} - onChange={(e) => - setBellInput((prev) => ({ - ...prev, - sec: Math.max( - 0, - Math.min(59, Number(e.target.value)), - ), - })) - } + onChange={(e) => { + const next = Number(e.target.value); + setBellInput((prev) => ({ + ...prev, + sec: Number.isNaN(next) ? prev.sec : Math.max(0, Math.min(59, next)), + })); + }} placeholder="초" />
771-801: 리스트 key로 index 사용은 삭제 시 리렌더링 부작용 가능.간단한 UI라 큰 문제는 아니지만, 가능하면 고유 id를 사용하세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (4)
src/components/NotificationBadge/NotificationBadge.stories.tsx(1 hunks)src/components/NotificationBadge/NotificationBadge.tsx(1 hunks)src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx(4 hunks)tailwind.config.js(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/components/NotificationBadge/NotificationBadge.stories.tsx (1)
src/components/NotificationBadge/NotificationBadge.tsx (1)
NotificationBadge(8-28)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (7)
src/components/NotificationBadge/NotificationBadge.tsx (1)
NotificationBadge(8-28)src/components/icons/Expand.tsx (1)
DTExpand(3-25)src/components/DropdownMenu/DropdownMenu.tsx (1)
DropdownMenu(19-129)src/type/type.ts (2)
BellType(6-6)BellTypeToString(25-29)src/components/icons/Bell.tsx (1)
DTBell(3-61)src/components/icons/Add.tsx (1)
DTAdd(3-25)src/components/icons/Close.tsx (1)
DTClose(3-35)
🔇 Additional comments (5)
tailwind.config.js (1)
84-85: 새 색상 토큰(dim2) 추가 LGTM.디자인 토큰/가이드(Figma, 문서)와 값 동기화만 확인해주세요.
src/components/NotificationBadge/NotificationBadge.stories.tsx (1)
1-33: 스토리 구성 깔끔합니다.0/1/100/일반 케이스로 동작이 명확히 드러납니다.
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (3)
27-28: 신규 컴포넌트/아이콘 import LGTM.
151-153: 아코디언 상태 추가 LGTM.
662-674: 배지 배치 적절.relative 컨테이너 내 absolute 포지셔닝이 안정적으로 보입니다.
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx
Show resolved
Hide resolved
useon
left a comment
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.
숀 ! 아코디언 구현 빠르게 해 주셔서 감사해요 !!! 쉭쉭 돌아가는 애니메이션도 너무 좋은데요? 몇 가지 코멘트만 달았고 동작에는 문제 없어서 바로 어프루브 합니다 !!!!!!
| return null; | ||
| } | ||
|
|
||
| const displayCount = safeCount > 99 ? '99+' : safeCount; |
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.
99+ .. 디테일 !!!
|
|
||
| const handleBellExpandButtonClick = useCallback(() => { | ||
| setIsBellExpanded((prev) => !prev); | ||
| }, []); |
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.
불필요한 함수 생성 방지 조아요 ~!!!
| ? '종소리 설정 접기' | ||
| : '종소리 설정 펼치기' | ||
| } | ||
| onClick={() => handleBellExpandButtonClick()} |
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.
onClick={handleBellExpandButtonClick} 새로운 익명함수를 생성하는 대신에 이렇게 바로 함수를 참조하는 것은 어떨까요? 인수를 전달하지 않아서 매번 새로운 인스턴스를 생성하지 않아도 될 것 같아서요 !!
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.
제안 반영했습니다!
| <span className="flex w-full flex-row items-center space-x-[4px]"> | ||
| {/* 벨 유형 */} | ||
| <DropdownMenu | ||
| className="" |
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.
className 전달할 것이 없으면 명시하지 않아도 되지 않을까요? 클래스네임은 옵셔널이라 괜찮을 것 같아서요!
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.
Actionable comments posted: 0
♻️ Duplicate comments (1)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (1)
758-769: 타종 횟수 입력의% 10보정 관련해당 보정은 값 왜곡을 유발할 수 있어 제거 권장되어 왔습니다만, 본 PR에서는 입력 로직 개선을 별도 PR로 진행하기로 하셨으므로 여기서는 패스합니다.
🧹 Nitpick comments (3)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (3)
676-684: 접힘/펼침 접근성(ARIA) 보강 제안토글 버튼에
aria-expanded/aria-controls, 패널에id/role="region"/aria-labelledby를 연결하면 스크린리더 친화도가 높아집니다.적용 예시:
@@ - <div className="relative flex items-center space-x-[8px]"> - <p className="text-body w-[80px] font-medium"> + <div className="relative flex items-center space-x-[8px]"> + <p + id="bell-settings-heading" + className="text-body w-[80px] font-medium" + > 종소리 설정 </p> @@ - <button + <button className="h-full" type="button" aria-label={ isBellExpanded ? '종소리 설정 접기' : '종소리 설정 펼치기' } + aria-expanded={isBellExpanded} + aria-controls="bell-settings-panel" onClick={handleBellExpandButtonClick} > @@ - {isBellExpanded && ( - <div className="flex w-full flex-col space-y-[8px] rounded-[12px] bg-default-dim2 p-[8px]"> + {isBellExpanded && ( + <div + id="bell-settings-panel" + role="region" + aria-labelledby="bell-settings-heading" + className="flex w-full flex-col space-y-[8px] rounded-[12px] bg-default-dim2 p-[8px]" + >Also applies to: 699-699, 665-667
685-694: 아이콘 크기/트랜지션 미세 최적화
h-full대신 고정 크기와transition-transform만 지정하면 레이아웃 영향이 줄고 성능이 미세 개선됩니다.- <DTExpand - className={clsx( - 'h-full transform rounded-full p-[8px] text-default-black transition-all duration-300 ease-in-out hover:bg-default-disabled/hover', + <DTExpand + className={clsx( + 'w-[16px] h-[16px] transform rounded-full p-[8px] text-default-black transition-transform duration-300 ease-in-out hover:bg-default-disabled/hover', { 'rotate-180': isBellExpanded, 'rotate-0': !isBellExpanded, }, )} />
788-789: 하드코딩 색상 → 토큰 사용으로 통일성 확보
bg-[#FFF2D0]는 테마/다크모드 대응에 취약합니다. 이번 PR에서 도입한 토큰을 활용해보세요.- className="relative flex w-full flex-row rounded-[4px] border border-default-border bg-[#FFF2D0] px-[12px] py-[4px]" + className="relative flex w-full flex-row rounded-[4px] border border-default-border bg-default-dim2 px-[12px] py-[4px]"시각적 강조가 더 필요하다면
bg-semantic-material/10등 의미 기반 토큰도 고려 가능합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx(4 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-08T14:21:17.745Z
Learnt from: i-meant-to-be
PR: debate-timer/debate-timer-fe#335
File: src/page/TimerPage/components/NormalTimer.tsx:50-54
Timestamp: 2025-08-08T14:21:17.745Z
Learning: Progress 퍼센트(원형 게이지)는 컴포넌트가 아닌 훅(src/page/TimerPage/hooks/useCircularTimerAnimation.ts)에서 0–100으로 clamp한다. 향후 리뷰에서는 컴포넌트 레벨에서의 중복 clamp 제안 대신 훅 사용을 권장한다.
Applied to files:
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx
📚 Learning: 2025-09-03T14:25:28.457Z
Learnt from: i-meant-to-be
PR: debate-timer/debate-timer-fe#359
File: src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx:745-758
Timestamp: 2025-09-03T14:25:28.457Z
Learning: 사용자 i-meant-to-be는 PR #359에서 종소리 입력들(분, 초, 횟수 등)에 관한 리뷰를 생략하고 다른 PR에서 정리할 예정이라고 명시했다. 이런 입력 처리 로직 개선은 별도 PR로 분리하는 것을 선호한다.
Applied to files:
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx
🧬 Code graph analysis (1)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (7)
src/components/NotificationBadge/NotificationBadge.tsx (1)
NotificationBadge(8-32)src/components/icons/Expand.tsx (1)
DTExpand(3-25)src/components/DropdownMenu/DropdownMenu.tsx (1)
DropdownMenu(19-129)src/type/type.ts (2)
BellType(6-6)BellTypeToString(25-29)src/components/icons/Bell.tsx (1)
DTBell(3-61)src/components/icons/Add.tsx (1)
DTAdd(3-25)src/components/icons/Close.tsx (1)
DTClose(3-35)
🔇 Additional comments (3)
src/page/TableComposition/components/TimerCreationContent/TimerCreationContent.tsx (3)
27-28: NotificationBadge/DTExpand 도입 👍두 컴포넌트 import 및 사용 방향 모두 적절합니다.
151-153: 아코디언 상태 도입 적절
isBellExpanded기본값과 토글 구조 직관적입니다.
435-438: 토글 핸들러 안정화(Lambda 생성 회피) 잘 처리됨
useCallback으로 안정화했고, 호출부에서도 함수 참조를 직접 넘겨 불필요한 렌더를 피합니다.
jaeml06
left a comment
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.
넵 확인했습니다. dev환경에서도 정상작동합니다. 고생하셨습니다
🚩 연관 이슈
closed #358
📝 작업 내용
새로운 색상 추가
아코디언 UI에 사용된 새로운 배경 색상
default-dim2를 추가했습니다.알림 배지 컴포넌트 추가
앱 곳곳에서 공통적으로 사용할 수 있게
NotificationBadge컴포넌트를 추가했습니다.타임박스 추가 모달의 종소리 설정 영역에 아코디언 UI 적용
통합 회의에서 논의된 대로 아코디언 UI를 적용했습니다. 여러분의 이해를 돕기 위해 간단하게 변경된 코드를 설명하겠습니다:
상태 값 추가
isBellExpanded변수를 통해, 종소리 영역이 보이는지 여부를 저장합니다.true일 경우 보이는 거고,false일 경우 가려진 상태입니다.버튼 클릭 시 이벤트 추가
버튼 클릭 시 동작하는 토글 함수를 추가했습니다. 단순하게, 현재
isBellExpanded의 반대 값으로 변경하는 로직입니다.종소리 영역에 아코디언 UI 구조 적용
이해를 돕기 위해 스타일 태그는 간소화해 작성해 뒀습니다. 전체 코드는 Files Changed 탭에서 확인하실 수 있구요. 새로 추가한
NotificationBadge컴포넌트를 사용하여 코드를 작성했습니다. 이 배지 컴포넌트 같은 경우, 아래와 같이 동작합니다:확장 버튼과 종소리 설정 추가 버튼에 간단한 애니메이션을 적용하여 심미성도 높였습니다.
추가로, 입력 필드들의 너비를 기존 60 px에서 더 줄였는데요. 이 부분은 종소리 설정 부분에 회색 배경이 들어오면서 양옆으로 패딩이 붙어버리는 바람에, 종소리 영역이 열렸을 때 모달 오른쪽의 입력 영역의 너비가 크게 늘어나서 타이머 샘플 사진이 너무 쪼그라들었기 때문입니다. 코드 리뷰하실 때 참고하시면 될 것 같아요.
🏞️ 스크린샷 (선택)
닫혔을 때
열렸을 때
🗣️ 리뷰 요구사항 (선택)
동작 잘 되는지
npm run dev로 한 번만 확인해주세요!Summary by CodeRabbit
신규 기능
스타일
문서
작업