Files
HMDesign/docs/components/collapsible.md
T

103 lines
5.9 KiB
Markdown

# Collapsible
현재 HM 구현의 기준 문서. 공통 원칙은 `docs/guidelines/프로젝트-지침.md`(§6, §7), Token 구조 원칙은 `테마-토큰-가이드.md`를 따른다. 이 문서는 Collapsible 고유의 API·Token·상태·결정만 기록한다. Accordion(`accordion.md`)과 값을 공유하지 않는다.
## 1. 상태
| 항목 | 내용 |
|---|---|
| 구현 상태 | 구현 완료 (현재 HM 규격) |
| 기준일 | 2026-10-02 |
| 기반 | shadcn/ui Collapsible (Radix `Collapsible`) |
| 대표 Story | `Components/Disclosure/Collapsible` → `All` (이름 "Collapsible") |
| 보류 | 아래 §11 |
## 2. 적용 근거
- **참고 근거**: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Collapsible이 없다. 참고할 수치가 없었다.
- **현재 HM 규격**: 아래 §3~§4. 현재 HM Semantic 체계로 새로 정했다.
- **구현 방식**: shadcn / Radix Collapsible 구조(Root·Trigger·Content)를 유지. shadcn Collapsible은 스타일이 없는 primitive라, 일반 trigger(asChild 없음)에만 텍스트 trigger 모양을 주고 content 간격·타이포를 정했다.
- **Accordion과의 구분**: Collapsible은 단일 영역의 간단한 disclosure다. divider 구조와 chevron 내장이 없다. Accordion을 항목 하나로 쓰는 용도가 아니다.
- **보류**: §11.
## 3. 기본 규격 (현재 HM 규격)
| 항목 | 값 |
|---|---|
| Trigger(일반) | inline-flex, gap 8px, 배경·border·padding 없음, 14 / 20 / 500, `--hm-sem-fg-primary`, 포인터 커서 |
| Trigger(`asChild`) | 자식이 자기 스타일을 유지(예: HM Button). HM trigger 스타일은 적용되지 않는다 |
| Indicator | trigger 바로 아래 자식 `svg`가 있으면 16px, `--hm-sem-fg-secondary`, 열리면 180° 회전 |
| Content | 위 padding 8px, 14 / 20 / 400, `--hm-sem-fg-primary` |
| 긴 텍스트 | `overflow-wrap: anywhere`, 고정 높이 없음 |
| Divider / border | 없음 |
## 4. 상태 규격
| 상태 | 값 |
|---|---|
| Closed / Open | Radix `data-state`. 닫힌 content는 `hidden`(display: none) |
| Hover | 일반 trigger 밑줄(disabled 제외) |
| Focus (`:focus-visible`) | ring 모양 `0 0 0 3px ring 50%` (일반 trigger) |
| Disabled | `opacity: 0.6`(이 컴포넌트 값, 전역 Disabled 규칙으로 승격 안 함), `cursor: not-allowed` |
| Animation | 없음(shadcn Collapsible에 없고 HM Motion 규칙도 없다) |
## 5. API
Radix Collapsible props 그대로. export: `Collapsible`, `CollapsibleTrigger`, `CollapsibleContent`.
- `Collapsible`: `open`/`defaultOpen`/`onOpenChange`, `disabled`.
- `CollapsibleTrigger`: `asChild`. **`asChild`일 때는 `data-slot`을 붙이지 않는다**(DialogClose와 같은 규칙). 붙이면 자식 Button의 `data-slot="button"`이 덮여 HM Button 스타일이 사라진다. 일반 trigger 출력은 `data-slot="collapsible-trigger"`.
- `CollapsibleContent`: 출력 `data-slot="collapsible-content"`.
- 새 prop은 만들지 않았다.
## 6. Token
Component Mapping 위치: `packages/ui/src/theme/collapsible.css` (`--hm-collapsible-*`).
`trigger-text`, `trigger-gap`, `trigger-font-size|line-height|font-weight`, `icon-size`, `icon-color`, `content-gap`, `content-text`, `content-font-size|line-height`, `disabled-opacity`. Semantic만 참조하고 `--hm-accordion-*` 등 다른 컴포넌트의 Token을 쓰지 않는다. 신규 Primitive 없음.
## 7. shadcn / Radix에서 유지한 항목
Radix 구조·ARIA(`aria-expanded`, `aria-controls`)·Enter/Space·controlled/uncontrolled·disabled·`asChild`, `data-slot`, `cn(..., className)`, Content의 `hidden` 처리.
## 8. HM에서 변경한 항목
- 일반 trigger의 텍스트 trigger 스타일, Content 간격·타이포, indicator 회전은 shadcn에 없던 시각 규격을 추가한 것이다.
- `CollapsibleTrigger`의 `asChild` data-slot 처리(위 §5).
- Animation은 추가하지 않았다.
## 9. Storybook
- 대표 Story `All`("Collapsible"): `StateBoard`로 Closed, Open, Disabled, Long Content, Controlled + Button trigger를 한 페이지에 둔다. trigger 안 chevron은 일반 소비 조합(`lucide-react` 아이콘)이다.
- verification: `Closed`, `Open`, `Disabled`, `Long Content`.
## 10. 사용자 확정 결정
- 2026-10-02: ui-viz는 참고 자료이며 최종 기준은 현재 HM 구현과 이 문서다(작업 지시). 개별 수치에 대한 별도 결정은 없다.
## 11. 미확정 / 보류
- 수치(14/20/500, gap 8px, Disabled opacity 0.6)는 현재 HM 규격이며 디자인 확정 시 재검토.
- 열림/닫힘 animation 없음. Motion 규칙이 정해지면 Accordion과 함께 재검토.
- indicator는 컴포넌트에 내장하지 않고 소비 조합으로 둔다(Accordion과 다름). 내장 여부는 사용 사례가 쌓이면 결정.
- 박스형(border/배경) Content variant는 만들지 않았다.
- Hover 밑줄은 일반 trigger에만 적용한다.
## 12. 관련 파일
```
packages/ui/src/components/ui/collapsible.tsx
packages/ui/src/theme/collapsible.css
packages/ui/src/theme.css (import)
packages/ui/src/index.ts (export)
src/components/collapsible.stories.tsx
```
## 13. 검증 상태
- `npm run typecheck`, `npm run build`: 통과(2026-10-02).
- 실제 interaction(Browser pane): Enter로 열기(`aria-expanded=true`, indicator 180° 회전), Space로 닫기, 닫힌 content `display: none`, disabled 클릭 무반응(opacity 0.6, cursor not-allowed), controlled(Button trigger asChild)에서 클릭으로 열리고 상태 문구와 버튼 라벨(`접기`)이 갱신됨.
- Button trigger: `data-slot="button"`, `data-variant="primary"`와 HM Button 색이 유지됨.
- computed style: 일반 trigger 14/20/500, `rgb(10,34,29)`, 배경 투명, icon 16px, content 위 padding 8px. 긴 콘텐츠에서 가로 overflow 없음.
- 미확인: 포인터 클릭(JS click과 키보드만 사용), focus ring 시각, 390px 폭, uncontrolled `defaultOpen=false`에서 trigger 클릭(키보드 Enter로 대체 확인).