feat(widget): 공통 탭바와 타이틀바 컴포넌트를 추가한다
This commit is contained in:
105
docs/prd/20260519_캡슐탭바컴포넌트_prd.md
Normal file
105
docs/prd/20260519_캡슐탭바컴포넌트_prd.md
Normal file
@@ -0,0 +1,105 @@
|
||||
# PRD: 캡슐 탭바 컴포넌트
|
||||
|
||||
## 1. Overview
|
||||
Figma `20:3590` 디자인을 기준으로 메뉴 개수가 많을 때 가로 스크롤되는 재사용 가능한 Capsule Tab Bar Component를 개발한다.
|
||||
|
||||
---
|
||||
|
||||
## 2. Problem
|
||||
- 기존 `TextTabBarView`는 텍스트 탭 전용이며 최대 3개 메뉴를 전제로 한다.
|
||||
- Figma `20:3590`은 capsule 형태 탭이 여러 개 나열되고, 메뉴가 화면 너비를 넘으면 가로 스크롤되어야 한다.
|
||||
- 기존 Text Tab 요구사항과 capsule 탭의 높이, 패딩, radius, border, 스크롤 동작이 달라 같은 컴포넌트에 합치면 변경 범위와 회귀 위험이 커진다.
|
||||
|
||||
---
|
||||
|
||||
## 3. Goals
|
||||
- 검정 배경, 높이 52dp의 재사용 가능한 Capsule Tab Bar를 제공한다.
|
||||
- 탭 항목은 capsule 형태로 표시한다.
|
||||
- 선택된 탭은 `soda_400` 배경과 white 텍스트로 표시한다.
|
||||
- 선택되지 않은 탭은 black 배경, `gray_700` border, white 텍스트로 표시한다.
|
||||
- 탭 내부 텍스트는 14sp medium 계열 Typography를 사용한다.
|
||||
- 탭이 많아 화면 너비를 넘으면 가로로 스크롤되어야 한다.
|
||||
- 메뉴 개수는 1개 이상을 허용하고, 항상 하나의 메뉴만 selected 상태여야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 4. Non-Goals
|
||||
- 기존 `TextTabBarView` 동작을 변경하지 않는다.
|
||||
- 기존 화면에 신규 컴포넌트를 일괄 적용하지 않는다.
|
||||
- Compose, 신규 Activity, Fragment, ViewModel을 추가하지 않는다.
|
||||
- line 타입 또는 기존 text 타입 탭을 이번 컴포넌트에 통합하지 않는다.
|
||||
- Figma에 없는 배지, 아이콘, 닫기 버튼, 스크롤 인디케이터를 추가하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
## 5. Target Users
|
||||
- XML 레이아웃을 작성하거나 유지보수하는 Android 개발자.
|
||||
- 메뉴 개수가 동적으로 늘어날 수 있는 화면에서 capsule 탭 필터를 재사용하려는 개발자.
|
||||
|
||||
---
|
||||
|
||||
## 6. User Stories
|
||||
- 개발자는 여러 개의 카테고리 메뉴를 capsule 형태로 표시하고 싶다.
|
||||
- 개발자는 메뉴가 많을 때 화면 밖 메뉴를 가로 스크롤로 접근하게 하고 싶다.
|
||||
- 개발자는 선택된 메뉴를 하나만 유지하고, 선택 변경 콜백으로 화면별 동작을 연결하고 싶다.
|
||||
|
||||
---
|
||||
|
||||
## 7. Core Features
|
||||
|
||||
### Capsule Tab Bar Component
|
||||
Figma `20:3590` 기준 capsule 타입 탭바를 XML + Kotlin custom view로 제공한다.
|
||||
|
||||
#### Requirements
|
||||
- Figma: https://www.figma.com/design/HmN1yNdJ3EIpqknFL0Hkab/-%EA%B3%B5%EC%9C%A0%EC%9A%A9-%EB%B3%B4%EC%9D%B4%EC%8A%A4%EC%98%A8-UI-UX-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C?node-id=20-3590&m=dev
|
||||
- Container width: `match_parent`
|
||||
- Container height: `52dp`
|
||||
- Container background: black
|
||||
- Container horizontal start padding: `spacing_20`
|
||||
- Tab list layout: horizontal, center vertical
|
||||
- Tab gap: `spacing_8`
|
||||
- Tab height: `34dp`
|
||||
- Tab horizontal padding: `spacing_12`
|
||||
- Tab vertical padding: `spacing_8`
|
||||
- Tab corner radius: capsule 형태. 현재 `radius_100` 토큰이 없으므로 구현 시 신규 dimen 토큰 추가 또는 drawable radius 직접 지정 중 하나를 계획에서 명시한다.
|
||||
- Selected tab: background `soda_400`, text white, no border
|
||||
- Normal tab: background black, border `gray_700`, text white
|
||||
- 메뉴가 화면 너비를 넘으면 가로 스크롤되어야 한다.
|
||||
- 메뉴 개수는 1개 이상을 허용한다.
|
||||
- selected index가 범위를 벗어나면 첫 번째 메뉴를 selected로 보정한다.
|
||||
|
||||
#### Edge Cases
|
||||
- 메뉴가 0개이면 호출부 오류로 간주한다.
|
||||
- 이미 선택된 탭을 다시 선택하면 중복 콜백을 호출하지 않는다.
|
||||
- 메뉴 목록이 바뀌어 기존 selected index가 범위를 벗어나면 첫 번째 메뉴를 selected로 보정한다.
|
||||
|
||||
---
|
||||
|
||||
## 8. UX / UI Expectations
|
||||
- 첫 번째 탭은 왼쪽 20dp 지점에서 시작한다.
|
||||
- 각 탭은 8dp 간격으로 배치된다.
|
||||
- 탭은 텍스트 길이에 따라 width가 늘어나며, 고정 균등 분배하지 않는다.
|
||||
- 메뉴가 많으면 자연스럽게 좌우 스크롤된다.
|
||||
- 스크롤 영역은 탭바 높이 52dp 안에서 세로 중앙 정렬되어야 한다.
|
||||
|
||||
---
|
||||
|
||||
## 9. Technical Constraints
|
||||
- 현재 프로젝트는 XML Views + ViewBinding 기반이므로 XML 레이아웃과 Kotlin custom view 패턴을 사용한다.
|
||||
- 신규 Kotlin 코드는 `kr.co.vividnext.sodalive.v2.widget` 패키지 하위에 둔다.
|
||||
- 기존 `TextTabBarView`와 `TextTabSelectionState`의 동작을 깨지 않는다.
|
||||
- 기존 디자인 토큰 `soda_400`, `gray_700`, `white`, `black`, `spacing_8`, `spacing_12`, `spacing_20`을 우선 사용한다.
|
||||
- 필요한 경우 capsule radius 전용 dimen 또는 drawable 리소스를 최소 범위로 추가한다.
|
||||
|
||||
---
|
||||
|
||||
## 10. Metrics
|
||||
- 메뉴 1개 이상을 설정할 수 있고 항상 하나만 selected 상태다.
|
||||
- 탭 항목이 화면 너비를 초과해도 가로 스크롤로 접근할 수 있다.
|
||||
- Android 리소스 병합 및 디버그 빌드가 성공한다.
|
||||
- 관련 선택 상태 테스트가 통과한다.
|
||||
|
||||
---
|
||||
|
||||
## 11. Open Questions
|
||||
- 사용자 응답이 없으므로 기존 `TextTabBarView` 확장이 아닌 별도 `CapsuleTabBarView` 추가를 기본 설계로 확정한다.
|
||||
Reference in New Issue
Block a user