Button
사용자 동작을 트리거하는 올인원 버튼 컴포넌트
개요
Cals Button은 Foundation Button을 래핑하여 CALS 제품에 필요한 편의 기능을 모두 내장한 올인원 컴포넌트입니다.
주요 특징
- ✅ title/icon/children: 선언적 버튼 콘텐츠 구성 (children 사용 시 title 대신 적용)
- ✅ 동적 색상 파생: backgroundColor만 지정하면 hover/active/disabled 색상 자동 계산
- ✅ 조건부 토큰 오버라이드: 해당 prop이 있을 때만 토큰 오버라이드 (기본값 보존)
- ✅ 단축키 내장: shortcut prop으로 키 조합 지정
- ✅ FormItem 내장: label/showLabel prop으로 폼 레이블 자동 래핑
- ✅ 가시성 제어: visible prop으로 선언적 표시/숨김
- ✅ 포커스 제어: ref.focus()/blur()/element로 프로그래밍 제어
- ✅ 디자인 토큰: Foundation 토큰 시스템 완벽 호환
기본 사용
title prop으로 버튼 텍스트를 지정합니다. variant로 스타일을 선택할 수 있습니다.
Preview
children 사용
children을 지정하면 title 대신 직접 버튼 내용을 구성할 수 있습니다.
Preview
커스텀 색상 (backgroundColor)
backgroundColor prop을 지정하면 Foundation 토큰(--button-background-default-*)을 오버라이드하여 hover/active/disabled 색상을 자동 파생합니다.
- hover: 원본 색상에서 -20 어두워짐
- active: 원본 색상에서 -35 어두워짐
- disabled: 원본 색상에서 +60 밝아짐
Preview
커스텀 색상 + disabled
Preview
테두리 색상 (borderColor)
borderColor prop으로 테두리 색상을 별도 지정합니다. hover/disabled 테두리도 자동 파생됩니다.
Preview
⚠️ 토큰 오버라이드 규칙: 해당 prop이 없으면 토큰을 오버라이드하지 않습니다. 예를 들어 backgroundColor만 지정하면 foreground/border 토큰은 기본값(variant 설정)을 유지합니다.
폰트 커스터마이징
fontSize, fontWeight, fontFamily, fontStyle prop으로 폰트를 개별 지정합니다.
Preview
아이콘
icon prop으로 제목 텍스트 왼쪽에 아이콘을 배치합니다.
Preview
로딩 상태
loading prop이 true이면 Spinner가 표시되고 클릭이 차단됩니다.
Preview
가시성 제어 (visible)
visible prop으로 선언적으로 표시/숨김을 제어합니다.
Preview
FormItem 래핑 (label / showLabel)
label prop으로 레이블을 지정하거나, showLabel로 빈 레이블 공간을 표시하여 폼 컨트롤과 세로 정렬을 맞춥니다.
Preview
단축키 (shortcut)
shortcut prop으로 키 조합 배열을 지정합니다. 단축키가 눌리면 onClick(또는 onShortcut)이 실행됩니다.
Preview
포커스 제어 (ref)
ref를 통해 focus()/blur()/element에 접근합니다.
import { useRef } from "react"
import { Button, type ButtonRef } from "@vortex/ui-cals"
function Example() {
const buttonRef = useRef<ButtonRef>(null)
return (
<>
<Button
title="포커스 이동"
variant="outline"
onClick={() => buttonRef.current?.focus()}
/>
<Button ref={buttonRef} title="포커스 대상" />
</>
)
}API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | - | 버튼에 표시할 제목 텍스트 |
icon | ReactNode | - | 제목 왼쪽에 표시할 아이콘 |
variant | "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" | "tertiary" | "default" | 버튼 시각적 스타일 |
size | "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | "icon-xl" | "md" | 버튼 크기 |
loading | boolean | false | 로딩 상태 |
loadingIcon | ReactNode | - | 커스텀 로딩 아이콘 |
disabled | boolean | false | 비활성화 상태 |
visible | boolean | true | 표시 여부 (false면 렌더링 안 함) |
backgroundColor | string | - | 배경색 (hover/active/disabled 자동 파생) |
color | string | - | 텍스트 색상 |
borderColor | string | - | 테두리 색상 (hover/disabled 자동 파생) |
fontSize | string | - | 폰트 크기 |
fontWeight | string | number | - | 폰트 굵기 |
fontFamily | string | - | 폰트 패밀리 |
fontStyle | string | - | 폰트 스타일 (italic 등) |
shortcut | string[][] | - | 단축키 조합 배열 (예: [["ctrl", "s"], ["meta", "s"]]) |
label | string | - | FormItem 레이블 텍스트 |
showLabel | boolean | false | 빈 레이블 공간 표시 (세로 정렬용) |
type | "button" | "submit" | "reset" | "button" | HTML button type |
className | string | - | 버튼 컨테이너에 적용할 CSS 클래스 |
formClassName | string | - | FormItem 래퍼에 적용할 CSS 클래스 |
style | CSSProperties | - | 인라인 스타일 (토큰 오버라이드보다 우선) |
children | ReactNode | - | 버튼 내용 (지정 시 title 대신 적용) |
Events
| Event | Type | Description |
|---|---|---|
onClick | (e: MouseEvent<HTMLButtonElement>) => void | 버튼 클릭 시 호출 |
onShortcut | () => void | 단축키 실행 시 호출 (미지정 시 onClick 호출) |
Ref (ButtonRef)
| Property | Type | Description |
|---|---|---|
focus | () => void | 버튼에 포커스 |
blur | () => void | 포커스 해제 |
element | HTMLButtonElement | null | 네이티브 button 엘리먼트 |
기본 사용법
import { Button } from "@vortex/ui-cals"
// 기본
<Button title="저장" />
// 커스텀 색상
<Button title="실행" backgroundColor="#16a34a" />
// 단축키
<Button title="검색" shortcut={[["ctrl", "k"]]} />
// 폼 레이블
<Button title="저장" label="동작" />색상 파생 로직
| 상태 | 계산 방식 | 설명 |
|---|---|---|
| 기본 | backgroundColor 그대로 | 원본 색상 |
| hover | adjustColor(bg, -20) | 20만큼 어두워짐 |
| active | adjustColor(bg, -35) | 35만큼 어두워짐 |
| disabled | adjustColor(bg, +60) | 60만큼 밝아짐 |
borderColor도 동일한 규칙:
- hover: -20
- disabled: +60
접근성
권장 사항
- ✅ 의미 있는 title 텍스트 사용
- ✅ 아이콘 전용 버튼에 aria-label 추가
- ✅ disabled 상태에서 시각적 피드백 (색상 밝아짐)
- ✅ 단축키(shortcut)로 키보드 사용자 접근성 지원
- ❌ backgroundColor만으로 의미 전달 지양 (색맹 고려)
관련 컴포넌트
- Foundation Button: 기본 Button (Cals Button의 베이스)
- FormItem: 폼 래퍼 (label/showLabel 내부 사용)
- Kbd: 단축키 표시