ComponentsP3 본문

Button

행동 유도 기본 컨트롤 — 3변형(primary·secondary·ghost) × 3크기. 기본 채움은 AA 4.5:1을 보장하고, 높이는 control 토큰으로 Flutter와 공유합니다.

마지막 업데이트 2026-06-28

한눈에#

행동 유도 기본 컨트롤. 화면당 primary는 1개를 원칙으로, secondary·ghost로 위계를 내립니다.

  • 3 변형
  • 3 크기
  • WCAG AA
  • Flutter 패리티

실제 맥락 — 위계 1·2·3 (primary는 화면당 1개)

사용 시점#

행동이면 Button, 그 외에는 목적에 맞는 컴포넌트를 — 대안을 실물로 비교합니다.

권장 — 이렇게 쓰세요

지양 — 이러지 마세요

쓴다행동 실행 — 저장·제출·삭제·생성

대신 Link페이지 이동·외부 링크

대신 Segmented옵션 중 택일(2~5)

대신 Switch보조적 켜고/끄기

해부#

실물 버튼 위에 토큰 실측을 핀으로 얹습니다 — 값이 바뀌면 핀도 함께 움직입니다(드리프트 0).

md · variant primary — 실물 렌더 위에 토큰 실측을 핀으로 표기
height
44pxcontrol.height-md
padding-inline
16pxspace-4
gap
8pxspace-2
radius
10pxbutton.radius
font
16 / 600body-1
border
1px

크기#

높이는 control.height-* 토큰 — 같은 줄의 Input·Select와 자동으로 정렬됩니다.

sm · md · lg — 공유 베이스라인에서 높이차 비교
sizeheightpadding-inlinefontsm32px12px14pxmd44px16px16pxlg52px24px16px
md — Input과 같은 줄에서 control.height로 자동 정렬

변형#

3단 위계. 색은 이름이 아니라 실제 스와치와 측정된 대비로 확인하세요.

primary
bg
button.bg
fg
button.fg
라이트 · AA 7.3:1
secondary
bg
surface
fg
primary-text
border
border-strong
라이트 · AA 7.3:1
ghost
bg
transparent
fg
text-muted
라이트 · AA 7.6:1
  • primary — 화면당 1개가 원칙인 기본 채움. Blue 700 + 흰 라벨로 7.3:1 — 버튼 라벨은 항상 일반 크기라는 사실에 맞춰 기본값부터 AA를 보장합니다(DD-6)
  • secondary — 아웃라인. 라벨은 primary-text(AA 보장 잉크)
  • ghost — 배경 없음. 툴바·반복 행동

대비 배지는 라이트 테마 기준입니다 — 다크 테마에서도 세 변형 모두 AA(4.5:1 이상)를 보장합니다.

상태#

Hover·Active·Focus는 의사클래스라 정적 문서에선 잘 안 보입니다 — 아래 매트릭스는 실제 Button에 동일 토큰을 적용해 모든 상태를 한 번에 보여줍니다.

변형 × 상태 — :focus-visible은 2px primary 링
defaulthoveractivefocusdisabledloadingprimary
secondary
ghost

셀은 실제 컴포넌트를 렌더하고 hover·active·focus를 동일 토큰으로 정적 재현 — 색 드리프트 0

loading은 라벨 앞에 Spinner를 더하고 버튼을 비활성화하며 aria-busy="true"를 부여합니다 — 텍스트는 그대로, 클릭은 차단됩니다. fullWidth는 부모 폭을 100% 채웁니다.

제출 중 피드백 선택과 모바일 버튼 문구 밀도는 Loading Feedback모바일 폼 액션 규칙을 따릅니다.

fullWidth — 부모 폭 100%

플레이그라운드#

컨트롤로 props를 조작하면 미리보기와 코드가 실시간 갱신됩니다.

Button를 직접 조작해 보세요

속성·테마·토큰을 바꾸고 React·Flutter 코드를 확인하는 풀스크린 빌더로 엽니다.

빌더 열기

플레이그라운드는 넓은 작업 영역이 필요해 웹·태블릿에서 편집할 수 있어요.

사용 지침#

권장 — 이렇게 쓰세요

지양 — 이러지 마세요

권장화면당 primary 1개 + 보조 위계(secondary·ghost)

지양primary 남발 — 위계가 무너집니다

권장아이콘 + 텍스트 라벨 — 의미가 분명

지양아이콘만 — 라벨 없으면 의미 모호(부득이하면 aria-label)

Props#

Prop타입기본값설명
variant'primary' | 'secondary' | 'ghost'primary시각 위계. primary 채움은 일반 크기 라벨 AA 4.5:1 보장 (DD-6)
size'sm' | 'md' | 'lg'md높이 32/44/52px — control.height 토큰과 동기
fullWidthbooleanfalse부모 폭 100% 채움
loadingbooleanfalse로딩 중 — 라벨 앞에 Spinner를 덧붙이고 비활성화 (불리언 prop 무접두, COMPONENT_API §1)
refRef<HTMLButtonElement>네이티브 <button>으로 전달되는 ref (React 19 ref-as-prop)

토큰#

토큰설명

접근성#

  • 네이티브 <button> 렌더 — Enter/Space 활성화가 기본 제공됩니다
  • type 기본값이 "button" — 폼 안에서 의도치 않은 submit을 방지합니다
  • :focus-visible에 2px primary 아웃라인 링 (위 상태 매트릭스 focus 열 참조)
  • 아이콘 전용 버튼은 aria-label을 소비자가 부여합니다

Flutter 패리티#

WDS Button은 Flutter WizButton과 동일 계약을 공유합니다 — 같은 3변형·3크기, loading·fullWidth, 그리고 control.height 높이 토큰. 웹과 Flutter가 한 SSOT에서 치수를 가져오므로 두 플랫폼의 버튼이 픽셀 단위로 일치합니다.