File name
Commit message
Commit date
File name
Commit message
Commit date
08-18
08-18
File name
Commit message
Commit date
08-14
08-14
08-14
08-18
08-18
08-18
08-14
08-14
08-14
08-14
08-18
08-18
08-14
08-18
08-18
// FoxChipSelectOption — 시안: 통합관리자페이지 디자인시스템 Figma chip-select-option
//
// 칩의 `select`가 열렸을 때 뜨는 목록이다. `fox-select-option`과 **다른 컴포넌트다** —
// 저쪽은 글자 한 줄짜리 listbox고, 이쪽은 시안이 체크박스·라디오 목록이라 이미 있는
// `fox-checkbox-group`·`fox-radio-group`을 그대로 담는다.
//
// 마크업 계약 (React 밖 소비자용):
// <div class="fox-chip-select-option" role="group">
// <div class="fox-chip-select-option__list">
// <div class="fox-checkbox-group fox-checkbox-group--vertical">…</div>
// </div>
// <button type="button" class="fox-chip-select-option__confirm">확인</button>
// </div>
//
// 폭은 **내용이** 정한다. 시안이 280px을 주지만 고정하지 않는다(사용자 결정) — 항목 글자가
// 길면 잘리고 짧으면 남는데, 어느 쪽도 목록이 스스로 해결할 수 있는 문제가 아니기 때문이다.
// 여는 칩의 폭도 따라가지 않는다: 칩은 글자만큼만 좁아서 거기 맞추면 읽을 수 없다
// (`fox-select-option`의 `inset-inline: 0`을 쓰지 않는 이유이기도 하다).
//
// 폭을 못박아야 하는 자리가 생기면 호출부가 `className`으로 준다.
//
// ⚠️ 확인 버튼은 **다중 선택 + 모바일**에서만 보인다. 조건이 둘이고 걸리는 자리가 다르다:
//
// - **다중 선택에만 있다** — React가 정한다. 단일 선택은 하나 고르는 순간 목록이 닫혀서 이
// 버튼이 할 일이 없다(눌러도 아무 일이 없는 버튼이 화면 아래를 차지하게 된다).
// - **모바일에만 보인다**(시안 주석 "모바일만 노출") — 이건 CSS가 정한다. 조건부 렌더로
// 하면 창 폭이 바뀔 때마다 DOM이 들락거려서, 열린 채로 화면을 돌리면 포커스가 날아간다.
//
// 값이 반영되는 시점은 플랫폼과 무관하게 같다(고르는 즉시). 모바일에서 달라지는 것은 닫는
// 수단이 하나 더 생기는 것뿐이고, 데스크톱에서 닫는 것은 바깥 클릭이다.
//
// ⚠️ `overflow: hidden`이 필요하다. 확인 버튼이 `align-self: stretch`라 판 좌우 끝까지
// 닿는데, 판의 둥근 모서리 밖으로 사각형 배경이 삐져나온다. 버튼에 모서리를 따로 주는 대신
// 판에서 한 번 잘라 낸다(`fox-segmented-control`과 같은 방식).
//
// 토큰이 아닌 값:
// - ⚠️ `max-block-size: 24rem`(240px): 항목이 많을 때의 상한. `fox-select-option`이 같은
// 이유로 잡아 둔 임시값을 그대로 따랐다(그 파일의 TODO 참고). 확정되면 함께 고친다.
// - box-sizing / position / display / flex / overflow / z-index / cursor: 구조 규칙.
@use "@fox/styles/abstracts" as fox;
.fox-chip-select-option {
box-sizing: border-box;
position: absolute;
inset-inline-start: 0;
inset-block-start: calc(100% + #{fox.gap(2)});
z-index: 10;
display: flex;
flex-direction: column;
align-items: flex-start;
// 내용이 폭을 정한다(파일 상단 주석 참고). `max-content`라 항목 글자가 줄바꿈되지 않고,
// 위치 기준인 `.fox-chip-select`가 좁아도 거기 눌리지 않는다.
inline-size: max-content;
// 확인 버튼의 사각 배경을 둥근 모서리로 잘라 낸다(파일 상단 ⚠️ 참고).
overflow: hidden;
border: fox.border(1) solid fox.color(border-neutral-subtle);
border-radius: fox.radius(3);
background: fox.color(surface-neutral-default);
// 항목이 놓이는 자리. 판에는 여백을 줄 수 없어(확인 버튼이 끝까지 닿아야 한다) 여기서 준다.
&__list {
box-sizing: border-box;
padding-block: fox.padding(8);
padding-inline: fox.padding(9);
// 판이 `align-items: flex-start`라 그냥 두면 내용만큼만 넓다. 시안이 이 자리에
// `align-self: stretch`를 준다 — 판 폭이 확인 버튼 때문에 더 넓어져도 여백이 따라간다.
align-self: stretch;
// ⚠️ 확정 전 임시값 — 파일 상단 승인 목록 참고.
max-block-size: 24rem;
overflow-y: auto;
}
// 모바일 전용. 판 좌우 끝까지 닿는다(`align-self: stretch`).
&__confirm {
box-sizing: border-box;
display: flex;
justify-content: center;
align-items: center;
align-self: stretch;
flex-shrink: 0;
block-size: fox.form(height-lg);
padding-inline: fox.form(padding-lg);
gap: fox.gap(2);
border: none;
background: fox.color(button-primary-surface);
cursor: pointer;
color: fox.color(button-primary-font);
font-family: fox.font-family(body);
font-size: fox.font-size(label-lg);
font-weight: fox.font-weight(medium);
line-height: 1;
letter-spacing: -0.025em;
// 데스크톱에서는 숨긴다(파일 상단 ⚠️ 참고).
@include fox.pc {
display: none;
}
}
}
// 항목 사이 간격만 묶음의 기본값과 다르다 — 체크박스·라디오 묶음의 세로 기본이 `gap-7`(24px)
// 인데 이 시안은 `gap-5`(16px)다. 나머지(세로 배치·왼쪽 정렬)는 묶음 것과 같아서 건드리지
// 않는다. 묶음이 `className`을 여는 목적("배치 조정용")에 정확히 해당한다.
//
// 클래스 둘을 겹쳐 적는다 — 묶음의 `--vertical`과 특정도가 같아, 겹치지 않으면 파일을
// @use 하는 순서가 승부를 가른다.
.fox-checkbox-group.fox-chip-select-option__group,
.fox-radio-group.fox-chip-select-option__group {
gap: fox.gap(5);
}