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-14
08-14
08-14
08-18
08-18
08-14
08-18
// FoxInput — 시안: 통합관리자페이지 디자인시스템(KE9UILWhB8qTBe14uXUn4F)
// Figma input (컴포넌트 세트 135:621)
//
// 마크업 계약 (React 밖 소비자용):
// <div class="fox-input fox-input--md">
// <label class="fox-form-label" for="…">레이블</label>
// <div class="fox-input__box">
// <input class="fox-input__field" id="…" placeholder="…">
// <button class="fox-input__clear" type="button">…svg…</button> <!-- 선택 -->
// <span class="fox-input__suffix">/ 총 39개</span> <!-- 선택 -->
// <span class="fox-input__icon">…svg…</span> <!-- 선택 -->
// </div>
// <p class="fox-input__message">…</p> <!-- 선택 -->
// </div>
//
// 상태는 두 갈래다.
// - 기본(자동): 브라우저가 판단한다. 포커스는 `:focus-within`, 비활성·읽기전용은 네이티브
// 속성, 오류는 `aria-invalid="true"`. 값이 들어찬 모습(시안의 completed)은 따로 규칙이
// 필요 없다 — 시안에서 default와 completed의 차이가 글자색뿐인데 그건 플레이스홀더와
// 입력값의 네이티브 차이다.
// - 고정: 루트에 `data-state`를 주면 그 모양으로 못박힌다. 자동 규칙은 전부 꺼진다.
// 카탈로그·스냅샷처럼 상태를 눈으로 비교해야 할 때 쓴다.
//
// 라벨·헬퍼·상자·알맹이와 두 갈래 상태는 `form-field` 믹스인이 갖는다 — 입력 계열 여섯
// 컴포넌트가 같은 값을 쓴다. 이 파일에는 FoxInput만의 것(크기 축, 아이콘, 지우기 버튼)이
// 남는다.
//
// 아이콘 크기 24/20/16은 시안이 변수를 걸지 않았지만 상자의 나머지 치수가 전부 `form/*`
// 반응형 토큰이라 아이콘도 `form-icon-*`(PC 24/20/16 · 모바일 20/16/12)에 맞춘다.
//
// 토큰이 아닌 값(FoxButton과 동일한 근거로 승인된 항목):
// - cursor / flex / appearance 관련: 구조·상호작용 규칙.
@use "abstracts" as fox;
@use "form-field" as field;
.fox-input {
@include field.root;
// 크기(높이·좌우 여백·모서리)는 아래 크기 수식어가 정한다.
&__box {
@include field.box;
}
// 글자 크기도 크기 수식어가 정한다.
&__field {
@include field.field;
}
&__icon,
&__clear {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
color: fox.color(icon-neutral-default);
}
&__icon > *,
&__clear > * {
inline-size: 100%;
block-size: 100%;
}
&__clear {
margin: 0;
padding: 0;
border: none;
background: none;
cursor: pointer;
}
// 아이콘 슬롯과 달리 정사각형으로 못박지 않는다 — 글자만큼 차지하고 줄어들지 않는다.
&__suffix {
flex-shrink: 0;
color: fox.color(font-neutral-default);
white-space: nowrap;
}
&__message {
@include field.message;
}
&__message-icon {
@include field.message-icon;
}
// ── 크기 ──────────────────────────────────────────────────────────────────
&--lg &__box {
block-size: fox.form(height-lg);
padding-inline: fox.form(padding-lg);
border-radius: fox.form(radius-lg);
}
&--lg &__field,
&--lg &__suffix {
font-size: fox.font-size(label-lg);
}
&--lg &__icon,
&--lg &__clear {
inline-size: fox.form(icon-lg);
block-size: fox.form(icon-lg);
}
&--md &__box {
block-size: fox.form(height-md);
padding-inline: fox.form(padding-md);
border-radius: fox.form(radius-md);
}
&--md &__field,
&--md &__suffix {
font-size: fox.font-size(label-md);
}
&--md &__icon,
&--md &__clear {
inline-size: fox.form(icon-md);
block-size: fox.form(icon-md);
}
&--sm &__box {
block-size: fox.form(height-sm);
padding-inline: fox.form(padding-sm);
border-radius: fox.form(radius-sm);
}
&--sm &__field,
&--sm &__suffix {
font-size: fox.font-size(label-sm);
}
&--sm &__icon,
&--sm &__clear {
inline-size: fox.form(icon-sm);
block-size: fox.form(icon-sm);
}
// 지우기 버튼은 포커스 중에만 보인다(시안에서 focused 변형에만 있다).
&__clear {
display: none;
}
&__box:focus-within &__clear {
display: inline-flex;
}
}
@include field.auto-states("fox-input");
@include field.fixed-states("fox-input") {
.fox-input[data-state="focused"] .fox-input__clear {
display: inline-flex;
}
}