Button
클릭·키보드 입력으로 사용자 액션이나 링크 이동을 실행하는 React 컴포넌트입니다. 스킨·색상·크기· 아이콘·상태를 props와 유틸리티 클래스로 조합합니다.
기본 유형
btn_filled · btn_outline · btn_ghost · btn_text 네 가지 기본 스킨을 제공합니다.
셀렉트 박스형
btn_select 클래스로 셀렉트 박스처럼 표시합니다. btn_select-text는 배경·테두리 없는 텍스트 형태입니다. 드롭다운·팝오버 트리거로 사용하며 aria-haspopup과 aria-expanded를 지정합니다.
텍스트 버튼
btn_text 계열 스킨으로 배경·테두리 없이 표시합니다. primary, muted, danger 등 색상 변형과 아이콘·크기·상태 조합을 지원합니다.
아이콘 + 텍스트
아이콘과 함께 사용하는 텍스트도 btn_label 클래스로 감쌉니다.
아이콘 + 텍스트 (세로)
btn_vertical 클래스로 아이콘을 위·텍스트를 아래에 배치합니다. 하단 탭·퀵 액션 등에 사용합니다.
아이콘 + 텍스트 (세로) · 균등 배분
btn_vertical과 btn_row-equal을 함께 사용하면 부모 100% 너비에서 버튼을 균등 분배합니다. 하단 탭 바 등에 사용합니다.
텍스트 + 아이콘
텍스트를 앞에 두고 아이콘을 뒤에 배치합니다. 텍스트는 btn_label로 감쌉니다.
아이콘 버튼
텍스트 없이 아이콘만 표시합니다. btn_icon-only와 함께 사용하며, 접근성을 위해 aria-label을 반드시 지정합니다.
아이콘 버튼 크기
btn_sm, medium, btn_lg 세 가지 크기를 지원합니다.
색상 변형
상황에 맞는 색상 변형을 사용합니다.
크기
small, medium, large 세 가지 크기를 지원합니다.
라운드
btn_round 클래스로 pill(캡슐) 형태의 둥근 모서리를 적용합니다. btn_icon-only와 조합하면 원형 아이콘 버튼이 됩니다.
너비
부모 영역 기준으로 너비를 조절합니다. btn_block은 가로 전체, btn_row-equal은 부모 100% 너비에서 버튼을 균등 분배, btn_grow는 비율 분배, btn_fit은 콘텐츠 너비를 유지합니다.
상태
disabled, is-disabled, is-loading 상태를 표현합니다. 비활성은 스킨별로, 로딩은 텍스트·아이콘 버튼 모두 적용할 수 있습니다.
버튼 그룹
가로·세로 방향으로 버튼을 묶습니다. btn_group-fit은 콘텐츠 크기 맞춤, btn_group-block은 전체 너비 균등 분배, btn_group-align-start·center·end로 그룹 정렬을 지정합니다.
최신 버전 v2.0 · 릴리스 노트
루트 태그
tag prop으로 button · a · div를 선택합니다. div와 href 없는 a에는 키보드 접근을 위해 role과 tabIndex={0}을 자동 적용합니다.
API · Props
| Prop | 타입 | 기본값 | 설명 |
|---|---|---|---|
variant | 'filled' | 'outline' | 'ghost' | 'text' | 'select' | filled | 버튼 스킨. select는 셀렉트 박스형 트리거 |
color | 'primary' | 'default' | 'success' | 'warning' | 'danger' | 'muted' | primary | 색상 변형. filled는 default·primary·success·warning·danger, text는 primary·muted·success·warning·danger 지원 |
size | 'sm' | 'md' | 'lg' | md | 버튼 크기 |
label | ReactNode | — | 버튼 텍스트. children으로 대체 가능 |
round | boolean | false | pill(캡슐) 형태 모서리 |
vertical | boolean | false | 아이콘 위 · 텍스트 아래 세로 배치 |
iconOnly | boolean | false | 아이콘만 표시. ariaLabel 필수 |
block | boolean | false | 루트 버튼을 부모 너비 100%로 확장 |
grow | boolean | '2' | false | flex 비율 분배. 2는 2배 너비 |
fit | boolean | false | 콘텐츠 너비 유지 |
disabled | boolean | false | button은 HTML disabled, a·div는 aria-disabled와 상호작용 차단 적용 |
ariaDisabled | boolean | false | Tab 순서에서 제외하고 is-disabled·aria-disabled·상호작용 차단 적용 |
loading | boolean | false | 스피너와 aria-busy를 표시하고 중복 상호작용 차단 |
open | boolean | false | 셀렉트 트리거 열림 상태 |
error | boolean | false | 셀렉트 트리거 오류 상태 |
placeholder | boolean | false | 셀렉트 미선택 placeholder 스타일 |
selectText | boolean | false | 배경·테두리 없는 셀렉트 텍스트 형태 |
selectCaret | boolean | false | select 이외의 스킨에도 드롭다운 캐럿 표시 |
type | 'button' | 'submit' | 'reset' | button | button 요소 type 속성 (tag="button"일 때만) |
tag | 'button' | 'a' | 'div' | button | 루트 HTML 태그. div·href 없는 a는 role과 tabIndex={0} 자동 적용 |
href | string | — | tag="a"일 때 href. 있으면 네이티브 링크, 없으면 role과 tabIndex 자동 적용 |
role | 'button' | 'link' | — | tag="a"이고 href가 없을 때 의미 지정. 필요한 tabIndex는 자동 적용 |
tabIndex | number | — | React tabIndex. div·href 없는 a는 기본 0, 비활성 -1 |
ariaLabel | string | — | 접근성 라벨 (iconOnly 시 필수) |
haspopup | boolean | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | — | aria-haspopup (셀렉트·드롭다운 트리거) |
expanded | boolean | — | aria-expanded (셀렉트·팝오버 트리거) |
invalid | boolean | false | aria-invalid (폼 오류) |
ripple | boolean | true | 클릭 파장(ripple). true 시 data-ripple 활성 · false 비활성. 기본 활성 |
선언되지 않은 HTML 속성·이벤트(id,data-*, onClick 등)는tag로 지정한 루트 요소에 그대로 전달됩니다.
API · Children
| Children / Prop | 설명 |
|---|---|
children | label을 대체하는 ReactNode. iconOnly이고 iconBefore가 없으면 아이콘 콘텐츠로 사용 |
iconBefore | 텍스트 앞에 렌더링할 ReactNode 아이콘 |
iconAfter | 텍스트 뒤에 렌더링할 ReactNode 아이콘 |
클래스 · 속성
React 컴포넌트가 렌더하는 OOCSS 클래스입니다. HTML 마크업으로 직접 작성할 때 동일하게 조합합니다.
| 클래스 | 설명 |
|---|---|
btn | 루트 구조 클래스 |
btn_filled | 배경 채움 스킨 |
btn_outline | 테두리 스킨 |
btn_ghost | 투명 배경 스킨 |
btn_text | 텍스트만 스킨 |
btn_select | 셀렉트 박스형 트리거 |
btn_select-text | 텍스트형 셀렉트 트리거 |
btn_sm · btn_lg | 크기 변형 |
btn_round | pill(캡슐) 모서리 |
btn_vertical | 아이콘 위 · 텍스트 아래 |
btn_icon-only | 아이콘만 |
btn_block · btn_grow · btn_fit | 너비 레이아웃 |
icon · btn_label · btn_spinner | 내부 파트 |
btn_row · btn_group · btn_stack | 버튼 묶음 컨테이너 |
is-disabled · is-loading · is-open · is-error | 상태 클래스 |
color_primary · color_danger … | 색상 유틸 (스킨과 조합) |
data-ripple | 클릭 파장 활성. data-ripple="surface"는 절대 위치 보조 버튼용 |
data-ripple="false" | 해당 요소 ripple 비활성 |
data-no-ripple | 하위 전체 ripple 비활성 |
디자인 토큰
| 토큰 | 기본값 | 설명 |
|---|---|---|
--btn-padding-y · --btn-padding-x · --btn-font-size | 0.5rem · 1rem · var(--text-size-base) | 기본(md) 패딩·타이포 |
--btn-padding-y-sm · --btn-padding-x-sm · --btn-font-size-sm | 0.3rem · 0.75rem · var(--text-size-sm) | sm 크기 |
--btn-padding-y-lg · --btn-padding-x-lg · --btn-font-size-lg | 0.65rem · 1.25rem · var(--text-size-lg) | lg 크기 |
--btn-font-weight · --btn-font-weight-normal · --btn-line-height | 600 · 400 · 1.4 | 타이포 두께·줄높이 |
--btn-border-width · --btn-gap | 1px · var(--space-sm) | 테두리·내부 간격 |
--btn-icon-size · --btn-icon-size-md · --btn-icon-size-lg · --btn-icon-size-xl | 1em · 1.125em · 1.25em · 1.375em | 아이콘 크기 |
--btn-icon-only-padding · --btn-icon-only-padding-sm · --btn-icon-only-padding-lg | 0.5rem · 0.35rem · 0.65rem | 아이콘만 버튼 패딩 |
--btn-vertical-min-width · --btn-vertical-min-width-sm · --btn-vertical-min-width-lg | 4.5rem · 3.75rem · 5.25rem | 세로 배치 최소 너비 |
--btn-vertical-padding-y · --btn-vertical-padding-x | 0.65rem · 0.75rem | 세로 배치 패딩(md) |
--btn-vertical-padding-y-sm · --btn-vertical-padding-x-sm | 0.5rem · 0.6rem | 세로 배치 패딩(sm) |
--btn-vertical-padding-y-lg · --btn-vertical-padding-x-lg | 0.85rem · 0.9rem | 세로 배치 패딩(lg) |
--btn-vertical-label-size · --btn-vertical-label-size-sm · --btn-vertical-label-size-lg | var(--text-size-sm) · var(--text-size-xs) · var(--text-size-base) | 세로 배치 라벨 크기 |
--btn-vertical-label-weight · --btn-vertical-label-line-height | 500 · 1.25 | 세로 배치 라벨 두께·줄높이 |
--btn-select-min-width · --btn-select-max-width | 10rem · 320px | 셀렉트 트리거 너비 |
--btn-select-padding-right · --btn-select-padding-right-sm · --btn-select-padding-right-lg | 0.65rem · 0.5rem · 0.85rem | 셀렉트 캐럿 여백 |
--btn-select-text-padding-x · --btn-select-text-padding-right | 0.5rem · 0.35rem | 텍스트형 셀렉트 패딩 |
--btn-select-text-padding-x-sm · --btn-select-text-padding-right-sm | 0.35rem · 0.25rem | 텍스트형 셀렉트 패딩(sm) |
--btn-select-text-padding-x-lg · --btn-select-text-padding-right-lg | 0.65rem · 0.45rem | 텍스트형 셀렉트 패딩(lg) |
--btn-spinner-size · --btn-spinner-border · --btn-spinner-duration | 1em · 2px · 0.6s | 로딩 스피너 |
--btn-stack-text-size · --btn-stack-text-line-height | var(--text-size-sm) · 1.5 | 스택 하단 안내 텍스트 |
--btn-group-overlap | -1px | 그룹 버튼 테두리 겹침 |