Button
사용자가 결과를 예측할 수 있는 명시적인 행동을 시작합니다.
목적
Button은 현재 맥락에서 사용자가 실행할 수 있는 행동을 나타낸다. 문구, 강조도, 위치를 함께 사용해 어떤 결과가 일어나는지 예측 가능하게 만든다.
선택 기준
- 저장, 생성, 검증, 삭제처럼 현재 화면에서 동작을 실행할 때 사용한다.
- 다른 위치로 이동하는 목적이면 anchor를 사용하고
asChild로 Button 스타일을 적용할 수 있다. - 한 화면의 주 행동은 하나만
default로 강조한다. - 상태 표시나 선택 가능한 filter에는 Badge나 Tabs처럼 의미가 맞는 component를 사용한다.
실제 패키지 렌더링
기본 사용 예시
구조
기본적으로 native button을 렌더한다. 텍스트를 중심으로 필요할 때 앞이나 뒤에 아이콘을 배치한다. asChild를 사용하면 자식 요소가 실제 DOM과 semantics를 소유하고 Button은 스타일을 제공한다.
변형과 크기
Variant:
default: 화면의 주 행동destructive: 삭제처럼 위험한 확정 행동outline: 보조 행동secondary: 같은 영역의 낮은 강조 행동ghost: toolbar나 밀집 영역의 보조 조작link: 문장 흐름 안의 낮은 강조 행동
Size:
default: 높이 40pxsm: 높이 40px, 더 작은 글자와 좌우 paddinglg: 높이 44pxicon: 40×40px 정사각형
기본값은 variant="default", size="default"다.
상태와 동작
hover, focus-visible, disabled가 스타일에 포함된다. disabled는 pointer event를 막고 투명도를 낮춘다. 전용 loading prop은 없으므로 비동기 처리 중에는 disabled와 진행형 문구를 함께 제공한다. form 안에서 제출이 목적이 아니면 type="button"을 명시한다.
콘텐츠
확인, 실행, 저장보다 초안 저장, 검증 실행, 커리큘럼 발행처럼 결과를 쓴다. 로딩 중에도 저장 중…처럼 작업 대상을 유지한다. 아이콘은 문구를 반복해서 설명하지 않고 인지 속도를 돕는 경우에만 사용한다.
접근성
아이콘만 있는 Button은 aria-label을 반드시 제공하고 필요하면 Tooltip을 함께 사용한다. focus ring을 제거하지 않는다. asChild를 사용할 때 자식이 실제 button 또는 anchor semantics와 keyboard 동작을 제공하는지 확인한다. disabled 상태의 이유가 중요하면 Button 가까이에 설명한다.
좁은 화면과 긴 콘텐츠
문구를 모호하게 줄이기보다 Button이 필요한 너비를 갖게 한다. 여러 행동이 좁은 화면에서 경쟁하면 주 행동을 유지하고 보조 행동을 DropdownMenu로 정리한다. 주요 form 제출 Button은 작은 화면에서 전체 너비가 유용할 수 있지만 모든 Button을 무조건 늘리지 않는다.
공개 API
Button: native button attributes,variant,size,asChild?: booleanButtonProps: 공개 prop typebuttonVariants: 동일한 Button variant 스타일을 composition에 적용하는 helper
전용 loading, icon, fullWidth prop은 없다.
예제
import { Button } from '@classum/dot-design-system/ui';
interface SaveActionsProps {
isSaving: boolean;
onSave: () => void;
}
export function SaveActions({ isSaving, onSave }: SaveActionsProps) {
return (
<div className="flex justify-end gap-2">
<Button type="button" variant="ghost">
변경 취소
</Button>
<Button type="button" disabled={isSaving} onClick={onSave}>
{isSaving ? '초안 저장 중…' : '초안 저장'}
</Button>
</div>
);
}피해야 할 사용
- 같은 영역에 default Button을 여러 개 두지 않는다.
- 안전한 행동을 destructive로 장식하지 않는다.
- 문구 없이 아이콘만 넣고 접근 가능한 이름을 생략하지 않는다.
- 비동기 처리 중 중복 실행이 가능하게 두지 않는다.
- anchor가 필요한 이동을 click handler와 router 호출로 흉내 내지 않는다.