// FoxSelectText — 시안: 통합관리자페이지 디자인시스템 Figma select-txt // // 글자만 있는 셀렉트다. 테두리도 고정 높이도 없고, 배경만 세 상태로 바뀐다. // // 마크업 계약 (React 밖 소비자용): //
// // //
// // `fox-select`와 무엇이 다른가: **폼 한 칸이 아니다.** 라벨·힌트·에러·필수 표시가 없고, // 배경 계열도 다르다 — `fox-select`는 중립(`action-default`, 흰 바탕에 테두리)이지만 이쪽은 // 강조(`action-primary`) 계열이라 기본이 **투명**이고 hover·pressed에서만 연한 파랑이 깔린다. // 크기가 글자 **계열까지** 바꾸는 것도 여기뿐이다 — lg는 heading/md(제목용 20px bold, // `font-family-title`), md·sm은 label/*-strong(본문용 medium)이다. 폼 한 칸이라면 크기를 // 바꿨다고 제목 폰트가 될 이유가 없다. 즉 이것은 "지금 무엇을 보고 있는지"를 글자로 보여 // 주면서 그 자리에서 바꾸게 하는 컨트롤이다. // // 크기가 바꾸는 것: 여백·간격·글자(계열·크기·굵기·줄높이)·아이콘 크기·글자 색. 모서리만 // 세 크기가 같다(`form-radius-xsm`). // // ⚠️ lg만 위아래 여백이 없다(`padding: 0 var(--padding-2)`). md·sm은 사방에 준다 — 시안이 // 그렇게 준다. lg는 줄높이가 140%라 그 자체로 위아래 여백을 만든다. // // ⚠️ 비활성은 시안에 없다. 색을 임의로 만들지 않고 hover·pressed만 막는다 — 네이티브 // `disabled`를 주면 커서와 클릭만 죽고 모양은 기본과 같다(`fox-tag`와 같은 처리). // // 토큰이 아닌 값(`fox-button`·`fox-tag`와 동일한 근거로 승인된 항목): // - letter-spacing: 시안 텍스트 스타일의 값이나 Figma가 변수로 export하지 않는다. 세 크기가 // 모두 `-0.025em`이라 규칙 하나로 끝난다(20px→-0.5px, 15px→-0.375px, 13px→-0.325px). // px이 아니라 em인 이유는 글자 크기가 크기 수식어마다, 그리고 브레이크포인트마다 // 달라지기 때문이다 — px으로 박으면 그 자리에서 비율이 어긋난다. // - line-height 1.4 / 1: 시안의 140% / 100%. 비율이라 토큰 스케일에 대응이 없다. // - box-sizing / display / flex / cursor / white-space / aspect-ratio: 구조·상호작용 규칙. // - `fox-select-text__list`의 위치·폭: 구조 규칙(아래 주석 참고). @use "@fox/styles/abstracts" as fox; // 목록의 위치 기준. `inline-block`인 이유는 글자만큼만 넓어야 하기 때문이다 — 블록이면 줄 // 전체를 차지해 제목 옆에 다른 것을 놓을 수 없다. .fox-select-text { position: relative; display: inline-block; &__trigger { // 여백이 바깥 크기를 늘리지 않게 한다. box-sizing: border-box; display: inline-flex; align-items: center; border: none; border-radius: fox.form(radius-xsm); background: fox.color(action-primary); cursor: pointer; letter-spacing: -0.025em; white-space: nowrap; &:hover:not(:disabled) { background: fox.color(action-primary-hover); } // 시안의 pressed는 `:active`가 받는다. &:active:not(:disabled) { background: fox.color(action-primary-pressed); } &:disabled { cursor: default; } } // 글자만 줄어들게 해 화살표가 밀리지 않게 한다. &__value { min-inline-size: 0; } &__icon { display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; // 시안이 아이콘에 정사각 비율을 못박는다. 자리가 좁아 눌려도 글리프가 찌그러지지 않는다. aspect-ratio: 1 / 1; } // 넘긴 SVG가 슬롯을 꽉 채운다 — 크기는 슬롯이 정하고 SVG는 따라온다. &__icon > * { inline-size: 100%; block-size: 100%; } // ── 크기 ──────────────────────────────────────────────────────────────────── // lg만 제목 계열이다(파일 상단 주석 참고). &--lg &__trigger { padding-block: 0; padding-inline: fox.padding(2); gap: fox.gap(2); color: fox.color(font-neutral-strong); font-family: fox.font-family(title); font-size: fox.font-size(heading-md); font-weight: fox.font-weight(bold); line-height: 1.4; } &--lg &__icon { inline-size: fox.form(icon-md); font-size: fox.form(icon-md); block-size: fox.form(icon-md); } &--md &__trigger { padding: fox.padding(2); gap: fox.gap(2); color: fox.color(font-neutral-default); font-family: fox.font-family(body); font-size: fox.font-size(label-md); font-weight: fox.font-weight(medium); line-height: 1; } &--md &__icon { inline-size: fox.form(icon-sm); font-size: fox.form(icon-sm); block-size: fox.form(icon-sm); } // sm만 여백과 간격이 한 단계 좁다. &--sm &__trigger { padding: fox.padding(1); gap: fox.gap(1); color: fox.color(font-neutral-default); font-family: fox.font-family(body); font-size: fox.font-size(label-sm); font-weight: fox.font-weight(medium); line-height: 1; } &--sm &__icon { inline-size: fox.form(icon-xsm); font-size: fox.form(icon-xsm); block-size: fox.form(icon-xsm); } } // `fox-select-option`의 기본값은 `inset-inline: 0`, 즉 여는 요소와 같은 폭이다. 폼 한 칸을 // 채우는 셀렉트에서는 맞지만 이쪽은 글자만큼만 좁아서 목록이 읽을 수 없게 눌린다. 왼쪽만 // 맞추고 폭은 **내용이** 정하게 한다. // // ⚠️ `min-inline-size: 100%`(트리거보다 좁아지지 말 것)를 걸지 않는다. 퍼센트는 위치 기준인 // `.fox-select-text`의 폭을 보는데, 이 요소는 `inline-block`이라 세로 flex·grid 안에 놓이면 // 부모의 `align-items: stretch`에 늘어난다. 그러면 목록이 그 늘어난 폭을 그대로 물려받아 // 화면을 가로지른다 — 목록 폭이 호출부 레이아웃에 끌려다니게 된다. 내용 폭만 보면 어디에 // 놓이든 목록은 같은 크기다. // // 클래스 둘을 겹쳐 적는다 — 한쪽이 `inset-inline` 단축, 이쪽이 `inset-inline-end` 낱개라 // 특정도가 같으면 파일을 @use 하는 순서가 승부를 가른다. 겹쳐 두면 순서와 무관하게 이긴다. .fox-select-option.fox-select-text__list { inset-inline-end: auto; inline-size: max-content; }