// FoxSelectOptionItem — 시안: 통합관리자페이지 디자인시스템(KE9UILWhB8qTBe14uXUn4F) Figma select (컴포넌트 세트 111:272) // // 옵션 목록(`fox-select-option`)의 항목 하나다. // // 마크업 계약 (React 밖 소비자용): //
  • // …svg… // … // …svg… //
  • // // 위험한 선택지에는 `fox-select-option-item--danger`를 더한다. // // 선택 여부는 `aria-selected="true"`가 스타일 훅을 겸한다 — 상태용 클래스를 만들지 않는다. // 체크 아이콘은 `currentColor`라 선택된 항목의 글자색을 물려받는다. 그 색이 시안의 아이콘 // 색(`#1C589C`)과 같아 별도 색 규칙이 없다. // // 시안은 hover·pressed·selected·danger를 모두 `state` 하나로 묶어 놨지만, 앞의 셋은 // 브라우저가 스스로 아는 상태다(`--active`·`:active`·`aria-selected`). 밖에서 지정해야 하는 // 건 danger뿐이라 그것만 클래스로 받는다. // // 네이티브 대응이 없어 클래스로 두는 둘: // - `--active`: 키보드로 이동 중인 항목. 마우스 hover와 같은 모양이어야 하는데 `:hover`로는 // 표현할 수 없다. 리스트박스를 여는 요소의 `aria-activedescendant`가 이 항목을 가리킨다. // - `--danger`: 위험한 선택지. 값의 성격이라 브라우저도 ARIA도 알 방법이 없다. // // `__text`가 남는 폭을 먹어서 체크는 왼쪽 끝, 아이콘은 오른쪽 끝에 붙는다. // // 토큰이 아닌 값(FoxButton과 동일한 근거로 승인된 항목): // - line-height / letter-spacing: 시안 텍스트 스타일의 값이나 Figma가 변수로 export하지 않는다. // - cursor / flex-shrink: 구조·상호작용 규칙. @use "@fox/styles/abstracts" as fox; .fox-select-option-item { display: flex; align-items: center; gap: fox.gap(3); padding: fox.padding(4) fox.form(padding-sm); border-radius: fox.form(radius-sm); background: fox.color(action-secondary); color: fox.color(font-neutral-default); font-family: fox.font-family(body); font-weight: fox.font-weight(regular); font-size: fox.font-size(body-sm); // line-height 150% / letter-spacing -0.375px — Figma 텍스트 스타일 값이며 변수로 // export되지 않아 토큰이 없다(fox-button의 label/*-strong 사례와 같은 예외, 사용자 승인). line-height: 1.5; letter-spacing: -0.375px; cursor: pointer; // 키보드 화살표로 이동한 항목도 마우스 호버와 같은 모양이어야 하므로, 실제 `:hover` // 대신 JS로 추적하는 active 모디파이어를 쓴다. &--active { background: fox.color(action-secondary-hover); } &:active { background: fox.color(action-secondary-pressed); } &[aria-selected="true"] { background: fox.color(action-secondary-selected); color: fox.color(font-theme-secondary); } // danger(위험한 선택지). 배경·눌림은 다른 항목과 같고 글자·아이콘 색만 다르다. // // 선택돼도 색을 유지한다 — 위험한 걸 고른 직후가 그 사실을 가장 알려야 할 때다. 다만 // `aria-selected` 규칙과 특이도가 같아 그것만으로는 지지 않으므로, 선택자를 겹쳐 쓴 // 두 번째 줄이 선택된 danger 항목까지 잡는다. &--danger, &--danger[aria-selected="true"] { color: fox.color(font-system-danger); // 아이콘 계열은 토큰이 따로다 — 라이트 모드에서 글자(danger-60)보다 한 단계 // 밝다(danger-50). 힌트 메시지에서 쓰는 짝과 같다. .fox-select-option-item__icon, .fox-select-option-item__check { color: fox.color(icon-system-danger); } } &__text { flex: 1; } // 시안이 체크 아이콘에 `icon-3`(16px)을 건다. 아이콘 viewBox도 16×16 정사각형이라 // 슬롯을 그대로 채운다. &__icon, &__check { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; inline-size: fox.icon(3); block-size: fox.icon(3); } // 슬롯이 크기를 정하고 안의 SVG는 그 상자를 채운다. 비율이 다른 아이콘이 들어와도 // `preserveAspectRatio` 기본값이 비율을 지키며 축소해 가운데 놓는다. &__icon > *, &__check > * { inline-size: 100%; block-size: 100%; } }