File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
08-14
08-18
08-14
08-14
08-18
08-19
08-19
// FoxButton — 시안: 통합관리자페이지 디자인시스템(KE9UILWhB8qTBe14uXUn4F) Figma btn (컴포넌트 세트 106:1606 · 섹션 390:439)
//
// 마크업 계약 (React 밖 소비자용):
// <button class="fox-button fox-button--primary fox-button--md">
// <span class="fox-button__icon">…svg…</span> <!-- 선택 -->
// <span class="fox-button__label">버튼</span>
// <span class="fox-button__icon">…svg…</span> <!-- 선택 -->
// </button>
// 비활성은 네이티브 `disabled`, 로딩은 앞 아이콘 자리에 `fox-button__spinner` + `disabled`.
// 그 안에 `fox-spinner`가 들어가며, 색은 `currentColor`라 계열별 글자색을 따라간다.
// 아이콘 SVG는 `currentColor`로 그려야 계열별 색이 적용된다.
//
// 토큰이 아닌 값 3건(사용자 승인):
// - line-height / letter-spacing: 시안 텍스트 스타일 label/*-strong의 값이나 Figma가
// 변수로 export하지 않는다. 네 크기가 같은 값이라 규칙 하나로 끝난다.
// - box-sizing: 높이 고정 + secondary·default의 1px 테두리 때문에 필수. 없으면 계열별
// 바깥 높이가 2px 어긋난다.
// - cursor / white-space / flex-shrink: 구조·상호작용 규칙.
@use "abstracts" as fox;
.fox-button {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
cursor: pointer;
font-family: fox.font-family(body);
font-weight: fox.font-weight(medium);
line-height: 1;
letter-spacing: -0.025em;
white-space: nowrap;
&:disabled {
cursor: default;
}
// 라벨만 줄어들게 해 아이콘이 밀리지 않게 한다.
&__label {
min-inline-size: 0;
}
&__icon,
&__spinner {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
}
&__icon > * {
inline-size: 100%;
block-size: 100%;
}
&--full-width {
inline-size: 100%;
}
// ── 크기 (높이만 고정, 너비는 가변) ────────────────────────────────────────
&--lg {
block-size: fox.form(height-lg);
padding-inline: fox.form(padding-lg);
border-radius: fox.form(radius-lg);
gap: fox.gap(2);
font-size: fox.font-size(label-lg);
.fox-button__icon,
.fox-button__spinner {
inline-size: fox.form(icon-lg);
font-size: fox.form(icon-lg);
block-size: fox.form(icon-lg);
}
}
&--md {
block-size: fox.form(height-md);
padding-inline: fox.form(padding-md);
border-radius: fox.form(radius-md);
gap: fox.gap(2);
font-size: fox.font-size(label-md);
.fox-button__icon,
.fox-button__spinner {
inline-size: fox.form(icon-md);
font-size: fox.form(icon-md);
block-size: fox.form(icon-md);
}
}
&--sm {
block-size: fox.form(height-sm);
padding-inline: fox.form(padding-sm);
border-radius: fox.form(radius-sm);
gap: fox.gap(2);
font-size: fox.font-size(label-sm);
.fox-button__icon,
.fox-button__spinner {
inline-size: fox.form(icon-sm);
font-size: fox.form(icon-sm);
block-size: fox.form(icon-sm);
}
}
// xsm만 gap이 한 단계 좁다.
&--xsm {
block-size: fox.form(height-xsm);
padding-inline: fox.form(padding-xsm);
border-radius: fox.form(radius-xsm);
gap: fox.gap(1);
font-size: fox.font-size(label-xsm);
.fox-button__icon,
.fox-button__spinner {
inline-size: fox.form(icon-xsm);
font-size: fox.form(icon-xsm);
block-size: fox.form(icon-xsm);
}
}
// ── 계열 ──────────────────────────────────────────────────────────────────
// 아이콘 색은 시안이 라벨과 별개 토큰으로 지정한다(지금은 값이 같다).
&--primary {
background: fox.color(button-primary-surface);
color: fox.color(button-primary-font);
.fox-button__icon {
color: fox.color(icon-neutral-static-inverse);
}
&:hover:not(:disabled) {
background: fox.color(button-primary-surface-hover);
}
&:active:not(:disabled) {
background: fox.color(button-primary-surface-pressed);
}
}
&--secondary {
border: fox.border(1) solid fox.color(button-secondary-border);
background: fox.color(button-secondary-surface);
color: fox.color(button-secondary-font);
.fox-button__icon {
color: fox.color(icon-theme-primary-strong);
}
&:hover:not(:disabled) {
background: fox.color(button-secondary-surface-hover);
}
&:active:not(:disabled) {
background: fox.color(button-secondary-surface-pressed);
}
}
&--default {
border: fox.border(1) solid fox.color(button-default-border);
background: fox.color(button-default-surface);
color: fox.color(button-default-font);
.fox-button__icon {
color: fox.color(icon-neutral-default);
}
&:hover:not(:disabled) {
background: fox.color(button-default-surface-hover);
}
&:active:not(:disabled) {
background: fox.color(button-default-surface-pressed);
}
}
// ⚠️ error 계열은 시안 미정.
&--error {
}
}
// 계열과 무관하게 같고 테두리가 없다(시안에서 disabled-border 미사용).
// 계열 모디파이어를 이기려면 특이도가 높아야 해 블록과 함께 지목한다.
.fox-button:disabled {
border: none;
background: fox.color(button-disabled-surface);
color: fox.color(button-disabled-font);
.fox-button__icon {
color: fox.color(icon-neutral-disabled-strong);
}
}