// FoxIconButton — 시안: 관리자페이지 Figma btn-ico (400:6312) + btn-ico-toggle (404:5247) // // 두 시안은 계열·크기·모양이 같고 토글에만 `active` 상태가 하나 더 있다. 그래서 한 블록으로 // 두고, 켜짐은 `aria-pressed="true"`로 표시한다 — 토글 버튼의 표준 속성이라 스타일 훅과 // 접근성 표시를 겸한다. // // 마크업 계약 (React 밖 소비자용): // // 토글이면 `aria-pressed="true|false"`를 함께 준다. 아이콘만 있으므로 `aria-label`이 필수다. // 아이콘 SVG는 `currentColor`로 그려야 계열별 색이 적용된다. // // 시안에 `active`와 hover·pressed가 겹치는 조합이 없어(상태가 단일 축이다) 켜진 동안에는 // 켜짐 색이 유지된다. // // 토큰이 아닌 값(FoxButton과 동일한 근거로 승인된 항목): // - box-sizing / cursor / flex-shrink: 구조·상호작용 규칙. // - `blur()`: backdrop-filter의 필수 함수 표기. 반지름은 토큰이다. @use "abstracts" as fox; .fox-icon-button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; border: none; cursor: pointer; &:disabled { cursor: default; } &__icon { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; } &__icon > * { inline-size: 100%; block-size: 100%; } // ── 크기 (정사각형) ──────────────────────────────────────────────────────── // 아이콘 슬롯은 ghost만 한 단계 크다. 테두리가 없는 만큼 시안이 아이콘을 키웠다. &--lg { inline-size: fox.form(height-lg); block-size: fox.form(height-lg); border-radius: fox.form(radius-lg); .fox-icon-button__icon { inline-size: fox.icon(6); block-size: fox.icon(6); } &.fox-icon-button--ghost .fox-icon-button__icon { inline-size: fox.icon(7); block-size: fox.icon(7); } } &--md { inline-size: fox.form(height-md); block-size: fox.form(height-md); border-radius: fox.form(radius-md); .fox-icon-button__icon { inline-size: fox.icon(5); block-size: fox.icon(5); } &.fox-icon-button--ghost .fox-icon-button__icon { inline-size: fox.icon(6); block-size: fox.icon(6); } } &--sm { inline-size: fox.form(height-sm); block-size: fox.form(height-sm); border-radius: fox.form(radius-sm); .fox-icon-button__icon { inline-size: fox.icon(4); block-size: fox.icon(4); } &.fox-icon-button--ghost .fox-icon-button__icon { inline-size: fox.icon(5); block-size: fox.icon(5); } } &--xsm { inline-size: fox.form(height-xsm); block-size: fox.form(height-xsm); border-radius: fox.form(radius-xsm); .fox-icon-button__icon { inline-size: fox.icon(3); block-size: fox.icon(3); } &.fox-icon-button--ghost .fox-icon-button__icon { inline-size: fox.icon(4); block-size: fox.icon(4); } } // ── 계열 ────────────────────────────────────────────────────────────────── &--default { border: fox.border(1) solid fox.color(button-default-border); background: fox.color(button-default-surface); 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); } } &--ghost { background: fox.color(button-default-surface); 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); } } &--overlay { background: fox.color(alpha-default-inverse50); backdrop-filter: blur(fox.backdrop(blur1)); color: fox.color(icon-neutral-strong-inverse); &:hover:not(:disabled), &:active:not(:disabled) { background: fox.color(alpha-default-inverse75); } } // ── 켜짐 (토글) ──────────────────────────────────────────────────────────── // 계열 hover·pressed 뒤에 와서 켜진 동안 색이 흔들리지 않는다. &--default[aria-pressed="true"]:not(:disabled) { border: none; background: fox.color(button-primary-surface); color: fox.color(icon-neutral-strong-inverse); } // ghost는 배경이 그대로 투명하고 아이콘 색만 바뀐다. &--ghost[aria-pressed="true"]:not(:disabled) { background: fox.color(button-default-surface); color: fox.color(icon-theme-primary); } &--overlay[aria-pressed="true"]:not(:disabled) { border: fox.border(1) solid fox.color(border-neutral-subtle); background: fox.color(action-default); color: fox.color(icon-theme-primary); } } // 계열과 무관하게 같고 테두리·배경흐림이 없다. .fox-icon-button:disabled { border: none; background: fox.color(button-disabled-surface); backdrop-filter: none; color: fox.color(icon-neutral-disabled-strong); }