File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
08-14
08-14
08-18
08-18
08-18
08-14
08-14
08-14
08-18
08-18
08-14
08-18
// FoxModal — 시안: 통합관리자페이지 디자인시스템(KE9UILWhB8qTBe14uXUn4F)
// modal (190:1136 · 섹션 391:4640)
//
// 마크업 계약 (React 밖 소비자용):
// <dialog class="fox-modal fox-modal--md">
// <div class="fox-modal__body">
// <div class="fox-modal__tit"><h2 class="fox-modal__title">타이틀</h2></div> <!-- 선택 -->
// <div class="fox-modal__contents">…</div>
// </div>
// <div class="fox-modal__foot"> <!-- 선택 -->
// <div class="fox-modal__utility">…</div> <!-- 선택 -->
// <div class="fox-modal__actions">…</div> <!-- 선택 -->
// </div>
// <button class="fox-modal__close" type="button" aria-label="닫기">…svg…</button>
// </dialog>
// `<dialog>`는 `showModal()`로 열어야 뒷배경과 초점 가두기가 생긴다.
//
// 크기 넷(sm·md·lg·full)이 모두 폭 토큰이다. 모바일에서는 넷 다 같은 폭(348px)으로
// 모이고 여백·모서리·닫기 버튼도 함께 줄어든다 — 반응형 토큰이 그렇게 정의돼 있다.
//
// 제목 줄에만 오른쪽 여백을 준다 — 닫기 버튼이 그 자리에 겹쳐 앉기 때문이다. 본문과
// 아래쪽은 그 여백이 필요 없다.
//
// 닫기 버튼은 64px 칸의 아래쪽에 아이콘을 붙인다(시안 items-end). 그래야 아이콘이 제목
// 글줄과 눈높이가 맞는다. 상자 테두리 위에 얹히도록 1px 밖으로 내민다.
//
// 토큰이 아닌 값:
// - 그림자 색: 시안이 테마 토큰이 아니라 `alpha/black10` 원시값에 직접 물려 놓았다
// (fox-carousel-button과 같은 사정).
// - 뒷배경을 덮는 방식(`::backdrop`)과 가운데 정렬: 구조 규칙.
// - line-height / letter-spacing: 시안 텍스트 스타일의 값이나 Figma가 변수로
// export하지 않는다.
@use "abstracts" as fox;
.fox-modal {
box-sizing: border-box;
// `<dialog>`는 닫혀 있을 때 브라우저가 숨기는데, `display`를 주면 그 기본값을 덮어
// 닫힌 모달이 화면에 그대로 남는다. 열렸을 때만 배치를 준다.
display: none;
flex-direction: column;
align-items: flex-start;
// `<dialog>`의 브라우저 기본 여백·테두리를 지우고 가운데에 놓는다.
max-inline-size: calc(100% - #{fox.padding(7)} * 2);
max-block-size: calc(100% - #{fox.padding(7)} * 2);
margin: auto;
padding: fox.modal(padding-default);
overflow: auto;
border: fox.border(1) solid fox.color(border-neutral-subtle);
border-radius: fox.card(radius-xlg);
background: fox.color(surface-neutral-default);
color: fox.color(font-neutral-default);
// 시안 neutral/lv3 — 그림자 둘이 겹친다.
box-shadow:
fox.shadow(location4) fox.shadow(location4) fox.shadow(blur4) 0
fox.primitive(alpha-black10),
fox.shadow(location2) fox.shadow(location2) fox.shadow(blur3) 0
fox.primitive(alpha-black10);
&::backdrop {
background: fox.color(background-dim);
}
// 닫기 버튼이 상자 모서리에 얹히므로 기준점이 필요하다.
position: relative;
&[open] {
display: flex;
}
// ── 크기 ──────────────────────────────────────────────────────────────────
&--sm {
inline-size: fox.modal(width-sm);
}
&--md {
inline-size: fox.modal(width-md);
}
&--lg {
inline-size: fox.modal(width-lg);
}
&--full {
inline-size: fox.modal(width-full);
}
// ── 본문 ──────────────────────────────────────────────────────────────────
&__body {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: fox.gap(5);
inline-size: 100%;
}
// 닫기 버튼이 오른쪽 위에 앉으므로 제목만 그만큼 비켜 준다.
&__tit {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: fox.gap(3);
inline-size: 100%;
padding-inline-end: fox.padding(8);
}
&__title {
inline-size: 100%;
margin: 0;
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;
letter-spacing: -0.025em;
word-break: break-word;
}
&__contents {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: fox.gap(5);
inline-size: 100%;
font-family: fox.font-family(body);
font-size: fox.font-size(body-md);
font-weight: fox.font-weight(regular);
line-height: 1.5;
letter-spacing: -0.025em;
}
// ── 아래쪽 ────────────────────────────────────────────────────────────────
&__foot {
display: flex;
align-items: center;
justify-content: flex-end;
gap: fox.gap(3);
inline-size: 100%;
padding-block-start: fox.padding(8);
}
// 왼편은 남는 폭을 먹어 버튼을 오른쪽 끝으로 민다.
&__utility {
display: flex;
flex: 1 0 0;
align-items: flex-start;
gap: fox.gap(3);
min-inline-size: 0;
}
&__actions {
display: flex;
flex-shrink: 0;
align-items: center;
justify-content: flex-end;
gap: fox.gap(3);
margin-inline-start: auto;
}
// ── 닫기 ──────────────────────────────────────────────────────────────────
// 시안대로 아이콘을 칸 아래쪽에 붙여 제목 글줄과 눈높이를 맞춘다.
&__close {
position: absolute;
inset-block-start: calc(-1 * #{fox.border(1)});
inset-inline-end: calc(-1 * #{fox.border(1)});
display: flex;
align-items: flex-end;
inline-size: fox.modal(btn-close);
block-size: fox.modal(btn-close);
padding: fox.padding(3);
border: none;
background: none;
color: fox.color(icon-neutral-default);
cursor: pointer;
}
&__close-icon {
display: inline-flex;
> * {
inline-size: fox.icon(5);
block-size: fox.icon(5);
}
}
}