feat: FoxInput 필수 표시 · FoxChipArea 줄바꿈
둘 다 시안 ADM_ADM_102_p(5227:2035)가 요구하는데 없던 것이다. - `FoxInput`에 `requirement`를 열었다. 라벨을 FoxFormLabel로 그리면서 그 값을 넘기지 않아 `이름*`처럼 필수 별표가 붙은 시안을 그릴 수 없었다. 이미 같은 prop을 가진 `FoxSelect`와 같은 모양으로 맞췄다. - `FoxChipArea`에 `wrap`을 열었다. 스타일 주석이 "칩이 여러 줄로 흘러야 하는 자리가 나오면 시안에 먼저 추가한다"고 적어 둔 그 자리다 — 시안의 "메뉴 선택"이 칩을 두 줄로 감는다. 기본값은 종전대로 한 줄이라 기존 호출부는 그대로다. `FoxButtonGroup`의 같은 prop과 맞췄다. Co-Authored-By: Claude Opus 5
@d8a58cd67c2a5ee17215c95659c6baf6f1159a6f
--- @fox/core/components/fox-chip-area/fox-chip-area.tsx
+++ @fox/core/components/fox-chip-area/fox-chip-area.tsx
... | ... | @@ -24,6 +24,8 @@ |
| 24 | 24 |
label?: string; |
| 25 | 25 |
/** 묶음 이름 역할을 하는 요소의 id. `label`보다 우선한다 — 화면의 글자와 어긋나지 않는다. */ |
| 26 | 26 |
labelledBy?: string; |
| 27 |
+ /** 칩이 한 줄에 다 들어가지 않으면 다음 줄로 흘린다(`FoxButtonGroup`과 같은 규약). */ |
|
| 28 |
+ wrap?: boolean; |
|
| 27 | 29 |
/** `FoxChip`들. */ |
| 28 | 30 |
children?: ReactNode; |
| 29 | 31 |
/** 배치 조정용. */ |
... | ... | @@ -77,6 +79,7 @@ |
| 77 | 79 |
size, |
| 78 | 80 |
label, |
| 79 | 81 |
labelledBy, |
| 82 |
+ wrap = false, |
|
| 80 | 83 |
children, |
| 81 | 84 |
className, |
| 82 | 85 |
ref, |
... | ... | @@ -93,7 +96,7 @@ |
| 93 | 96 |
role="group" |
| 94 | 97 |
aria-label={labelledBy ? undefined : label}
|
| 95 | 98 |
aria-labelledby={labelledBy}
|
| 96 |
- className={cx("fox-chip-area", className)}
|
|
| 99 |
+ className={cx("fox-chip-area", wrap && "fox-chip-area--wrap", className)}
|
|
| 97 | 100 |
> |
| 98 | 101 |
{overrideChildren(children, overrides)}
|
| 99 | 102 |
</div> |
--- @fox/core/components/fox-input/fox-input.tsx
+++ @fox/core/components/fox-input/fox-input.tsx
... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 |
type ReactNode, |
| 11 | 11 |
} from "react"; |
| 12 | 12 |
import { cx } from "../../utils";
|
| 13 |
-import { FoxFormLabel } from "../fox-form-label";
|
|
| 13 |
+import { FoxFormLabel, type FoxFormLabelRequirement } from "../fox-form-label";
|
|
| 14 | 14 |
|
| 15 | 15 |
export type FoxInputSize = "lg" | "md" | "sm"; |
| 16 | 16 |
export type FoxInputState = "default" | "focused" | "completed" | "error" | "disabled" | "view"; |
... | ... | @@ -31,6 +31,8 @@ |
| 31 | 31 |
onChange?: (value: string, event?: ChangeEvent<HTMLInputElement>) => void; |
| 32 | 32 |
onInput?: (value: string, event: FormEvent<HTMLInputElement>) => void; |
| 33 | 33 |
label?: string; |
| 34 |
+ /** 라벨 뒤 필수·선택 표시. `label`이 없으면 의미 없다(`FoxSelect`와 같은 규약). */ |
|
| 35 |
+ requirement?: FoxFormLabelRequirement; |
|
| 34 | 36 |
/** 헬퍼 메시지. 색은 상태를 따라간다. */ |
| 35 | 37 |
message?: string; |
| 36 | 38 |
/** 헬퍼 메시지 앞 아이콘. `currentColor`로 그려야 상태 색을 따라간다. */ |
... | ... | @@ -70,6 +72,7 @@ |
| 70 | 72 |
onChange, |
| 71 | 73 |
onInput, |
| 72 | 74 |
label, |
| 75 |
+ requirement, |
|
| 73 | 76 |
message, |
| 74 | 77 |
messageIcon, |
| 75 | 78 |
icon, |
... | ... | @@ -138,7 +141,9 @@ |
| 138 | 141 |
data-state={state}
|
| 139 | 142 |
> |
| 140 | 143 |
{label && (
|
| 141 |
- <FoxFormLabel htmlFor={fieldId}>{label}</FoxFormLabel>
|
|
| 144 |
+ <FoxFormLabel htmlFor={fieldId} requirement={requirement}>
|
|
| 145 |
+ {label}
|
|
| 146 |
+ </FoxFormLabel> |
|
| 142 | 147 |
)} |
| 143 | 148 |
|
| 144 | 149 |
<div className="fox-input__box"> |
--- @fox/styles/_fox-chip-area.scss
+++ @fox/styles/_fox-chip-area.scss
... | ... | @@ -15,8 +15,8 @@ |
| 15 | 15 |
// `align-items: center`가 필요한 이유는 칩의 크기(높이)가 섞일 수 있어서다. `FoxChipArea`의 |
| 16 | 16 |
// `size`로 통일하면 섞이지 않지만, 통일하지 않고 쓰는 것도 막지 않는다. |
| 17 | 17 |
// |
| 18 |
-// ⚠️ 줄바꿈이 없다(`flex-wrap`을 주지 않는다) — 시안이 한 줄만 그린다. 폭이 모자라면 칩이 |
|
| 19 |
-// 눌리는 게 아니라 넘친다. 칩이 여러 줄로 흘러야 하는 자리가 나오면 시안에 먼저 추가한다. |
|
| 18 |
+// 기본은 한 줄이다 — 폭이 모자라면 칩이 눌리는 게 아니라 넘친다. 여러 줄로 흘러야 하는 자리는 |
|
| 19 |
+// `--wrap`을 건다(시안 ADM_ADM_102_p의 "메뉴 선택"이 칩을 두 줄로 감는다). |
|
| 20 | 20 |
|
| 21 | 21 |
@use "@fox/styles/abstracts" as fox; |
| 22 | 22 |
|
... | ... | @@ -24,4 +24,8 @@ |
| 24 | 24 |
display: inline-flex; |
| 25 | 25 |
align-items: center; |
| 26 | 26 |
gap: fox.gap(2); |
| 27 |
+ |
|
| 28 |
+ &--wrap {
|
|
| 29 |
+ flex-wrap: wrap; |
|
| 30 |
+ } |
|
| 27 | 31 |
} |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?