Files
HMDesign/docs/components/toggle.md
shkim4 4c29894e56 refactor(storybook): simplify component and preview examples
Drop page / section descriptions, state notes and repeated captions from
the representative Stories of 44 components, the Patterns, Center
Graphic and OrgChart pages. Value readouts, spec lists and captions hide
only on the representative page; hidden verification Stories keep them.
Tabs Default API and the Filter Bar draft / applied counts move to the
hidden DefaultApi and DraftApplied Stories; Center Overview is hidden
with its direct URL kept. Story IDs are unchanged.

Align the component, pattern and OrgChart docs with the pages, point the
quality reference check at the DraftApplied Story, and make the P8
styles check expect no section header on the preview-only Expanded page.
2026-10-23 00:28:05 +09:00

8.3 KiB
Raw Permalink Blame History

Toggle

현재 HM 구현의 기준 문서. 공통 원칙은 docs/guidelines/프로젝트-지침.md(§6, §7), Token 구조 원칙은 테마-토큰-가이드.md를 따른다. 이 문서는 Toggle 고유의 API·Token·상태·결정만 기록한다.

1. 상태

항목 내용
구현 상태 구현 완료 (현재 HM 규격)
기준일 2026-10-02
기반 shadcn/ui Toggle (Radix Toggle)
대표 Story Components/Form/Toggle → All (이름 "Toggle")
보류 아래 §11

2. 적용 근거

  • 참고 근거: 외부 ui_viz Reference (ZIP 미포함)의 기존 테스트 규격에는 Toggle이 없다(인벤토리에 Switch 계열 기능 이름으로만 언급). 참고할 수치가 없었다.
  • 현재 HM 규격: 아래 §3~§4. 현재 HM Semantic/Primitive로 새로 정했다.
  • 구현 방식: shadcn / Radix Toggle 구조와 variant(default | outline), size(default | sm | lg) API를 유지하고, 모양은 HM 독립 Token(--hm-toggle-*)으로 정한다.
  • Button과의 관계: 이 문서 §14.
  • 보류: §11.

3. 기본 규격 (현재 HM 규격)

항목 값
Size sm 28px, default 34px, lg 42px (높이). padding-x 8 / 12 / 16px
Icon-only 단일 React element + 직계 svg 하나인 경우 data-icon-only와 CSS로 padding 0. SVG + text node는 size별 padding 8/12/16px 유지
Radius --hm-radius-control-md (4px)
Typography 14 / 20 / 500, icon + text는 gap 8px
Off 배경 투명, 글자 --hm-sem-fg-primary
On 배경 --accent, 글자 --accent-foreground (full Accent; Select 선택 항목의 Accent 45% 면과는 별도 정책)
outline variant 1px --hm-sem-stroke-input-default border(default는 border 없음)
커서 pointer

4. 상태 규격

상태 값
Off / On Radix `data-state="off"
Hover (off) 배경 --accent 45% (on 상태는 그대로 On 면)
Selected + Hover (on) 배경 --accent 100%, 글자·아이콘 --accent-foreground 유지. Hover 45% 면으로 내려가지 않음
Focus (:focus-visible) shadcn ring (ring-3 ring-ring/50) 유지
Disabled opacity: 0.6(이 컴포넌트 값, 전역 Disabled 규칙으로 승격 안 함), cursor: not-allowed, 클릭·hover 무반응

5. API

Radix Toggle props 그대로. export: Toggle, toggleVariants.

  • pressed/defaultPressed/onPressedChange, disabled, asChild.
  • variant "default" | "outline", size "default" | "sm" | "lg"(shadcn 호환). 출력 data-variant, data-size, data-slot="toggle".
  • icon-only Toggle은 소비자가 aria-label을 준다(Story 참고).
  • 새 variant는 만들지 않았다(default, outline 두 개만 유지).

6. Token

Component Mapping 위치: packages/ui/src/theme/toggle.css (--hm-toggle-*).

height-sm|md|lg, padding-x-sm|md|lg, radius, gap, font-size|line-height|font-weight, off-background|off-text, hover-background, on-background|on-text, outline-border-width|color, disabled-opacity. Semantic과 Theme palette(--hm-sem-stroke-input-default)만 참조한다. --hm-button-*와 Button의 role 체계는 참조하지 않는다. 신규 Primitive와 Semantic 없음.

7. shadcn / Radix에서 유지한 항목

Radix 구조·aria-pressed·data-state·Enter/Space·controlled/uncontrolled·disabled·asChild, shadcn variant/size API와 toggleVariants(cva), focus ring class, svg 정렬 class, data-slot, cn(..., className).

8. HM에서 변경한 항목

  • shadcn toggleVariants의 색·크기 class(h-8 min-w-8 px-2.5, hover:bg-muted, data-[state=on]:bg-muted, outline border-input shadow-xs)를 제거하고 theme CSS로 이전. On 면은 muted가 아닌 accent.
  • 기본 모양을 @layer components에 두어 소비자의 className(폭, radius, 레이아웃 utility)이 이긴다. 다른 theme CSS(레이어 밖)와 달리 Toggle은 Story에서 className="w-40 rounded-full"이 적용되는 것을 확인했다.

9. Storybook

  • 대표 Story All("Toggle"): Overview(Off/On, default·outline), 단독 · 연결 그룹(단독 Toggle, spacing=0 ToggleGroup 단일·다중 선택), Sizes, States(Disabled off/on). 2026-10-22 Icon-only·icon + text 예시는 숨김 IconOnly로만 확인하고, Controlled(pressed 표시)·className 확장 예시는 대표 화면에서 제거했다. pressed / onPressedChange와 className 확장 API(§5)는 그대로다.
  • verification: States, Icon Only, Disabled.

10. 사용자 확정 결정

  • 2026-10-02: ui-viz는 참고 자료이며 최종 기준은 현재 HM 구현과 이 문서다(작업 지시). Toggle은 Button과 독립 Component Token을 쓴다(작업 지시).
  • 2026-10-06 Selected 원복: Git baseline d101530의 --accent / --accent-foreground 매핑을 복원했다. 아이콘은 currentColor로 전경을 따른다. Border는 baseline대로 default 투명 / outline --hm-sem-stroke-input-default이며 Selected 전용 border는 없다. Active Semantic은 참조하지 않고 Focus는 기존 --ring → --hm-sem-stroke-input-focus(Light 2)와 ring-ring/50을 유지한다. Hover·Disabled·Icon-only / Icon+Text padding·Theme JSON·Runtime 계약 변경 없음.

11. 미확정 / 보류

  • 수치(28/34/42px, padding, On 면 accent, Disabled opacity 0.6)는 현재 HM 규격이며 디자인 확정 시 재검토.
  • On 상태 hover는 On 면 그대로이다(별도 hover 면을 정하지 않음).
  • On 상태를 Primary(진한 녹색 면)로 강하게 표시하는 variant는 만들지 않았다.
  • 아이콘 크기는 shadcn 기본(16px) 유지.

12. 관련 파일

packages/ui/src/components/ui/toggle.tsx
packages/ui/src/theme/toggle.css
packages/ui/src/theme.css            (import)
packages/ui/src/index.ts             (export)
src/components/toggle.stories.tsx

13. 검증 상태

  • 2026-10-06 Selected 원복 검증: Storybook All / ContentNodes에서 Default·실제 Hover·Selected·Selected + Hover·키보드 Focus·Disabled·Icon-only·Icon+Text 확인. Selected 배경 rgb(189, 223, 212) / 전경·아이콘 rgb(18, 51, 40), Focus는 Light 2 #266651 50%의 3px ring. Runtime API의 Active override는 Selected에 영향 없음, Accent/on Accent override는 면·전경만 변경, Focus override는 ring만 변경. 1280/390px에서 sm/default/lg Icon-only 28/34/42px square·padding 0, Icon+Text/Text-only padding-x 8/12/16px 및 Array/Fragment 조합 유지. typecheck, build, build-storybook, git diff --check 통과(기존 CSS 예시·Storybook chunk 경고 유지).

  • 2026-10-06 Visual QA: 1280/1024/768/390px, sm/default/lg에서 Icon-only PL/PR 0/0px·28/34/42px square, Icon+Text와 Text-only PL/PR 각각 8/12/16px, pressed 상태 정상. Array/Fragment icon과 Fragment/element label 조합도 확인. typecheck, build, build-storybook 통과.

  • npm run typecheck, npm run build: 통과(2026-10-02).

  • 실제 interaction(Browser pane): 클릭으로 off → on → off(aria-pressed, data-state 일치), 키보드 focus 후 Enter로 on, Space로 off, disabled는 클릭과 focus 불가, controlled는 클릭으로 pressed = true와 data-state="on" 동기화.

  • computed style: default 34px / On 배경 rgb(189,223,212)·글자 rgb(18,51,40), outline border rgb(222,219,210), sm 28px, lg 42px, icon-only 34×34, disabled opacity 0.6, className="w-40 rounded-full" 적용(폭 160px, radius 최대).

  • 미확인: 실제 pointer hover 면 시각, focus ring 시각, 390px(단일 버튼이라 폭 문제 없음).

14. 역할 구분 (Button · Checkbox · Radio Group · Switch와의 차이)

컴포넌트 역할
Button Action 실행(일회성). variant가 역할(primary/secondary/destructive…), appearance가 treatment
Toggle pressed 상태 유지(툴바식 on/off). aria-pressed
Toggle Group 선택 그룹(단일/다중 선택, roving focus)
Checkbox 폼의 boolean / 다중 선택
Radio Group 폼의 배타적 선택
Switch 설정 on/off(즉시 적용되는 설정 값)

Toggle은 Button과 모양이 비슷해 보여도 Button의 action 중심 variant 체계(role/appearance)와 --hm-button-* Token을 상속하지 않는다. 역할이 다르고, Button 규격이 바뀔 때 Toggle이 함께 바뀌면 안 되기 때문이다. 공통 의미(선택 면의 accent, control radius)만 Semantic으로 공유한다.