// FoxHelperText — 시안: 통합관리자페이지 디자인시스템 Figma helper-txt // // 입력 아래 한 줄로 붙는 안내·오류 문구다. 아이콘 하나와 글자 한 덩어리로 끝난다. // // 마크업 계약 (React 밖 소비자용): //

// …아이콘 svg… // 필수 항목입니다. //

// // 아이콘은 없어도 된다(글자만 있는 자리가 많다). 계열은 `FoxAlert`와 같은 다섯 개이고, // 글리프도 같은 것을 쓰되 **굵기만 regular**다(알럿은 duotone). // // **모양 값을 여기서 새로 적지 않는다.** 시안 값이 `_form-field.scss`의 `message`· // `message-icon` 믹스인과 한 자도 다르지 않아(gap 4px · 아이콘 padding-top 2px · body/sm · // line-height 150% · letter-spacing -0.025em) 그대로 부른다. 폼 컴포넌트의 `__message`가 // 같은 믹스인을 쓰므로, 두 경로가 갈라질 수 없다. // // 유일한 차이가 `display`다 — 시안이 `inline-flex`를 준다(폼 안에서는 `flex`). 문구가 // 글줄 안에 놓일 수 있어서 폭을 내용만큼만 갖는 쪽이 맞다. // // 계열은 **글자와 아이콘의 색만** 바꾼다. `default`는 믹스인이 정한 회색 // (`font-neutral-subtle`)이고, 나머지 넷은 알럿 제목과 같은 `font-system-*`이다. 시안 확인 완료. // // 아이콘 크기도 믹스인이 정한 16px(`icon-3`)이 시안 값이다 — 폼 안 헬퍼와 같다(시안 확인 완료). // // TODO(폼 통합, 적용 후 이 주석 삭제): 폼 컴포넌트 여섯 곳의 헬퍼를 이 클래스로 모은다. // 지금은 각자 그린다 — FoxInput · FoxTextArea · FoxEmail · FoxPhoneNumber · FoxAddress가 // `__message`, FoxSelect가 `__hint`다. 모양은 `_form-field.scss`의 `message` 믹스인 한 // 곳에서 나와 어긋나지는 않지만 마크업이 여섯 벌이다. // // 옮길 때 할 일: // 1) `FoxHelperText`에 `icon` 오버라이드 prop을 더한다 — 폼은 호출부가 준 아이콘을 쓰고 // 계열 글리프를 쓰지 않는다. // 2) tsx의 `

`를 ``로 // 바꾼다. **클래스를 남기는 것이 요점이다** — 그래야 상태 색 규칙(`auto-states`의 // `:focus-within`·`:has([aria-invalid])`)이 선택자를 고치지 않고 그대로 먹는다. // 3) 각 컴포넌트 scss에서 `&__message { @include field.message; }`와 // `&__message-icon { … }` 블록을 지운다 — `.fox-helper-text`가 대신 준다. // 4) 아이콘은 `showIcon={Boolean(messageIcon)}`으로 넘겨 기존 동작(아이콘을 안 주면 안 // 그린다)을 유지한다. // // ⚠️ 옮기면 **FoxSelect만 모양이 달라진다.** 진행 전에 확인받을 것: // - 힌트 간격이 `gap 8px` · `align-items: center`에서 `4px` · `flex-start`로 바뀐다 // (helper-txt 시안 값이 이쪽이다). // - 오류일 때 아이콘 색이 `icon-system-danger`(danger-50)에서, 글자색을 상속한 // `font-system-danger`(danger-60)로 한 단계 진해진다. // // 나머지 다섯은 값이 같아 화면이 바뀌지 않는다. 앱·다른 컴포넌트가 `__message`·`__hint` // 클래스를 직접 참조하는 곳은 없다(확인 완료). @use "@fox/styles/abstracts" as fox; @use "@fox/styles/form-field" as field; .fox-helper-text { // 시안이 inline-flex다(폼 안에서는 flex) — 믹스인에 인자로 넘겨 한 번만 적는다. @include field.message($display: inline-flex); &__icon { @include field.message-icon; } // ── 계열 ──────────────────────────────────────────────────────────────────── // 글자와 아이콘의 색이 **다르다** — 글자는 `font-system-*`, 아이콘은 한 단계 진한 // `icon-system-*-strong`이다(시안 확인). 아이콘 글리프가 `fill: currentColor`라 슬롯에 // 색을 주면 그대로 입는다. // // `default`만 예외다 — 글자도 아이콘도 믹스인이 정한 회색(`font-neutral-subtle`)을 함께 // 쓰므로 따로 덮을 것이 없다. &--default { // 시안 그대로 — 믹스인에 있는 값이 전부다. } &--information { color: fox.color(font-system-information); } &--information &__icon { color: fox.color(icon-system-information-strong); } &--success { color: fox.color(font-system-success); } &--success &__icon { color: fox.color(icon-system-success-strong); } &--warning { color: fox.color(font-system-warning); } &--warning &__icon { color: fox.color(icon-system-warning-strong); } &--danger { color: fox.color(font-system-danger); } &--danger &__icon { color: fox.color(icon-system-danger-strong); } }