File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
08-14
08-14
08-18
08-18
08-14
08-14
08-14
08-18
08-18
08-14
08-18
// FoxToggleQuantity — 시안: 통합관리자페이지 디자인시스템 Figma toggle-quantity
//
// 회색 판 위에 빼기 버튼 · 숫자 · 더하기 버튼이 놓인다. 크기 수식어가 없다 — 시안이 한 벌만
// 준다.
//
// 마크업 계약 (React 밖 소비자용):
// <div class="fox-toggle-quantity" role="group" aria-label="수량">
// <button type="button" class="fox-toggle-quantity__button" aria-label="수량 줄이기" disabled>
// <span class="fox-toggle-quantity__icon">…빼기 svg…</span>
// </button>
// <span class="fox-toggle-quantity__value" aria-live="polite">1</span>
// <button type="button" class="fox-toggle-quantity__button" aria-label="수량 늘리기">
// <span class="fox-toggle-quantity__icon">…더하기 svg…</span>
// </button>
// </div>
//
// 숫자가 `flex: 1 0 0`이라 남는 자리를 혼자 가져간다 — 버튼 둘은 크기가 고정이므로 값이
// 한 자리든 세 자리든 버튼 위치가 흔들리지 않는다.
//
// ⚠️ 버튼이 `fox-icon-button`이 아니다. `fox-icon-button--sm`과 크기(28)·모서리(4)·아이콘
// 슬롯(20)이 전부 같지만 **배경이 다르다** — 아이콘 버튼의 `default` 계열은
// `button-default-surface`(투명)인데 이 시안은 `action-default`(불투명 흰색)다. 회색 판
// 위에 놓이므로 투명이면 판 색이 그대로 비쳐 버튼이 사라진다. 아이콘 버튼에 흰 배경 계열이
// 생기면 그때 이 규칙을 걷어내고 갈아탄다.
//
// 비활성은 배경만 바뀐다 — 시안이 disabled에 `border`를 적지 않아 테두리를 지운다(투명으로
// 두어 폭은 남긴다. 지우면 28×28이 26×26이 되어 판 안에서 자리가 밀린다).
//
// 토큰이 아닌 값:
// - ⚠️ `inline-size: 14rem`: **시안의 폭(140px)을 일단 그대로 적용해 둔 것이다.** Figma가
// 변수로 export하지 않았고 토큰 스케일에도 140이 없어서 원시값으로 남아 있다. 토큰이
// 생기면 `fox.*()`로 바꾸고, 폭을 고정하지 않는 쪽으로 정해지면 여기서 뺀다.
// 그때까지 폭을 바꿔야 하는 자리는 호출부가 `className`으로 덮는다.
// - letter-spacing: 시안 텍스트 스타일 label/lg-em의 값이나 Figma가 변수로 export하지
// 않는다. `-0.025em`이면 17px에서 -0.425px로 시안과 같고, 글자 크기가 브레이크포인트마다
// 달라져도 비율이 유지된다(다른 컴포넌트와 같은 근거).
// - 아이콘 색 `fox.primitive(neutral-60)`: 시안 값 `#58616A`를 가진 **semantic 토큰이 없다**
// (icon 계열에 있는 것은 neutral-70인 `icon-neutral-default`와 neutral-50인
// `icon-neutral-subtle`뿐이다). 그래서 시안이 가리키는 원시값을 직접 쓴다 —
// `fox-select-option`이 그림자 색에 `alpha-black10`을 직접 쓰는 것과 같은 방식이다.
//
// ⚠️ 원시값이라 **다크 모드에서 뒤집히지 않는다** — 밝은 회색 아이콘이 어두운 버튼 위에
// 그대로 남는다(`action-default`는 다크에서 neutral-100이라 대비는 확보된다). 반전이
// 필요해지면 Figma에서 icon 계열에 neutral-60을 추가한 뒤 그 토큰으로 바꾼다.
// - box-sizing / display / flex / cursor / aspect-ratio: 구조·상호작용 규칙.
@use "@fox/styles/abstracts" as fox;
.fox-toggle-quantity {
// 안쪽 여백이 바깥 폭을 늘리지 않게 한다 — 시안의 140px은 테두리까지 포함한 값이다.
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
// ⚠️ 시안 값을 일단 적용해 둔 상태다 — 파일 상단 주석 참고.
inline-size: 14rem;
padding: fox.padding(2);
gap: fox.gap(2);
border-radius: fox.radius(4);
background: fox.color(surface-neutral-gray);
&__button {
box-sizing: border-box;
display: flex;
flex-shrink: 0;
justify-content: center;
align-items: center;
inline-size: fox.form(height-sm);
block-size: fox.form(height-sm);
// 시안이 버튼에 정사각 비율을 못박는다. 자리가 좁아 눌려도 모양이 무너지지 않는다.
aspect-ratio: 1 / 1;
padding: 0;
border: fox.border(1) solid fox.color(button-default-border);
border-radius: fox.form(radius-sm);
background: fox.color(action-default);
// 시안 값을 가진 semantic 토큰이 없어 원시값을 직접 쓴다(파일 상단 승인 항목 참고).
color: fox.primitive(neutral-60);
cursor: pointer;
&:disabled {
// 테두리를 지우지 않고 투명으로 둔다(파일 상단 주석 참고).
border-color: transparent;
background: fox.color(button-disabled-surface);
cursor: default;
}
}
&__icon {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
inline-size: fox.icon(4);
block-size: fox.icon(4);
aspect-ratio: 1 / 1;
}
// 넘긴 SVG가 슬롯을 꽉 채운다 — 크기는 슬롯이 정하고 SVG는 따라온다.
&__icon > * {
inline-size: 100%;
block-size: 100%;
}
// 남는 자리를 혼자 가져간다 — `flex-basis: 0`이라 글자 길이가 버튼 위치를 밀지 않는다.
&__value {
flex: 1 0 0;
color: fox.color(font-neutral-strong);
font-family: fox.font-family(body);
font-size: fox.font-size(label-lg);
font-weight: fox.font-weight(bold);
line-height: 1;
letter-spacing: -0.025em;
text-align: center;
}
}