Skip to content

refactor(ui): 공통 UI와 대화상자를 shadcn(Base UI)으로 통합 - #253

Merged
minbros merged 97 commits into
devfrom
refactor/shadcn-base-ui
Nov 2, 2026
Merged

minbros merged 97 commits into
devfrom
refactor/shadcn-base-ui

Conversation

@KangShinGyu98

@KangShinGyu98 KangShinGyu98 commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

노션

변경 내용

  • #254를 원래 base에 병합하여 Button·Dialog·AlertDialog·Drawer·메뉴·선택기·팝오버·탭 및 관련 화면·폼 전환을 함께 포함
  • 팝업/배경 이벤트 전파 경계와 시간 입력 동작을 보존하고 후속 Sonar 이슈도 해소
  • 목적지 검색 표시 분기를 분리하고 라벨 연결·경로 스위치 이벤트를 정리해 Sonar 이슈 4건을 해소
  • shadcn base-nova(Base UI)·cva를 설치하고 src/components/ui에 Toast·Spinner·Alert·Skeleton·Badge·Avatar·Chip·Field·Input·Textarea·Checkbox·Switch·Radio·SearchBar를 Figma 디자인 시스템 값으로 맞춤
  • 화면마다 직접 만든 토스트·로딩 표시·안내 상자·배지·칩·아바타·입력칸·체크박스·스위치를 ui 부품으로 교체
  • 코드 원칙 문서(principles·anti-patterns)를 Base UI·cva 기준으로 수정

변경 이유

  • 직접 만든 부품이 화면마다 모양·동작이 달라, 동작은 shadcn(Base UI)·모양은 Figma 디자인 시스템으로 통일

테스트

  • npm run lint — 검증한 #254와 동일 소스 트리
  • npm test — 병합 후 소스 트리가 검증한 #254와 동일함을 확인해 1,663개 통과 결과 재사용
  • npm run build — 검증한 #254와 동일 소스 트리의 로컬 테스트 설정 빌드 결과 재사용
  • 화면 확인: 이번 Sonar 수정은 브라우저 미실행. 기존 작성자의 pc-chrome·iphone 확인과 구분
  • SonarCloud 최신 head 재분석: 미해결 이슈 0건, Quality Gate OK

🤖 Generated with Claude Code

KangShinGyu98 and others added 30 commits October 29, 2026 15:04
- @base-ui/react, class-variance-authority 설치
- components.json 작성(style base-nova, init 없이 globals.css 유지)
- shadcn add로 sonner·spinner·alert·skeleton·badge·avatar·toggle·field·input·textarea·checkbox·switch·radio-group 받기(label·separator는 field가 함께 받음)
- 받은 코드는 그대로 두고 적용할 때 디자인 시스템에 맞춰 고친다. add가 함께 설치한 cn·next-themes도 그때 정리한다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 원칙 1-1: Radix 대신 Base UI(base-nova), init 없이 add로만 받기, cn import·dark: 정리, asChild 대신 render
- 원칙 3-6·안티패턴 17: 변형은 클래스 맵 대신 cva로 모으기
- Design.md 1-3·3-3: 설치 전 문구 정리

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Toast: circle-check(Positive)·circle-ban(Negative)
- Spinner: progress
- Checkbox·Radio: checkbox·checkbox-activated·radio-button(Figma 원본 선 2px·1.8px 유지)
- Avatar 대체: user
- 지도 카테고리 Chip: travel-restaurant·hotel·themepark·museum·train
- Design.md 2-1대로 width·height 삭제, currentColor, 원본에 있던 24×24 clipPath 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma Toast Base(5285:5064) 값으로 그림: 최소 높이 52, 여백 4·8·4·16, 간격 8, 모서리 8, border/default 1px, fill/elevation, 그림자 없음
- sonner 기본 CSS가 레이어 밖이라 unstyled + classNames로 토큰만 씀, 라이트 테마 고정
- 아이콘: Positive circle-check, Negative circle-ban(20px), 일반 안내는 아이콘 없음
- 닫기 44px·액션 XS Neutral Weak 모양, 접근성 라벨 한국어('알림', '닫기')
- next-themes·lucide·shadcn CSS 변수 제거, 화면은 위치·여백·시간만 넘기도록 Props 제한
- 쓰는 곳이 없어진 next-themes 의존성 삭제

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma progress 아이콘(252:30981)과 Button Loading 색: 기본 icon/default, 버튼 안 inverse
- 크기는 Figma 아이콘 크기(12·16·20·24·28·32, 기본 20)만 받고 svg에 px 클래스로도 줌(shadcn 부모 규칙에 덮이지 않게)
- 루트는 output(암묵 status), 기본 aria-label '불러오는 중', 동작 줄이기에서는 회전 멈춤
- lucide·cn 패키지 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma에 인라인 Alert가 없어 지금 상자 3종을 tone으로 옮김: neutral 회색 상자, brand 파란 틴트, warning 주황 테두리
- size lg(로그인·약관 화면)·md(앱 안 상자), orientation vertical·horizontal(동작 위치)
- 금지 색(primary 투명도, muted-brown 등)은 가까운 토큰·원시 색으로 바꿈
- 폭·바깥 margin을 두지 않아 넘치지 않게 함, role="alert" 기본(덮어쓰기 가능)
- shadcn 아이콘 칸·absolute 동작 위치·cn 패키지 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma에 없어 지금 블록 모양을 기본값으로: fill-strong, 0.25rem 모서리, 펄스, 동작 줄이기에서 멈춤
- tone subtle(fill)로 일정 목록 스켈레톤의 옅은 톤을 보존
- render={<span />} 지원(output·span 안), 기본 block, aria-hidden
- bg-muted(우때에 없는 색)·cn 패키지 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma 15 Badges: variant weak·solid·outline × tone 6종 × size lg(24)·md(20)
- Figma 값이 코드 토큰과 다른 색(primary/subtle은 blue-50, status subtle·strong)은 원시 변수로 맞춤
- 모서리 4px, 아이콘 lg 14·md 12px 고정, 비조작 라벨이라 hover·focus 없음
- shadcn variant(default·secondary·destructive 등)·cn 패키지 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma Avatar가 없어 지금 크기(24·28·32·36·40·56)·모양(원·둥근 사각)·톤·접속 링을 variant로 옮김
- 기본값은 Figma Header Profile(36px, fill/strong 원)
- 사진: referrer 없이 요청, 받는 동안 배경색, 실패하면 바로 대체, 주소가 바뀌어도 새 사진이 올 때까지 이전 사진 유지
- AvatarGroup·AvatarGroupCount는 버튼 안에 둘 수 있게 span으로, 쓰지 않는 AvatarBadge 삭제

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- toggle.tsx를 chip.tsx로 바꿈: Base UI Toggle 위의 Chip, 모양만 맡는 chipVariants(제거용 칩 등 버튼이 아닌 칩용)
- Figma 14 Chips: Solid·Outline × lg 44·md 36·sm 32, Selected(aria-pressed)·Pressed(:active)·Disabled 색
- Outline 선택+눌림 배경은 원시 변수로 Figma primary/subtle(blue-50)
- 120ms 색 전환, 모바일에서 md·sm 누르는 영역만 44px로 넓힘
- hover·그림자 없음(Figma에 없음)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Input: Figma Text Field 48px, Focused·Error·Disabled·Read Only를 DOM 상태(:focus·aria-invalid·:disabled·:read-only)로 그림
- Textarea: Figma Textarea Field 96px 고정 높이와 스크롤
- Field: Figma Header·Footer에 맞춰 FieldHeader·FieldLabel·FieldSuffix·FieldFooter·FieldDescription·FieldError·FieldCount
- 오류 글자는 status/negative/strong(원시 변수 red-800), 오류 테두리는 status-negative
- 쓰지 않는 Field 부품·separator.tsx와 이름 없는 role="group" 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma checkbox 아이콘: 해제는 border/default 외곽선, 선택은 primary 외곽선과 체크
- size md 24·sm 20(가계부 결제자·부담자 시안 크기)
- 비활성은 커서만 바꿈(저장 중 깜빡임 방지), 일부 선택(indeterminate)은 받지 않음
- lucide·cn 패키지 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma에 없어 쿠키 설정(md 트랙 48×28, 누르는 영역 56×44)과 경로 표시(sm 36×20) 모양을 옮김
- 지금처럼 <button type="button" role="switch">로 그림(nativeButton)
- 금지 색은 가까운 값으로: md 꺼짐 gray-600, sm 꺼짐 fill-strong, 손잡이 그림자는 지금 값 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Figma radio button 아이콘: 해제는 border/default 원, 선택은 primary/subtle(원시 변수 blue-50) 원과 10px primary 점
- 간격은 쓰는 쪽이 정하도록 RadioGroup 기본 grid gap 제거

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ui 파일이 모두 @/lib/utils의 cn(타이포 토큰 등록)으로 바뀌어 쓰는 곳이 없음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AppToaster가 ui/sonner의 Toaster를 그림(기기별 위치·여백은 그대로), richColors 제거
- unstyled로 바뀌어 쓰이지 않는 sonner [data-icon] 24px 규칙 삭제
- toast() 호출부는 그대로 sonner를 씀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- LoadingIndicator 27곳(21파일)을 Spinner로 바꾸고 LoadingIndicator.tsx 삭제(label → aria-label, size 14 → 16, 40 → 32)
- 버튼 안 2곳(승인 상태 확인·시간 시트 확인)은 색 className 대신 variant="inverse"
- 테두리 링 3곳(AuthFlowSpinner·RoomGrid·RoomTripSettingsSection)을 Spinner size 32로, RoomGrid의 role=status 래퍼 이름은 Spinner로 옮김
- lucide Loader2 3곳 교체: 이동 수단 행은 size 16·라벨(줄 높이가 튀지 않게 align-top), 일정 카드 사진·AI 처리 중은 장식용 aria-hidden

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 지도 카테고리·선택 카테고리·'영업 중' 칩을 Chip(outline md)으로, 아이콘은 Figma travel 아이콘(글자색을 따름)으로 바꿈
- 지도 칩 그림자를 칩 대신 가로 스크롤 줄 drop-shadow로 옮김(Figma Chip에는 그림자가 없음)
- 카테고리 초기화 버튼은 chipVariants와 CloseIcon, 평점 트리거 helper는 하나만 남기고 칩 값에 맞춤
- 목적지 입력값 칩을 chipVariants outline md로 바꾸고 제거 버튼 누르는 영역을 44×44로 넓힘
- 쓰지 않게 된 map-search SVG 6개와 MapSearchIcon 이름 정리

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- AGENTS.md 로딩 원칙·원칙 2-4·안티패턴 6: 작은 영역 로딩 표시는 Spinner
- 원칙 1-1: 맞는 부품에 src/components/ui 포함, 기존 사용처는 '두지' 않고 따로 옮김
- Design.md 1-4: Chips(5624-159)와 Badges(5864-12983) 페이지 링크를 나눔

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 로그인·약관 동의 화면·약관 섹션 오류 상자를 Alert brand lg로, 약관 없음 안내를 Alert lg role=status로 바꿈
- login-error-alert.tsx를 login/page.tsx에 합쳐 삭제하고 '!' 원은 grid로 제목 줄 가운데에 맞춤
- 장소 상세·경로 카드 오류와 모바일 장소 검색 오류를 Alert(기본·가로)로 바꾸고 바깥 margin은 감싸는 div padding으로 옮김
- 준비물 알림을 Alert warning 가로로 바꾸고 .alert·.alert button CSS 삭제(아래 16px은 감싸는 div pb-4)
- 버튼 글자 토큰에 덧붙인 font-medium·font-semibold 제거(약관 화면 버튼은 label-l-emphasis 700)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 일정·가계부 일차, 구성원 역할, 참여 승인 대기 상태 라벨을 Badge(weak md)로 바꿈(방장·승인 대기·일차는 brand, 참여자·참여 거절은 neutral)
- PC 장소 카드와 북마크 행의 장소 분류 라벨을 Badge(neutral md)로 바꾸고, 장소 카드는 안쪽 truncate span으로 말줄임 유지
- 쓰지 않게 된 PLAN_PLACE_CARD_TW.primaryTypeBadge 삭제

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 북마크 목록·폴더 상세, 장소 상세·시트 요약, 사진 자리, 경로 카드·후보 카드·경로 상세의 직접 만든 블록을 Skeleton으로 바꿈(bg-fill 블록은 tone subtle, 모서리만 className)
- output 안 블록은 render={<span />}로 span 유지
- 폴더 상세 래퍼의 animate-pulse를 지우고 블록마다 펄스
- PlaceDetailSkeleton의 Bar 헬퍼 삭제, 건드린 템플릿 리터럴 래퍼는 cn()으로
- bg-gray-200 블록은 bg-fill-strong이 되고, 동작 줄이기 설정에서는 펄스가 멈춤
- 일정 목록 스켈레톤(PlanLoadingSkeleton)은 모바일 바탕과 블록 색이 같아 묶음 펄스만 보이는 문제가 있어 결정 전까지 그대로 둠

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- UserAvatar를 ui Avatar로 다시 짜고 색·모양을 size·shape·tone·ring variant로만 받음(호출부 className 색 덮기 제거)
- 헤더 구성원 미리보기를 AvatarGroup·AvatarGroupCount로 옮기고, 본인이 위인 겹침 순서와 화살표 원을 묶음 안에 둠
- 채팅 메시지·장소 공유·새 메시지 미리보기·가계부 인물 아바타를 UserAvatar로 합치고 ChatMemberAvatarRing·chatMessageChrome.avatarSm 삭제
- WOORI·홈 헤더 빈 원·리뷰 작성자 이니셜을 ui Avatar로 교체
- 이름이 옆에 보이는 아바타는 장식으로 숨김(aria-hidden, alt="")

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 북마크 제목, 가계부 제목·금액·메모·예산, 여행 제목, 준비물 이름·메모, 모바일 메모 시트, 일정 카드 메모를 Field·FieldLabel·Input·Textarea로 바꾸고 라벨은 htmlFor/id로 연결
- 북마크 글자 수는 FieldSuffix, 가계부·준비물 메모 글자 수는 FieldFooter·FieldCount, 예산·준비물 입력 오류는 FieldError(role=alert), 모바일 메모 안내는 FieldDescription으로 옮김
- 예산 모달은 입력 검증 오류만 칸의 Error 상태로 그리고, 저장 실패·충돌 문구는 지금처럼 칸 밖 문장으로 둠
- 준비물 이름·메모에 aria-invalid·aria-describedby를 달아 오류를 Figma Error 모양으로 그림
- ExpenseAmountInput은 ui Input을 그리고 금액 고정폭 숫자(tabular-nums)만 더함
- 쓰지 않게 된 expenseInputClass·PLAN_PLACE_CARD_TW.memoTextarea·준비물 CSS 규칙·RoomTripEditFields 로컬 Field의 htmlFor 분기·일정 메모 rows 삭제
- 준비물 CSS의 레이어 밖 focus-visible 규칙에서 input·textarea를 빼 포커스를 primary 테두리로 통일
- react-test-renderer 가짜 이벤트에 currentTarget 추가(Base UI Input이 읽음, 기대값은 그대로)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 준비물 행·상세 헤더 체크박스를 Checkbox md로 바꾸고 label 래퍼(24px, 모바일 44px)는 유지, 비활성 커서는 래퍼 전체에 적용
- 가계부 결제자·부담자를 Checkbox sm으로 바꾸고, fieldset disabled가 닿지 않아 ExpenseRolePicker가 disabled를 받아 저장 중 비활성으로 둠
- 가계부 행 포커스 링을 has-[:focus-visible]로 바꿔 키보드 포커스에서만 표시
- 약관 전체 동의는 Checkbox md, 항목은 sm으로 바꾸고 전체 동의 행을 가운데 정렬
- 일정 '지도에 경로 표시'를 label 행 + Switch sm으로, 쿠키 설정 분석 쿠키를 Switch md로 교체(받은 checked 값 사용)
- 바텀시트 드래그 제외 선택자에 label·checkbox·switch·radio role 추가
- 쓰지 않게 된 준비물 CSS 규칙, packingIcons.checkbox·checkboxChecked, 체크박스 SVG 4개 삭제
- react-test-renderer 가짜 onChange 호출을 onCheckedChange 호출로 바꿈(기대값 그대로)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ui Textarea에 sizing 변형 추가: fixed(기본, Figma 96px 고정)·content(3줄 98px~5줄 146px, 넘치면 스크롤)
- content는 값이 바뀔 때마다 높이를 내용에 맞추고, 내용이 줄면 다시 줄어든다
- PC 일정 메모(PlanItemMemoForm)만 content를 쓴다(교체 때 사라진 끌어서 늘리기를 대신함)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 채팅 묶음·장소 공유 카드·새 메시지 미리보기에 복사돼 있던 사진 자리 규칙을 한 컴포넌트로 옮김
- 화면 결과는 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 함께 뜨지 않는 두 오류를 kind(field·save)가 있는 유니온 하나로 둠(원칙 2-1)
- 설명 id도 하나를 나눠 씀, 화면 결과는 같음

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 제목은 ui Field·Input, 글자 수는 Header Suffix로 옮김
- 목적지는 여행 정보 수정과 같은 배치(검색 칸 → 칩 → 경고)와 field 모양 검색 칸으로 바꿈
- 카드 클래스(TRIP_FORM_FIELD_*)와 쓰지 않던 읽기 전용 분기 삭제

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ui Chip은 기본 span(useRender), 누르는 칩은 render로 button·Toggle을 넘긴다
- ChipRemove(칩 안 X 버튼) 추가, chipVariants는 밖으로 내보내지 않음
- 지도 고르는 칩은 MapChipToggle(Outline md 고정, 모바일 44px 누르는 영역)로 옮김
- 목적지 칩 2곳·지도 초기화 버튼의 chipVariants className을 Chip으로 바꿈

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
KangShinGyu98 and others added 18 commits November 1, 2026 17:40
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 목록 폭이 트리거 폭(144·160)과 같아, 체크 자리 48과 스크롤 막대 15가 생기면 '전체 카테고리'가 두 줄이 됨
- 두 폭 구분 없이 184 하나로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 입력바 100 → 124(14px 글자 3줄), 모바일 기기는 100 그대로, 작은 패널 110 그대로
- 높이를 인라인 style에서 클래스(mobile: 변형)로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 스크롤 막대를 늘 숨겨 마우스로는 뒤쪽 일차(Day 20 등)에 닿을 수 없었음
- PC는 얇은 막대(북마크에서 추가 칩 줄과 같은 모양), 모바일 기기는 지금처럼 숨김

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 통화 칸 96 → 112: ui Combobox 트리거의 여백·▼ 자리(66)를 빼면 코드 자리가 30이라 KRW·BHD가 말줄임됐음
- 16px에서 가장 넓은 코드(MWK 37)도 들어가는 46 확보

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	src/components/rooms/RoomTripEditForm.tsx
- ConfirmDialog에 confirmDisabled 추가(확인 버튼만 비활성, 취소·닫기는 그대로)
- 동기화 오류 등 ready가 아닐 때 '삭제'가 눌리는데 아무 반응이 없던 문제(옛 화면은 비활성)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 대화상자 안 버튼만 loading(progress·aria-busy), 패널의 재시도 버튼은 대화상자 밖이라 문구 그대로

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 제목·목적지·기간을 form.Field + validators로, 오류는 칸 아래 FieldError(제목은 aria-invalid로 Text Field 오류 모양)
- 검증 함수는 trip-form.ts의 tripTitleError·tripDestinationsError·tripDateRangeError(나중에 zod 스키마 자리), 적용하기 잠금도 같은 함수
- RoomTripEditFields는 읽기 전용 칸만 남겨 RoomTripReadOnlyFields로, 목적지는 새 여행 만들기와 같은 DestinationChipsField 재사용
- 테스트는 실제 제목 칸·목적지·기간 onChange로 바꾸고 칸별 오류 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 포털된 대화상자·메뉴를 document에서 찾고, dialog[open] 대신 role="dialog"·menuitem
- Tab 순환·메뉴 좌표 단정은 Base UI 몫이라 빼고, 바깥 aria-hidden·포커스 복귀·메뉴 단계 전환으로 검사
- 저장 중 닫힘 막힘, 제목 칸 오류(aria-invalid·칸 아래 문장), 목적지 비움 오류, 기간 축소 확인 저장 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- react-test-renderer 대신 react-dom + document 조회, props 직접 호출 대신 실제 클릭·입력 이벤트
- 확인창: X 없음, 바깥 aria-hidden, 진행 중 접근성 이름 '처리 중'·aria-busy, 첫 포커스 '취소'
- 시트 끌기 수치·Tab 순환 테스트는 지우고, 저장 중 닫힘 막힘·모바일 메모 초안 유지·삭제 확인 confirmDisabled 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- dialog[open]·aria-modal·inert 대신 role="dialog"·바깥 aria-hidden, 메뉴·Select 목록은 document에서 menuitem·option으로
- 옛 SettingsDialog 클래스 계약(거터·640 폭) 테스트는 지움
- 쿠키 설정 취소(저장 안 하고 닫힘)·저장 결과 문장이 버튼 아래 live 영역에 보이는지, 모바일 메뉴 항목으로 수정 대화상자 열기 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- react-test-renderer(Base UI 메뉴 트리거가 렌더 단계에서 실패) 대신 react-dom + document 조회, props 직접 호출 대신 실제 메뉴·Select·탭 조작
- 확인창 mock 대신 실제 alertdialog, 예산 칸 오류는 aria-invalid·aria-describedby FieldError로 검사
- 정산 요약 대화상자 안 재시도는 progress(aria-busy·이름 '조회 다시 시도 중'), 패널 재시도는 native disabled 그대로인지 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- react-test-renderer props 호출 대신 react-dom + 실제 클릭·입력·키 이벤트, 가짜 native dialog 제거
- 오류는 칸별(aria-invalid·칸 아래 FieldError)로, 폼 아래 문장은 저장 실패·권한 같은 폼 전체 오류만
- 카테고리 칸 오류, 목록·통화 검색 Esc는 팝업만 닫힘, PC 딤은 안 닫고 모바일 시트 딤은 닫음, 빈 값 '장소 연결 없음' 표시 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- ExpenseDialog.drag.test 삭제: 옛 useSheetDrag 수치(translateY·80px) 검사라 끌기는 Base UI Drawer 몫
- ExpenseBackdrop.test를 새 동작으로 다시 씀: 모바일 시트는 딤으로 닫힘, PC는 딤으로 안 닫힘, 저장·삭제 중엔 딤·Esc·X·취소 모두 막힘
- ExpenseProvider·ExpenseScopePanel은 react-dom + document 조회, 삭제 중 확인 버튼 progress(aria-busy·이름 '삭제 중')

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 저장 요청(useUpdateRoom)을 대화상자가 만들어 폼에 내려 주고, 대화상자는 그 isPending으로 closeDisabled
- 저장 중 Esc·X로 닫히지 않는 테스트 추가

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Popover modal="trap-focus" + 보이지 않는 Popover.Close(Base UI는 닫기 부품이 있어야 가둠, Tab 순서 밖, 누르면 Esc처럼 취소)
- 달력이 body로 포털된 뒤 마지막 버튼에서 Tab을 누르면 로고 링크로 튀고 달력이 열린 채 남던 회귀

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
frontend-server Ready Ready Preview Nov 2, 2026 10:07am UTC

Request Review

refactor(ui): 대화상자·시트·메뉴·선택기를 shadcn(Base UI) 동작 부품으로 교체
@sonarqubecloud

sonarqubecloud Bot commented Nov 2, 2026

Copy link
Copy Markdown

@minbros minbros changed the title refactor(ui): 정적 화면 부품을 shadcn(Base UI)으로 교체하고 디자인 시스템에 맞춤 refactor(ui): 공통 UI와 대화상자를 shadcn(Base UI)으로 통합 Nov 2, 2026
@minbros
minbros merged commit f0d18e5 into dev Nov 2, 2026
3 checks passed

This branch was successfully deployed

1 active deployment
Preview — ec24c4dd Deployed Nov 2, 2026 by vercel[bot]
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.

2 participants