@idbrnd/design-system 1.6.3 → 1.7.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
|
@@ -63,6 +63,11 @@ export default function App() {
|
|
|
63
63
|
- [AvatarStack](#avatarstack)
|
|
64
64
|
- [ContentBadge](#contentbadge)
|
|
65
65
|
- [StateBadge](#statebadge)
|
|
66
|
+
- [Chip](#chip)
|
|
67
|
+
- [Chip](#chip-1)
|
|
68
|
+
- [ChipGroup](#chipgroup)
|
|
69
|
+
- [FilterChip](#filterchip)
|
|
70
|
+
- [FilterBar](#filterbar)
|
|
66
71
|
- [기타](#기타)
|
|
67
72
|
- [Spinner](#spinner)
|
|
68
73
|
|
|
@@ -918,6 +923,189 @@ import { StateBadge } from "@idbrnd/design-system";
|
|
|
918
923
|
|
|
919
924
|
---
|
|
920
925
|
|
|
926
|
+
## Chip
|
|
927
|
+
|
|
928
|
+
`Chip`, `ChipGroup`, `FilterChip`, `FilterBar` 4개의 컴포넌트로 구성됩니다.
|
|
929
|
+
|
|
930
|
+
### Chip
|
|
931
|
+
|
|
932
|
+
기본 칩 버튼 컴포넌트입니다.
|
|
933
|
+
|
|
934
|
+
```tsx
|
|
935
|
+
import { Chip } from "@idbrnd/design-system";
|
|
936
|
+
|
|
937
|
+
// 기본
|
|
938
|
+
<Chip>텍스트</Chip>
|
|
939
|
+
|
|
940
|
+
// variant + selected
|
|
941
|
+
<Chip variant="fill" selected>선택됨</Chip>
|
|
942
|
+
|
|
943
|
+
// 아이콘 포함
|
|
944
|
+
<Chip
|
|
945
|
+
leadingSlot={<img src="/icon.svg" width={16} height={16} alt="" />}
|
|
946
|
+
trailingSlot={<img src="/close.svg" width={16} height={16} alt="" />}
|
|
947
|
+
>
|
|
948
|
+
검색어
|
|
949
|
+
</Chip>
|
|
950
|
+
|
|
951
|
+
// 클릭 핸들러
|
|
952
|
+
<Chip variant="outline" selected={isSelected} onClick={() => setIsSelected(p => !p)}>
|
|
953
|
+
토글
|
|
954
|
+
</Chip>
|
|
955
|
+
```
|
|
956
|
+
|
|
957
|
+
| Prop | Type | Default | Description |
|
|
958
|
+
|------|------|---------|-------------|
|
|
959
|
+
| `variant` | `"fillWeak" \| "fill" \| "outline" \| "outlineSurface"` | `"outline"` | 칩 스타일 |
|
|
960
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 크기 |
|
|
961
|
+
| `selected` | `boolean` | `false` | 선택 상태 |
|
|
962
|
+
| `disabled` | `boolean` | `false` | 비활성화 |
|
|
963
|
+
| `leadingSlot` | `ReactNode` | — | 텍스트 왼쪽 콘텐츠 |
|
|
964
|
+
| `trailingSlot` | `ReactNode` | — | 텍스트 오른쪽 콘텐츠 |
|
|
965
|
+
| `onClick` | `MouseEventHandler` | — | 클릭 핸들러 |
|
|
966
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
967
|
+
|
|
968
|
+
---
|
|
969
|
+
|
|
970
|
+
### ChipGroup
|
|
971
|
+
|
|
972
|
+
여러 `Chip`을 묶어서 표시하는 컨테이너입니다.
|
|
973
|
+
|
|
974
|
+
```tsx
|
|
975
|
+
import { Chip, ChipGroup } from "@idbrnd/design-system";
|
|
976
|
+
|
|
977
|
+
// selection — 줄바꿈 다중 선택
|
|
978
|
+
const [selected, setSelected] = useState<DropdownOption[]>([]);
|
|
979
|
+
|
|
980
|
+
function toggle(prev: DropdownOption[], item: DropdownOption) {
|
|
981
|
+
return prev.some(o => o.value === item.value)
|
|
982
|
+
? prev.filter(o => o.value !== item.value)
|
|
983
|
+
: [...prev, item];
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
<ChipGroup type="selection" leadingSlot={<span>카테고리</span>}>
|
|
987
|
+
{categories.map(({ label, value }) => (
|
|
988
|
+
<Chip
|
|
989
|
+
key={value}
|
|
990
|
+
variant="outline"
|
|
991
|
+
selected={selected.some(o => o.value === value)}
|
|
992
|
+
onClick={() => setSelected(prev => toggle(prev, { label, value }))}
|
|
993
|
+
>
|
|
994
|
+
{label}
|
|
995
|
+
</Chip>
|
|
996
|
+
))}
|
|
997
|
+
</ChipGroup>
|
|
998
|
+
|
|
999
|
+
// suggestion — 가로 드래그 캐러셀 + 그라데이션
|
|
1000
|
+
<ChipGroup type="suggestion" gradient>
|
|
1001
|
+
{suggestions.map(({ label, value }) => (
|
|
1002
|
+
<Chip key={value} variant="fillWeak">{label}</Chip>
|
|
1003
|
+
))}
|
|
1004
|
+
</ChipGroup>
|
|
1005
|
+
```
|
|
1006
|
+
|
|
1007
|
+
| Prop | Type | Default | Description |
|
|
1008
|
+
|------|------|---------|-------------|
|
|
1009
|
+
| `type` | `"selection" \| "suggestion"` | `"selection"` | `selection`: 줄바꿈, `suggestion`: 가로 드래그 캐러셀 |
|
|
1010
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 간격 크기 |
|
|
1011
|
+
| `gradient` | `boolean` | `false` | `suggestion` 타입에서 스크롤 시 양끝 그라데이션 표시 |
|
|
1012
|
+
| `leadingSlot` | `ReactNode` | — | 칩 목록 앞 텍스트/라벨 |
|
|
1013
|
+
| `leadingElementSlot` | `ReactNode` | — | 칩 목록 앞 구분선 포함 엘리먼트 |
|
|
1014
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
1015
|
+
|
|
1016
|
+
---
|
|
1017
|
+
|
|
1018
|
+
### FilterChip
|
|
1019
|
+
|
|
1020
|
+
드롭다운 옵션 선택 기능이 내장된 칩입니다. `trailingSlot`을 제외한 `Chip`의 모든 props를 지원합니다.
|
|
1021
|
+
|
|
1022
|
+
```tsx
|
|
1023
|
+
import { FilterChip } from "@idbrnd/design-system";
|
|
1024
|
+
import type { DropdownOption } from "@idbrnd/design-system";
|
|
1025
|
+
|
|
1026
|
+
const [sort, setSort] = useState<DropdownOption | undefined>();
|
|
1027
|
+
|
|
1028
|
+
// 기본
|
|
1029
|
+
<FilterChip
|
|
1030
|
+
variant="outline"
|
|
1031
|
+
options={sortOptions}
|
|
1032
|
+
selectedValue={sort?.value}
|
|
1033
|
+
onSelect={setSort}
|
|
1034
|
+
>
|
|
1035
|
+
{sort?.label ?? "정렬"}
|
|
1036
|
+
</FilterChip>
|
|
1037
|
+
|
|
1038
|
+
// showSelectedLabel — "소속 하의" 형태로 표시, 재클릭 시 선택 해제
|
|
1039
|
+
<FilterChip
|
|
1040
|
+
variant="outline"
|
|
1041
|
+
options={categoryOptions}
|
|
1042
|
+
selectedValue={category?.value}
|
|
1043
|
+
onSelect={setCategory}
|
|
1044
|
+
showSelectedLabel
|
|
1045
|
+
>
|
|
1046
|
+
소속
|
|
1047
|
+
</FilterChip>
|
|
1048
|
+
|
|
1049
|
+
// 검색형 드롭다운 + 너비 고정
|
|
1050
|
+
<FilterChip
|
|
1051
|
+
variant="outline"
|
|
1052
|
+
options={brandOptions}
|
|
1053
|
+
selectedValue={brand?.value}
|
|
1054
|
+
onSelect={setBrand}
|
|
1055
|
+
dropdownType="search"
|
|
1056
|
+
dropdownWidth={280}
|
|
1057
|
+
>
|
|
1058
|
+
{brand?.label ?? "브랜드"}
|
|
1059
|
+
</FilterChip>
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
| Prop | Type | Default | Description |
|
|
1063
|
+
|------|------|---------|-------------|
|
|
1064
|
+
| `options` | `DropdownOption[]` | (필수) | 드롭다운 옵션 목록 |
|
|
1065
|
+
| `onSelect` | `(option: DropdownOption \| undefined) => void` | (필수) | 선택/해제 콜백. 이미 선택된 옵션 재클릭 시 `undefined` 전달 |
|
|
1066
|
+
| `selectedValue` | `string` | — | 현재 선택된 옵션의 `value` |
|
|
1067
|
+
| `dropdownType` | `"basic" \| "search"` | `"basic"` | `search`: 검색 입력란 포함 |
|
|
1068
|
+
| `dropdownAlign` | `"left" \| "center"` | `"left"` | 드롭다운 정렬 방향 |
|
|
1069
|
+
| `dropdownWidth` | `number` | — | 드롭다운 너비 (px) |
|
|
1070
|
+
| `showSelectedLabel` | `boolean` | `false` | `children`을 prefix로, 선택값 label을 옆에 함께 표시 |
|
|
1071
|
+
|
|
1072
|
+
---
|
|
1073
|
+
|
|
1074
|
+
### FilterBar
|
|
1075
|
+
|
|
1076
|
+
`FilterChip`들을 가로 드래그 캐러셀로 배치하는 컨테이너입니다.
|
|
1077
|
+
|
|
1078
|
+
```tsx
|
|
1079
|
+
import { FilterBar, FilterChip } from "@idbrnd/design-system";
|
|
1080
|
+
|
|
1081
|
+
<FilterBar
|
|
1082
|
+
leadingElementSlot={<img src="/filter-icon.svg" width={24} height={24} alt="" />}
|
|
1083
|
+
trailingElementSlot={<button onClick={handleReset}>초기화</button>}
|
|
1084
|
+
>
|
|
1085
|
+
<FilterChip options={sortOptions} selectedValue={sort?.value} onSelect={setSort} showSelectedLabel>
|
|
1086
|
+
정렬
|
|
1087
|
+
</FilterChip>
|
|
1088
|
+
<FilterChip options={categoryOptions} selectedValue={category?.value} onSelect={setCategory} showSelectedLabel>
|
|
1089
|
+
소속
|
|
1090
|
+
</FilterChip>
|
|
1091
|
+
</FilterBar>
|
|
1092
|
+
|
|
1093
|
+
// verticalPadding — 패딩 O, 그라데이션 X
|
|
1094
|
+
<FilterBar verticalPadding>
|
|
1095
|
+
<FilterChip ...>정렬</FilterChip>
|
|
1096
|
+
</FilterBar>
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
| Prop | Type | Default | Description |
|
|
1100
|
+
|------|------|---------|-------------|
|
|
1101
|
+
| `size` | `"large" \| "medium" \| "small" \| "xsmall"` | `"medium"` | 칩 간격 및 슬롯 폰트 크기 |
|
|
1102
|
+
| `verticalPadding` | `boolean` | `false` | `true`: 위아래 8px 패딩, 그라데이션 없음. `false`: 그라데이션 사용 |
|
|
1103
|
+
| `leadingElementSlot` | `ReactNode` | — | 칩 목록 앞 구분선 포함 엘리먼트 |
|
|
1104
|
+
| `trailingElementSlot` | `ReactNode` | — | 칩 목록 뒤 엘리먼트 (초기화 버튼 등) |
|
|
1105
|
+
| `customStyle` | `CSSProperties` | — | 루트 엘리먼트 인라인 스타일 |
|
|
1106
|
+
|
|
1107
|
+
---
|
|
1108
|
+
|
|
921
1109
|
## 기타
|
|
922
1110
|
|
|
923
1111
|
### Spinner
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ButtonHTMLAttributes, type CSSProperties, type MouseEventHandler, type ReactNode } from "react";
|
|
2
|
+
export type ChipVariant = "fillWeak" | "fill" | "outline" | "outlineSurface";
|
|
3
|
+
export type ChipSize = "large" | "medium" | "small" | "xsmall";
|
|
4
|
+
export interface ChipProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "style" | "type" | "onClick"> {
|
|
5
|
+
onClick?: MouseEventHandler<HTMLButtonElement>;
|
|
6
|
+
variant?: ChipVariant;
|
|
7
|
+
size?: ChipSize;
|
|
8
|
+
selected?: boolean;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
leadingSlot?: ReactNode;
|
|
11
|
+
trailingSlot?: ReactNode;
|
|
12
|
+
customStyle?: CSSProperties;
|
|
13
|
+
}
|
|
14
|
+
declare function Chip({ variant, size, selected, disabled, leadingSlot, trailingSlot, customStyle, className, onClick, children, ...rest }: ChipProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export default Chip;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
export type ChipGroupType = "selection" | "suggestion";
|
|
3
|
+
export type ChipGroupSize = "large" | "medium" | "small" | "xsmall";
|
|
4
|
+
export interface ChipGroupProps {
|
|
5
|
+
/**
|
|
6
|
+
* 칩 목록의 overflow 처리 방식.
|
|
7
|
+
* - `selection`: 줄바꿈 (기본값)
|
|
8
|
+
* - `suggestion`: Embla 캐러셀 (가로 드래그 스크롤)
|
|
9
|
+
*/
|
|
10
|
+
type?: ChipGroupType;
|
|
11
|
+
/** 칩 목록 앞에 표시할 텍스트/라벨 콘텐츠 */
|
|
12
|
+
leadingSlot?: ReactNode;
|
|
13
|
+
/** 칩 목록 앞에 구분선과 함께 표시할 엘리먼트 (아이콘, 아바타 등) */
|
|
14
|
+
leadingElementSlot?: ReactNode;
|
|
15
|
+
/** 그룹 내 칩 간격 및 칩 크기 */
|
|
16
|
+
size?: ChipGroupSize;
|
|
17
|
+
/**
|
|
18
|
+
* suggestion 타입에서 스크롤 여부에 따라 양끝에 그라데이션 오버레이 표시
|
|
19
|
+
*/
|
|
20
|
+
gradient?: boolean;
|
|
21
|
+
/** 루트 엘리먼트 인라인 스타일 */
|
|
22
|
+
customStyle?: CSSProperties;
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
declare function ChipGroup({ type, leadingSlot, leadingElementSlot, size, gradient, customStyle, children, }: ChipGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export default ChipGroup;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
2
|
+
export type FilterBarSize = "large" | "medium" | "small" | "xsmall";
|
|
3
|
+
export interface FilterBarProps {
|
|
4
|
+
/** 필터 칩 목록 앞에 구분선과 함께 표시할 엘리먼트 (아이콘, 아바타 등) */
|
|
5
|
+
leadingElementSlot?: ReactNode;
|
|
6
|
+
/** 필터 칩 목록 뒤에 표시할 엘리먼트 */
|
|
7
|
+
trailingElementSlot?: ReactNode;
|
|
8
|
+
/** 칩 간격 크기 */
|
|
9
|
+
size?: FilterBarSize;
|
|
10
|
+
/**
|
|
11
|
+
* true: 위아래 8px 패딩, 그라데이션 없음
|
|
12
|
+
* false(기본값): 그라데이션 사용, 패딩 없음
|
|
13
|
+
*/
|
|
14
|
+
verticalPadding?: boolean;
|
|
15
|
+
/** 루트 엘리먼트 인라인 스타일 */
|
|
16
|
+
customStyle?: CSSProperties;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
declare function FilterBar({ leadingElementSlot, trailingElementSlot, size, verticalPadding, customStyle, children, }: FilterBarProps): import("react/jsx-runtime").JSX.Element;
|
|
20
|
+
export default FilterBar;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { DropdownAlign, DropdownOption, DropdownType } from "../../Dropdown/Dropdown.types";
|
|
2
|
+
import { type ChipProps } from "../Chip/Chip";
|
|
3
|
+
export interface FilterChipProps extends Omit<ChipProps, "onSelect" | "trailingSlot"> {
|
|
4
|
+
/** 드롭다운에 표시할 옵션 목록 */
|
|
5
|
+
options: DropdownOption[];
|
|
6
|
+
/**
|
|
7
|
+
* 옵션 선택/해제 콜백.
|
|
8
|
+
* - 새로운 옵션 선택 시: 선택된 `DropdownOption` 전달
|
|
9
|
+
* - 이미 선택된 옵션 재클릭 시: `undefined` 전달 (선택 해제)
|
|
10
|
+
*/
|
|
11
|
+
onSelect: (option: DropdownOption | undefined) => void;
|
|
12
|
+
/** 현재 선택된 옵션의 value */
|
|
13
|
+
selectedValue?: string;
|
|
14
|
+
/** 드롭다운 형태. `basic`(기본) | `search`(검색 포함) */
|
|
15
|
+
dropdownType?: DropdownType;
|
|
16
|
+
/** 옵션 정렬 방향 */
|
|
17
|
+
dropdownAlign?: DropdownAlign;
|
|
18
|
+
/** 드롭다운 목록 너비 (px) */
|
|
19
|
+
dropdownWidth?: number;
|
|
20
|
+
/**
|
|
21
|
+
* true면 선택된 옵션의 label을 children 옆에 함께 표시.
|
|
22
|
+
* ex) children="소속", 선택값="4공장 C조" → "소속 4공장 C조"
|
|
23
|
+
*/
|
|
24
|
+
showSelectedLabel?: boolean;
|
|
25
|
+
}
|
|
26
|
+
declare function FilterChip({ options, onSelect, selectedValue, dropdownType, dropdownAlign, dropdownWidth, showSelectedLabel, variant, size, disabled, selected, children, ...chipRest }: FilterChipProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export default FilterChip;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idbrnd/design-system",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"vite-plugin-lib-inject-css": "^2.2.2"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
+
"embla-carousel-react": "^8.6.0",
|
|
52
53
|
"style-dictionary": "^5.3.1"
|
|
53
54
|
}
|
|
54
55
|
}
|