@idbrnd/design-system 1.5.4 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -226,7 +226,7 @@ function InputExample() {
|
|
|
226
226
|
| `type` | `HTMLInputTypeAttribute` | `"text"` | 실제 HTML input 타입 (`text`, `password`, `email` 등) |
|
|
227
227
|
| `designType` | `"outline"` \| `"fill"` | `"outline"` | Input 컨테이너 외형 |
|
|
228
228
|
| `size` | `"default"` \| `"small"` | `"default"` | Input 높이 |
|
|
229
|
-
| `variant` | `"basic"` \| `"error"` \| `"onTyping"` \| `"typed"` \| `"onFocus"` \| `"success"` | 자동 계산 | 수동 상태 지정.
|
|
229
|
+
| `variant` | `"basic"` \| `"error"` \| `"onTyping"` \| `"typed"` \| `"onFocus"` \| `"success"` | 자동 계산 | 수동 상태 지정. `errorMessage`가 있으면 `error`가 우선 적용 |
|
|
230
230
|
| `width` | `number \| string` | `"100%"` | 루트 너비 |
|
|
231
231
|
| `value` | `string \| number \| readonly string[]` | — | **(필수)** 입력값 |
|
|
232
232
|
| `onChange` | `ChangeEventHandler<HTMLInputElement>` | — | 값 변경 핸들러 |
|
|
@@ -235,7 +235,7 @@ function InputExample() {
|
|
|
235
235
|
| `required` | `boolean` | `false` | 필수 입력 표시 및 native `required` 속성 적용 |
|
|
236
236
|
| `description` | `ReactNode \| boolean` | `false` | 하단 안내 문구. `true`면 기본 안내 문구를 사용 |
|
|
237
237
|
| `fixedDescriptionHeight` | `boolean` | `true` | helper 영역 높이 고정 여부 |
|
|
238
|
-
| `errorMessage` | `ReactNode` | 기본 에러 문구 |
|
|
238
|
+
| `errorMessage` | `ReactNode` | 기본 에러 문구 | 전달되면 에러 상태가 자동 적용되고 해당 메시지가 표시됨 |
|
|
239
239
|
| `leadingIcon` | `ReactNode` | — | 입력 필드 좌측 아이콘 |
|
|
240
240
|
| `trailingContent` | `ReactNode` | — | 입력 필드 우측 콘텐츠 |
|
|
241
241
|
| `readOnly` | `boolean` | `false` | 읽기 전용 |
|
|
@@ -245,15 +245,31 @@ function InputExample() {
|
|
|
245
245
|
유의사항:
|
|
246
246
|
|
|
247
247
|
- `variant`를 지정하지 않으면 값 존재 여부에 따라 내부적으로 `basic` 또는 `typed` 상태가 자동 적용됩니다.
|
|
248
|
-
- `
|
|
248
|
+
- `errorMessage`가 있으면 `variant` 값보다 우선해서 에러 상태가 적용됩니다. `errorMessage`가 사라지면 다시 전달된 `variant` 또는 자동 계산 상태로 돌아갑니다.
|
|
249
|
+
- `variant="error"`일 때는 `description` 대신 에러 문구가 우선 노출되며, `errorMessage`를 생략하면 기본 에러 문구가 표시됩니다.
|
|
249
250
|
- `description={true}`를 전달하면 기본 안내 문구(`2~19자 이내로 입력해 주세요.`)가 표시됩니다.
|
|
250
251
|
- `fixedDescriptionHeight={true}`면 안내/에러 문구가 없을 때도 helper 영역 높이를 유지해 레이아웃 점프를 방지합니다.
|
|
252
|
+
- helper 문구(`description`, `errorMessage`)는 기본적으로 입력창 너비에 맞춰 줄바꿈되지 않습니다. 특정 케이스에서만 줄바꿈이 필요하면 래퍼 노드에 `maxWidth`를 주거나 `<br />`를 사용하세요.
|
|
251
253
|
- `id`, `name`, `placeholder`, `autoComplete`, `maxLength`, `minLength`, `onFocus`, `onBlur` 등 대부분의 native `<input>` props도 함께 사용할 수 있습니다.
|
|
252
254
|
- `defaultValue`는 지원하지 않습니다. 반드시 `value` + `onChange`로 제어해야 합니다.
|
|
253
255
|
|
|
256
|
+
```tsx
|
|
257
|
+
<Input
|
|
258
|
+
value={value}
|
|
259
|
+
onChange={onChange}
|
|
260
|
+
errorMessage={
|
|
261
|
+
<span style={{ display: "inline-block", maxWidth: "240px", whiteSpace: "normal", wordBreak: "keep-all" }}>
|
|
262
|
+
긴 에러 문구를 이 케이스에서만 두 줄로
|
|
263
|
+
<br />
|
|
264
|
+
보여주고 싶을 때 사용할 수 있습니다.
|
|
265
|
+
</span>
|
|
266
|
+
}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
|
|
254
270
|
### SearchBar
|
|
255
271
|
|
|
256
|
-
`Enter` 입력 또는 우측 검색 버튼 클릭 시 `onSearch`를 호출합니다.
|
|
272
|
+
`Enter` 입력 또는 우측 검색 버튼 클릭 시 `onSearch`를 호출합니다. 검증 규칙과 에러 문구는 컴포넌트 내부에서 만들지 않고, 사용하는 쪽에서 직접 제어합니다. `errorMessage`가 전달되면 에러 스타일은 자동 적용됩니다.
|
|
257
273
|
|
|
258
274
|
```tsx
|
|
259
275
|
import { useState } from "react";
|
|
@@ -261,28 +277,47 @@ import { SearchBar } from "@idbrnd/design-system";
|
|
|
261
277
|
|
|
262
278
|
function SearchExample() {
|
|
263
279
|
const [keyword, setKeyword] = useState("");
|
|
280
|
+
const messages = {
|
|
281
|
+
minLength: "검색어를 2자 이상 입력해 주세요.",
|
|
282
|
+
maxLength: "검색어는 19자 이하로 입력해 주세요."
|
|
283
|
+
};
|
|
284
|
+
const searchErrorMessage =
|
|
285
|
+
keyword.length === 1
|
|
286
|
+
? messages.minLength
|
|
287
|
+
: keyword.length >= 20
|
|
288
|
+
? messages.maxLength
|
|
289
|
+
: undefined;
|
|
264
290
|
|
|
265
291
|
return (
|
|
266
292
|
<SearchBar
|
|
267
293
|
value={keyword}
|
|
268
294
|
onChange={(e) => setKeyword(e.target.value)}
|
|
269
295
|
onSearch={(value) => console.log("search:", value)}
|
|
296
|
+
errorMessage={searchErrorMessage}
|
|
270
297
|
placeholder="검색어를 입력하세요"
|
|
271
298
|
/>
|
|
272
299
|
);
|
|
273
300
|
}
|
|
274
301
|
```
|
|
275
302
|
|
|
276
|
-
| Prop
|
|
277
|
-
|
|
|
278
|
-
| `value`
|
|
279
|
-
| `onChange`
|
|
280
|
-
| `onSearch`
|
|
281
|
-
| `onClear`
|
|
282
|
-
| `size`
|
|
283
|
-
| `variant`
|
|
284
|
-
| `
|
|
285
|
-
| `
|
|
303
|
+
| Prop | 타입 | 기본값 | 설명 |
|
|
304
|
+
| -------------- | ----------------------------------------------------- | ----------- | -------------------------------------------------------- |
|
|
305
|
+
| `value` | `string` | — | **(필수)** 입력값 |
|
|
306
|
+
| `onChange` | `ChangeEventHandler` | — | **(필수)** 변경 핸들러 |
|
|
307
|
+
| `onSearch` | `(value: string) => void` | — | 검색 실행 콜백 |
|
|
308
|
+
| `onClear` | `() => void` | — | 삭제 버튼 클릭 콜백. 미지정 시 기본 동작 사용 |
|
|
309
|
+
| `size` | `"default"` \| `"small"` | `"default"` | 크기 |
|
|
310
|
+
| `variant` | `"default"` \| `"onTyping"` \| `"typed"` \| `"error"` | — | 상태 변형. `errorMessage`가 있으면 `error`가 우선 적용 |
|
|
311
|
+
| `errorMessage` | `ReactNode` | — | 전달되면 에러 상태가 자동 적용되고 해당 문구가 표시됨 |
|
|
312
|
+
| `maxLength` | `number` | `20` | native `input`의 `maxLength` 속성으로 전달 |
|
|
313
|
+
| `heading` | `boolean` | `false` | 상단 heading 표시 여부 |
|
|
314
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
315
|
+
| `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
|
|
316
|
+
|
|
317
|
+
- `SearchBar`는 UI 컴포넌트로만 동작하며, 길이 검증이나 번역 문구 생성 로직은 포함하지 않습니다.
|
|
318
|
+
- `errorMessage`가 사라지면 `variant` prop 또는 기본 자동 상태(`default`/`typed`)로 되돌아갑니다.
|
|
319
|
+
- `description`, `fixedDescriptionHeight` 등 나머지 보조 속성은 `Input`과 동일하게 사용할 수 있습니다.
|
|
320
|
+
- helper 문구를 일부 케이스에서만 줄바꿈하고 싶다면 `errorMessage` 또는 `description`에 래퍼 노드를 넘겨 `maxWidth`나 `<br />`를 적용하면 됩니다.
|
|
286
321
|
|
|
287
322
|
---
|
|
288
323
|
|
|
@@ -301,10 +336,14 @@ function CheckBoxExample() {
|
|
|
301
336
|
|
|
302
337
|
return (
|
|
303
338
|
<>
|
|
304
|
-
<CheckBox checked={checked} onChange={(value) => setChecked(value)}
|
|
339
|
+
<CheckBox checked={checked} onChange={(value) => setChecked(value)}>
|
|
340
|
+
알림 받기
|
|
341
|
+
</CheckBox>
|
|
305
342
|
|
|
306
343
|
{/* indeterminate: checked와 함께 사용 */}
|
|
307
|
-
<CheckBox checked={true} indeterminate onChange={() => {}}
|
|
344
|
+
<CheckBox checked={true} indeterminate onChange={() => {}}>
|
|
345
|
+
부분 선택
|
|
346
|
+
</CheckBox>
|
|
308
347
|
|
|
309
348
|
{/* variant / size / density */}
|
|
310
349
|
<CheckBox
|
|
@@ -313,9 +352,13 @@ function CheckBoxExample() {
|
|
|
313
352
|
density="compact"
|
|
314
353
|
checked
|
|
315
354
|
onChange={() => {}}
|
|
316
|
-
|
|
355
|
+
>
|
|
356
|
+
소형 옵션
|
|
357
|
+
</CheckBox>
|
|
317
358
|
|
|
318
|
-
<CheckBox checked disabled
|
|
359
|
+
<CheckBox checked disabled>
|
|
360
|
+
비활성 옵션
|
|
361
|
+
</CheckBox>
|
|
319
362
|
</>
|
|
320
363
|
);
|
|
321
364
|
}
|
|
@@ -326,6 +369,7 @@ function CheckBoxExample() {
|
|
|
326
369
|
| `checked` | `boolean` | — | **(필수)** 체크 상태 |
|
|
327
370
|
| `onChange` | `(checked: boolean) => void` | — | 변경 핸들러 |
|
|
328
371
|
| `indeterminate` | `boolean` | `false` | `checked={true}`와 함께 사용 시 대시(–) 아이콘 표시 |
|
|
372
|
+
| `children` | `ReactNode` | — | 체크박스 우측에 렌더링할 라벨/콘텐츠 |
|
|
329
373
|
| `variant` | `"primary"` \| `"assistive"` | `"primary"` | 색상 변형 |
|
|
330
374
|
| `size` | `"medium"` \| `"small"` | `"medium"` | 크기 |
|
|
331
375
|
| `density` | `"default"` \| `"compact"` | `"default"` | wrapper 밀도 |
|
|
@@ -336,6 +380,7 @@ function CheckBoxExample() {
|
|
|
336
380
|
|
|
337
381
|
- `indeterminate={true}`는 `checked={true}`일 때만 대시 아이콘을 표시합니다.
|
|
338
382
|
- `density="compact"`은 wrapper 크기만 줄이며, 아이콘은 `size` 기준으로 그대로 표시됩니다.
|
|
383
|
+
- `children`을 전달하면 라벨 영역까지 함께 클릭되어 체크/해제됩니다.
|
|
339
384
|
|
|
340
385
|
### Radio
|
|
341
386
|
|
|
@@ -351,18 +396,15 @@ function RadioGroupExample() {
|
|
|
351
396
|
return (
|
|
352
397
|
<>
|
|
353
398
|
{["A", "B", "C"].map((v) => (
|
|
354
|
-
<
|
|
399
|
+
<Radio
|
|
355
400
|
key={v}
|
|
356
|
-
|
|
401
|
+
name="group"
|
|
402
|
+
value={v}
|
|
403
|
+
checked={selected === v}
|
|
404
|
+
onChange={(isChecked) => isChecked && setSelected(v)}
|
|
357
405
|
>
|
|
358
|
-
<Radio
|
|
359
|
-
name="group"
|
|
360
|
-
value={v}
|
|
361
|
-
checked={selected === v}
|
|
362
|
-
onChange={(isChecked) => isChecked && setSelected(v)}
|
|
363
|
-
/>
|
|
364
406
|
Option {v}
|
|
365
|
-
</
|
|
407
|
+
</Radio>
|
|
366
408
|
))}
|
|
367
409
|
</>
|
|
368
410
|
);
|
|
@@ -375,6 +417,7 @@ function RadioGroupExample() {
|
|
|
375
417
|
| `onChange` | `(checked: boolean) => void` | — | 변경 핸들러 |
|
|
376
418
|
| `name` | `string` | — | input name 속성 |
|
|
377
419
|
| `value` | `string` | — | input value 속성 |
|
|
420
|
+
| `children` | `ReactNode` | — | 라디오 우측에 렌더링할 라벨/콘텐츠 |
|
|
378
421
|
| `variant` | `"primary"` \| `"assistive"` | `"primary"` | 색상 변형 |
|
|
379
422
|
| `size` | `"medium"` \| `"small"` | `"medium"` | 크기 |
|
|
380
423
|
| `density` | `"default"` \| `"compact"` | `"default"` | wrapper 밀도 |
|
|
@@ -385,6 +428,7 @@ function RadioGroupExample() {
|
|
|
385
428
|
|
|
386
429
|
- `name`이 같아도 자동으로 하나만 선택되지 않습니다. `checked={selected === value}` 비교로 직접 제어해야 합니다.
|
|
387
430
|
- `onChange`는 클릭 시 `true`가 전달됩니다. `isChecked && setSelected(v)` 패턴으로 true일 때만 state를 변경합니다.
|
|
431
|
+
- `children`을 전달하면 라벨 영역까지 함께 클릭되어 선택/해제됩니다.
|
|
388
432
|
|
|
389
433
|
### ToggleSwitch
|
|
390
434
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CSSProperties, type InputHTMLAttributes } from "react";
|
|
1
|
+
import { type CSSProperties, type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
2
|
export type CheckBoxVariant = "primary" | "assistive";
|
|
3
3
|
export type CheckBoxSize = "medium" | "small";
|
|
4
4
|
export type CheckBoxDensity = "default" | "compact";
|
|
@@ -9,7 +9,8 @@ export interface CheckBoxProps extends Omit<InputHTMLAttributes<HTMLInputElement
|
|
|
9
9
|
customStyle?: CSSProperties;
|
|
10
10
|
checked?: boolean;
|
|
11
11
|
indeterminate?: boolean;
|
|
12
|
+
children?: ReactNode;
|
|
12
13
|
onChange?: (checked: boolean) => void;
|
|
13
14
|
}
|
|
14
|
-
declare function CheckBox({ variant, size, density, disabled, customStyle, className, checked, indeterminate, onChange, ...rest }: CheckBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare function CheckBox({ variant, size, density, disabled, customStyle, className, checked, indeterminate, children, onChange, ...rest }: CheckBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
15
16
|
export default CheckBox;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type CSSProperties, type InputHTMLAttributes } from "react";
|
|
1
|
+
import { type CSSProperties, type InputHTMLAttributes, type ReactNode } from "react";
|
|
2
2
|
export type RadioVariant = "primary" | "assistive";
|
|
3
3
|
export type RadioSize = "medium" | "small";
|
|
4
4
|
export type RadioDensity = "default" | "compact";
|
|
@@ -7,7 +7,8 @@ export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
|
|
|
7
7
|
size?: RadioSize;
|
|
8
8
|
density?: RadioDensity;
|
|
9
9
|
customStyle?: CSSProperties;
|
|
10
|
+
children?: ReactNode;
|
|
10
11
|
onChange?: (checked: boolean) => void;
|
|
11
12
|
}
|
|
12
|
-
declare function Radio({ variant, size, density, disabled, checked, customStyle, className, onChange, ...rest }: RadioProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
declare function Radio({ variant, size, density, disabled, checked, customStyle, className, children, onChange, ...rest }: RadioProps): import("react/jsx-runtime").JSX.Element;
|
|
13
14
|
export default Radio;
|
|
@@ -41,6 +41,7 @@ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
|
|
|
41
41
|
size?: InputSize;
|
|
42
42
|
/**
|
|
43
43
|
* Input 상태 variant.
|
|
44
|
+
* `errorMessage`가 있으면 `error`가 우선 적용된다.
|
|
44
45
|
* 미지정 시 값 존재 여부에 따라 `basic`/`typed`를 자동 계산한다.
|
|
45
46
|
* 포커스 시각 상태는 CSS interaction으로 처리한다.
|
|
46
47
|
*/
|
|
@@ -91,7 +92,7 @@ export interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
|
|
|
91
92
|
fixedDescriptionHeight?: boolean;
|
|
92
93
|
/**
|
|
93
94
|
* 에러 문구.
|
|
94
|
-
* `variant
|
|
95
|
+
* 전달되면 `variant` 지정 여부와 관계없이 `error` 상태가 우선 적용된다.
|
|
95
96
|
* 미지정 시 기본 에러 문구를 표시한다.
|
|
96
97
|
*/
|
|
97
98
|
errorMessage?: ReactNode;
|