// FoxTable — 시안: 통합관리자페이지 디자인시스템(KE9UILWhB8qTBe14uXUn4F) // tbl-basic (425:5781) · tbl-list (391:4283) · tbl-form (391:4389) // // 마크업 계약 (React 밖 소비자용): // // // // // // // // // // // // // //
…
…
……
// // 세 타입은 뼈대가 같고 여백·글자·기본 정렬만 다르다. 그 차이를 클래스가 아니라 커스텀 // 프로퍼티로 내려보낸다 — 칸에 `.fox-table--basic .fox-table-cell`처럼 후손 선택자를 쓰면 // 표 안에 표가 들어갔을 때 바깥 표의 규칙이 안쪽까지 덮어쓴다. 커스텀 프로퍼티는 안쪽 // 표가 자기 값으로 다시 덮으므로 그 문제가 없다. // // 좁은 화면에서 `list`는 한 줄이 카드로 접히고 `form`은 레이블이 입력 위로 올라간다 // (시안 device 축). 표 요소를 `display: block`으로 바꿔 만드는데, 그러면 표 의미가 사라져 // 스크린리더가 행·열을 읽지 못한다. 그래서 `list`의 칸은 `label`을 함께 받아 카드에서 // 열 이름을 글자로 보여 준다. // // 열 정렬 규약(디자인팀 확정, 2026-09-22) — 목록·기본 표는 **가운데가 기본**이고, **제목 열 // (emphasis)과 긴 글 열(주소·설명·내용·키워드·이메일·전화번호)만 `align="start"`** 로 왼쪽에 둔다. // 머리칸은 본문 열과 같은 정렬이다(FoxListContainer가 같은 align을 머리칸에도 준다). // // 토큰이 아닌 값: // - form 머리칸의 최소 크기 12rem×4.8rem: 시안 값이나 Figma가 변수로 export하지 // 않는다(사용자 승인). // - line-height / letter-spacing: 시안 텍스트 스타일의 값이나 Figma가 변수로 // export하지 않는다. // - border-collapse / table-layout / display 전환: 구조 규칙. @use "abstracts" as fox; .fox-table { // 타입이 칸에 내려보내는 값. 기본은 시안 basic이다. --fox-table-cell-padding-inline: #{fox.padding(5)}; --fox-table-head-padding-block: #{fox.padding(3)}; --fox-table-body-padding-block: #{fox.padding(6)}; --fox-table-head-font-size: #{fox.font-size(heading-2xsm)}; --fox-table-head-font-family: #{fox.font-family(title)}; --fox-table-head-font-weight: #{fox.font-weight(bold)}; --fox-table-head-line-height: 1.4; --fox-table-head-align: center; --fox-table-body-align: center; --fox-table-head-min-inline-size: 0; --fox-table-cell-min-block-size: 0; inline-size: 100%; border-collapse: collapse; border-block-start: fox.border(1) solid fox.color(border-neutral-subtler); // 목록표는 줄이 촘촘하다. &--list { --fox-table-body-padding-block: #{fox.padding(3)}; } // 입력표는 레이블 열이 왼쪽에 서고 여백이 넓다. &--form { --fox-table-cell-padding-inline: #{fox.padding(6)}; --fox-table-head-padding-block: #{fox.padding(6)}; --fox-table-body-padding-block: #{fox.padding(3)}; --fox-table-head-font-size: #{fox.font-size(label-md)}; --fox-table-head-font-family: #{fox.font-family(body)}; --fox-table-head-font-weight: #{fox.font-weight(medium)}; --fox-table-head-line-height: 1; --fox-table-head-align: start; --fox-table-body-align: start; // 시안 값이나 변수로 export되지 않는다 — 파일 상단 참고. --fox-table-head-min-inline-size: 12rem; --fox-table-cell-min-block-size: 4.8rem; } // 표가 무엇을 담는지 스크린리더에만 알린다. &__caption { position: absolute; inline-size: fox.border(1); block-size: fox.border(1); margin: calc(-1 * #{fox.border(1)}); padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; } // ── 좁은 화면 ───────────────────────────────────────────────────────────── @include fox.mobile { // 목록표는 한 줄이 카드가 된다. 머리행은 카드마다 열 이름이 붙으므로 감춘다. &--list { border-block-start: none; .fox-table__head { display: none; } .fox-table__body, .fox-table-row, .fox-table-cell { display: block; inline-size: 100%; } .fox-table-row { border-block-end: fox.border(1) solid fox.color(border-neutral-subtler); } .fox-table-cell { border-block-end: none; } } // 입력표는 레이블이 입력 위로 올라간다. &--form { .fox-table__body, .fox-table-row, .fox-table-cell { display: block; inline-size: 100%; } .fox-table-row { border-block-end: fox.border(1) solid fox.color(border-neutral-subtler); } .fox-table-cell { border-block-end: none; } .fox-table-cell--head { min-inline-size: 0; background: fox.color(surface-neutral-default); } } } }