# Button > 2026-10-10 추가 수정 요청 기준: Gray Solid/Outline 기준 #767676, Red Solid 추가. 팝업 결정 버튼은 동일 Solid·size. 일반 화면의 여러 반복·보조 버튼은 Outline, 검색은 조회 Solid Green / 초기화 Outline Gray 예외. 과거 검증 기록은 당시 결과이며 현재 검증은 [추가 수정 보고서](../guidelines/publisher-additional-review-2026-10-10.md)를 따릅니다. 현재 HM 구현과 Runtime-neutral 사용 기준 문서. 공통 원칙은 `AGENTS.md`와 `docs/guidelines/runtime-portability.md`를 따른다. 이 문서는 Button API·Token·상태·사용 위치·조합 계약을 기록한다. ## 1. 상태 | 항목 | 내용 | |---|---| | 구현 상태 | HM 스타일 적용 완료 (`hm-*` class 없음) | | 기준일 | 2026-10-08 (Role × Appearance 계약·현재 Story 대조) | | 기반 | shadcn/ui Button (CVA, Radix `Slot`) | | 대표 Story | `Components/Form/Button` → `All` (이름 "Button") | | 보류 | Brand label Text Border 두께(EXPERIMENTAL, 미적용), Focus(ui_viz TBD) | ## 2. 적용 근거 - **ui_viz Confirmed**: size, padding-x, label size/line-height(button.md §26, D-087), Brand gradient·bevel(D-087), Standard Solid/Outline 색(§28, D-086, D-087), Hover/Pressed 동일 Black 20%(§12), Red Outline Hover/Pressed Red 8%. - **HM 사용자 확정 규칙**: 실제 화면 Brand 최대 1개·팝업 Brand 금지, 일반 확인/작성 Solid 세트, 삭제 확인 Solid 세트·행/반복 작업 Outline, 같은 세트의 appearance와 size 통일(§5). Disabled `0.6`은 ui_viz 규격 값이며, Input·Select의 2026-10-02 결정과는 별개다. - **shadcn 유지**: 구조(CVA, `data-slot`, `cn(..., className)`), focus/invalid ring class, `ghost`·`link` variant와 기존 size 이름. - **미정의/TBD**: Focus 표현(ui_viz TBD → shadcn 기본 focus ring 유지), `aria-invalid` 표현(ui_viz에 없음 → shadcn class 유지), `ghost`·`link`의 규격(ui_viz 없음). ## 3. 기본 규격 | Size | Height(min) | Padding-x | Font / Line-height | |---|---|---|---| | `sm` | 28 | 10 | 12 / 18 | | `default` | 34 | 14 | 13 / 20 | | `lg` | 42 | 18 | 15 / 22 | - 높이는 `min-height`다. 기본 라벨은 `nowrap`으로 한 줄을 유지한다. 여러 줄이 필요한 경우 기존 `className="whitespace-normal"`을 명시하며, 이때만 줄바꿈에 따라 높이가 늘어난다(가운데 정렬, `overflow-wrap: anywhere`). - 세로 padding은 `(height − line-height) / 2 − border`로 계산한다. - Radius `--hm-radius-button`, font-family `--hm-font-family-base`. - Weight: Brand 700, Standard 500. - 아이콘 전용 size(`icon*`)와 `xs`는 shadcn 기본이며 HM 규격이 없다(`data-appearance`가 있는 버튼에 한해 `default|sm|lg`만 HM 크기 적용). ## 4. 상태 규격 | 상태 | 값 | 근거 | |---|---|---| | Default | treatment별 face/border (아래 Token) | ui_viz Confirmed | | Hover / Pressed (Brand, Solid) | face 위에 Black 20% overlay (`inset` shadow) | ui_viz §12 Confirmed | | Hover (Outline) | role ink로 채움 + 흰 글자 | ui_viz Confirmed | | Pressed (Outline) | 흰 face + Black 20% overlay | ui_viz Confirmed | | Red Outline Hover/Pressed | Red 8% face, Black overlay 없음 | ui_viz D-087 Confirmed | | Disabled | `opacity: 0.6`, `cursor: not-allowed`, Default paint 유지 | ui_viz Confirmed (HM roles) | | Focus | shadcn 기본 `focus-visible` ring | ui_viz TBD → shadcn 유지 | | Invalid | shadcn `aria-invalid` ring | ui_viz 미정의 → shadcn 유지 | - Brand/Solid의 Hover·Pressed는 `:not(:disabled)`에만 적용된다. - transition과 눌림 이동(`translate-y-px`)은 HM role에서 제거한다. - **`ghost`·`link`의 Disabled는 `opacity-50`(shadcn 기본)** 이다. HM role(`0.6`)과 값이 다르다. 규격이 없는 호환 variant라 그대로 둔다(아래 §11). ## 5. 사용 위치와 버튼 세트 - `brand`: 페이지 대표 실행에 사용한다. 실제 서비스 화면당 최대 1개이며 팝업에서는 사용하지 않는다. Storybook 비교 갤러리는 예외다. - `solid`: 일반 실행과 등록·저장·확인에 사용한다. - `outline`: 반복·보조 작업과 표/목록 행 작업에 사용한다. - 일반 작성·수정창: 취소 Solid + 등록/저장 Solid. - 일반 확인창: 취소 Solid + 확인 Solid. - 삭제 확인창: 취소 Solid + 삭제 Solid. - 표/목록 행과 반복·보조 작업: 동일 `appearance`의 Outline 조합. - 검색은 조회 `primary/solid` + 초기화 `cancel/outline`·같은 size를 사용한다. 조회·초기화는 진행/취소 결정 세트가 아니므로 같은 appearance를 강제하지 않는다. - 취소·적용처럼 동일 작업의 결정 세트는 `appearance`와 `size`를 통일한다. 역할 차이는 variant의 기존 역할색과 문구로 표현한다. 사용 위치를 기준으로 appearance를 명시하며 버튼 문구만으로 판단하지 않는다. 컴포넌트는 appearance 생략 시 기본 `brand`를 출력하므로, 팝업·버튼 세트에서는 기본값에 의존하지 않는다. ## 6. API ``` variant: shadcn "default | outline | secondary | ghost | destructive | link" → HM "primary | secondary | modify | destructive | cancel" + 별칭 "default"(= primary), "outline"(= primary + outline appearance) + 호환 "ghost", "link" appearance: (신규) "brand | solid | outline" 기본 "brand" size: "default | xs | sm | lg | icon | icon-xs | icon-sm | icon-lg" (shadcn 그대로) asChild: shadcn 그대로 ``` - 기본값: `variant="primary"`, `appearance="brand"`, `size="default"`. - 출력 속성: `data-slot="button"`, `data-variant`(별칭은 role로 정규화), `data-appearance`(`ghost`/`link`은 없음), `data-size`. - `secondary`의 의미가 바뀌었다: shadcn 회색 보조 → ui_viz Brown 역할. 기존 사용처 영향은 별도 확인하지 않았다. ### 6.1 허용 Role × Appearance (AI Reference) 현재 `button.css`의 역할별 Mapping과 대표 `All` Story의 `rolesFor`가 지원하는 조합은 다음과 같다. - `primary` (Green): `brand`, `solid`, `outline`. - `secondary` (Brown): `brand`, `solid`, `outline`. - `modify` (Orange): `brand`, `solid`. **`outline` 미지원**. - `cancel` (Gray): `solid`, `outline`. **`brand` 미지원**. - `destructive` (Red): `solid`, `outline` 지원. **`brand` 미지원**. 공개 Props는 `variant`와 `appearance`를 독립적으로 받는다. TypeScript 통과나 Storybook Controls에서 선택 가능하다는 사실은 해당 조합의 디자인 지원을 뜻하지 않는다. 미지원 조합에는 필요한 역할별 CSS Custom Property가 없으며 자동 보정·fallback도 없다. 기존 CSS 변수에 임의 fallback이나 새로운 역할색을 추가하지 않는다. ### 6.2 기본값·별칭·합성 주의 - ` // Alert Dialog 삭제 확인: 두 요소 모두 Standard Solid 취소 삭제 ``` 미지원 조합 추가, role별 자동 appearance 선택, 기본 appearance 변경은 사용자 결정이 필요한 별도 변경이다. 현재 계약과 공개 API를 유지한다. ## 7. Token Component Mapping 위치: `packages/ui/src/theme/button.css` (`--hm-button-*`). 공통 값은 `packages/ui/src/theme/default.css`, Primitive는 `packages/ui/src/theme/primitives.css`. - 공통 Semantic 재사용: `--hm-radius-button`, `--hm-font-family-base`, `--hm-font-weight-*`, `--hm-color-text-inverse`, `--hm-color-surface-default`, `--hm-color-action-*`, `--hm-sem-surface/border-action-primary`. - `--hm-button-height-md`는 `--hm-control-height-md`(34)를 참조한다. sm/lg 높이는 Button 전용 값이다. - Brand/Solid의 색 Token은 role별(`green|brown|orange|gray`)로 Component 안에 둔다. Brown/Orange gradient의 일부 stop과 Gray 값은 `default.css`의 공개 Theme palette를 참조한다. `button.css`에 직접 HEX는 남아 있지 않다. - Input·Select와 높이 값(28/34/42)이 겹쳐도 alias하지 않는다. 각 ui_viz 규격이 따로 확정한 값이기 때문이다. ## 8. Runtime-neutral DOM 계약 React가 아닌 Runtime도 배포된 `@hm-design/ui/theme.css` 또는 승인된 standalone Theme CSS를 먼저 로드하고, semantic `