본문으로 건너뛰기
액션 / button

Button

행동을 트리거하는 기본 버튼.
액션buttonInteractivebutton버튼ctaaction
01 · Specimen

먼저 보고, 그다음 계약을 읽습니다

행동을 트리거하는 기본 버튼.

Workbench 불러오는 중…
Component intent의도와 경계 읽기

primary/secondary/ghost/danger 4 변형과 sm/md/lg 크기를 CSS 변수로 처리한다. loading 은 자식 앞에 sm Spinner 를 렌더하고 버튼을 disabled + aria-busy 로 만든다. leftIcon/rightIcon 은 `axe-btn__icon` 슬롯으로 래핑된다. asChild(Radix Slot)로 <a> 등 임의 element 에 버튼 스타일을 입힐 수 있으나 이때 Slot 은 단일 자식만 허용하므로 Spinner/icon 슬롯은 렌더되지 않는다.

02 · Use

예제

SSOT에 등록된 실제 API 기준 snippet입니다. standalone 배지만 독립 실행 단위이며, fragment는 주변 state·handler 문맥을 생략합니다.

01변형 + 크기tsxfragment
변형 + 크기
import { Button } from "@axe/ui";export function Example() {  return (    <>      <Button variant="primary" onClick={() => {}}>저장</Button>      <Button variant="ghost" size="sm">취소</Button>      <Button variant="danger" loading={false}>삭제</Button>    </>  );}
02asChild — 링크에 버튼 스타일tsxfragment
asChild — 링크에 버튼 스타일
import { Button } from "@axe/ui";<Button asChild variant="secondary">  <a href="/docs">문서 열기</a></Button>
03CSS-only (비-React)htmlfragment
CSS-only (비-React)
<button class="axe-btn axe-btn--primary" type="button">저장</button><button class="axe-btn axe-btn--secondary" type="button">  <span class="axe-btn__icon">→</span>다음</button>
03 · React

Props

TSX 소스가 진실입니다. 주요 export 컴포넌트의 public API만 노출합니다.

이름타입필수기본값설명
variant"primary" | "secondary" | "ghost" | "danger""secondary"시각 강조 단계 / 의미(danger = 파괴적 행동).
size"sm" | "md" | "lg""md"높이·패딩·폰트 크기. md 는 modifier 없이 기본.
asChildbooleanfalsetrue 면 <button> 대신 Radix Slot 으로 단일 자식 element 에 스타일/props 를 병합(예 <a>). 이때 Spinner/leftIcon/rightIcon 미렌더.
loadingbooleanfalsedisabled + aria-busy + 자식 앞 sm Spinner. `axe-btn--loading` 도 추가.
leftIconReact.ReactNode자식 앞 icon 슬롯(`axe-btn__icon` 래핑).
rightIconReact.ReactNode자식 뒤 icon 슬롯(`axe-btn__icon` 래핑).
type"button" | "submit" | "reset""button"네이티브 button type. 폼 제출은 명시적으로 submit 지정.
...restReact.ButtonHTMLAttributes<HTMLButtonElement>onClick·aria-label·name 등 나머지는 루트 element 로 전파(asChild 면 자식 element 로). 단 disabled·type 은 rest 가 아니라 명시 처리되어(disabled=loading||disabled, asChild 는 aria-disabled 로만) 전달된다.
04 · Any stack

.axe-* 클래스 계약

React 밖에서도 같은 표면을 그리는 공개 계약입니다. stable은 minor 버전 안에서 이름을 바꾸지 않습니다.

클래스안정성용도
.axe-btnstable버튼 루트.
.axe-btn--primarystableprimary 변형(CTA).
.axe-btn--secondarystablesecondary 변형(기본).
.axe-btn--ghoststableghost 변형(배경 없음).
.axe-btn--dangerstabledanger 변형(파괴적 행동).
.axe-btn--smstablesmall 크기.
.axe-btn--lgstablelarge 크기.
.axe-btn--loadingstableloading 상태 modifier.
.axe-btn__iconstableleft/right icon 슬롯 래퍼.
.axe-interactivestableButton 이 아닌 임의 클릭 요소(내비 행·표 링크·카드)에 다는 공유 affordance 유틸리티 — hover/focus-visible/press 어휘만 준다. Button 자신은 .axe-btn 어휘를 쓰므로 겹쳐 달지 않는다.
.axe-interactive--activestable.axe-interactive 의 활성 상태(accent 텍스트 + accent-soft 배경). aria-current="page" · aria-selected="true" · data-active="true" 와 동등.
비-React 소비 노트
프레임/변형은 CSS-only 로 재현 가능하나, loading Spinner 는 React <Spinner> 컴포넌트라 CSS-only 로는 스피너 마크업을 직접 넣어야 한다. asChild 병합도 React(Radix Slot) 전용.
05 · Inclusive

접근성

키보드, ARIA, 구현 노트를 함께 검토합니다.

Keyboard
  • Enter/Space 로 실행(네이티브 <button>)
ARIA

기본은 네이티브 <button> — role 불요. loading 시 disabled + aria-busy="true". asChild 는 native disabled 를 걸 수 없어 loading/disabled 를 aria-disabled="true" 로만 전달한다(키보드 활성화까지 막지는 않음 — 확실한 비활성이 필요하면 asChild 없이 쓸 것).

Notes

아이콘 전용 버튼은 aria-label 을 직접 넘길 것(...rest 로 전파). :active scale(0.98) 누름 피드백은 native :disabled 에서만 빠진다 — asChild 로 렌더된 aria-disabled 버튼(비-loading)은 :disabled 가 매치되지 않아 여전히 눌림 피드백이 적용된다(확실한 비활성은 asChild 없이).

06 · Judgment

권장 · 지양

권장
  • 라벨은 동사로(‘저장’, ‘삭제’).
  • 파괴적 행동은 variant="danger".
  • 제출 버튼은 type="submit" 명시.
지양
  • 한 화면에 primary 를 여러 개 두지 말 것.
  • asChild 로 감쌀 때 loading/icon 슬롯에 의존하지 말 것(미렌더).
  • 아이콘만 있는 버튼에 aria-label 을 빠뜨리지 말 것.
검색창을 열면 컴포넌트 인덱스를 불러옵니다.