File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
// FoxButton 스타일 — 시안: 관리자페이지 Figma, node 390:439 (`btn`)
//
// **모든 디자인 값은 토큰으로만 지목한다.** 시안의 Figma 변수가 우리 토큰과 1:1로
// 대응하므로 예외가 필요 없었고, 아래 세 가지만 토큰이 아니다(사용자 승인 후 사용):
//
// 1. `line-height: 1` / `letter-spacing: -0.025em`
// 시안 텍스트 스타일 `label/*-strong`의 값이다(lineHeight 1, letterSpacing -2.5%).
// Figma에서 텍스트 스타일로만 존재하고 변수로 export되지 않아 토큰이 없다.
// 네 크기가 모두 같은 값이라 스케일이 아니고 규칙 하나로 끝난다.
// 2. `box-sizing: border-box`
// 높이가 고정인데 secondary·default가 1px 테두리를 가져, 없으면 계열별로 바깥
// 높이가 2px 어긋난다. 디자인 값이 아니라 레이아웃 메커니즘이다.
// 3. `cursor` / `white-space` / `flex-shrink` 등 구조·상호작용 규칙.
//
// 이 파일은 CSS를 출력하므로 `fox-button.module.scss` **한 곳에서만** `@use`한다.
// 전역 진입점(`index.scss`)에 넣으면 안 된다.
@use "abstracts" as fox;
.button {
box-sizing: border-box;
display: inline-flex;
align-items: center;
justify-content: center;
border: none;
cursor: pointer;
// 시안 label/*-strong. 크기별 font-size는 아래 size 클래스가 정한다.
font-family: fox.font-family(body);
font-weight: fox.font-weight(medium);
line-height: 1;
letter-spacing: -0.025em;
white-space: nowrap;
}
.button:disabled {
cursor: default;
}
.fullWidth {
inline-size: 100%;
}
// 라벨이 길어도 아이콘을 밀어내지 않게 라벨만 줄어들 수 있게 둔다.
.label {
min-inline-size: 0;
}
// 아이콘 슬롯. 크기는 size 클래스가, 색은 type 클래스가 정한다 —
// 안에 들어오는 SVG는 `currentColor`로 그려야 계열별 색이 적용된다.
.icon,
.spinner {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
}
.icon > * {
inline-size: 100%;
block-size: 100%;
}
// ── 크기 ────────────────────────────────────────────────────────────────────
// 높이만 고정이고 너비는 내용에 따라 가변이다(시안도 좌우 padding만 지정).
.sizeLg {
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);
.icon,
.spinner {
inline-size: fox.form(icon-lg);
block-size: fox.form(icon-lg);
}
}
.sizeMd {
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);
.icon,
.spinner {
inline-size: fox.form(icon-md);
block-size: fox.form(icon-md);
}
}
.sizeSm {
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);
.icon,
.spinner {
inline-size: fox.form(icon-sm);
block-size: fox.form(icon-sm);
}
}
// xsm만 gap이 한 단계 좁다(시안 확인).
.sizeXsm {
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);
.icon,
.spinner {
inline-size: fox.form(icon-xsm);
block-size: fox.form(icon-xsm);
}
}
// ── 계열 ────────────────────────────────────────────────────────────────────
// 아이콘 색은 라벨 색과 별개 토큰으로 지정돼 있어(시안) 각각 지목한다 —
// 지금은 두 값이 같지만 토큰이 갈라지면 시안을 따라가야 한다.
.typePrimary {
background: fox.color(button-primary-surface);
color: fox.color(button-primary-font);
.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);
}
}
.typeSecondary {
border: fox.border(1) solid fox.color(button-secondary-border);
background: fox.color(button-secondary-surface);
color: fox.color(button-secondary-font);
.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);
}
}
.typeDefault {
border: fox.border(1) solid fox.color(button-default-border);
background: fox.color(button-default-surface);
color: fox.color(button-default-font);
.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 계열은 시안 미정이라 규칙을 두지 않는다. 확정되면 여기에 채운다.
.typeError {
}
// ── 비활성 ──────────────────────────────────────────────────────────────────
// 계열과 무관하게 같은 모양이고 **테두리가 없다**(시안에서 disabled-border 미사용).
// `.button:disabled`가 계열 클래스보다 특이도가 높아 뒤에 두지 않아도 이긴다.
.button:disabled {
border: none;
background: fox.color(button-disabled-surface);
color: fox.color(button-disabled-font);
.icon {
color: fox.color(icon-neutral-disabled-strong);
}
}