@idbrnd/design-system 1.9.0 → 1.10.0

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
@@ -1,6 +1,6 @@
1
1
  # @idbrnd/design-system
2
2
 
3
- ![Version](https://img.shields.io/badge/version-1.9.0-4B5FE1?style=flat-square)
3
+ ![Version](https://img.shields.io/badge/version-1.10.0-4B5FE1?style=flat-square)
4
4
  ![React](https://img.shields.io/badge/React-18.3.1-61DAFB?style=flat-square&logo=react&logoColor=white)
5
5
  ![Vite](https://img.shields.io/badge/Vite-7.3.0-646CFF?style=flat-square&logo=vite&logoColor=white)
6
6
  ![TypeScript](https://img.shields.io/badge/TypeScript-5.9.3-3178C6?style=flat-square&logo=typescript&logoColor=white)
@@ -68,6 +68,7 @@ export default function App() {
68
68
  - [ChipGroup](#chipgroup)
69
69
  - [FilterChip](#filterchip)
70
70
  - [FilterBar](#filterbar)
71
+ - [SegmentedControl](#segmentedcontrol)
71
72
  - [테이블](#테이블)
72
73
  - [TableContainer](#tablecontainer)
73
74
  - [Table](#table)
@@ -1118,6 +1119,103 @@ import { FilterBar, FilterChip } from "@idbrnd/design-system";
1118
1119
 
1119
1120
  ---
1120
1121
 
1122
+ ## SegmentedControl
1123
+
1124
+ 탭 형태로 옵션을 전환하는 컴포넌트입니다. WAI-ARIA `tablist` 패턴을 따르며 키보드(Arrow, Home, End)로 탐색할 수 있습니다.
1125
+
1126
+ ```tsx
1127
+ import { useState } from "react";
1128
+ import { SegmentedControl } from "@idbrnd/design-system";
1129
+ import type { SegmentedControlItem } from "@idbrnd/design-system";
1130
+
1131
+ const items: SegmentedControlItem[] = [
1132
+ { value: "day", label: "일" },
1133
+ { value: "week", label: "주" },
1134
+ { value: "month", label: "월" },
1135
+ ];
1136
+
1137
+ function Example() {
1138
+ const [period, setPeriod] = useState("day");
1139
+
1140
+ return <SegmentedControl items={items} value={period} onChange={setPeriod} />;
1141
+ }
1142
+ ```
1143
+
1144
+ **outlined 타입 + large 크기**
1145
+
1146
+ ```tsx
1147
+ <SegmentedControl
1148
+ type="outlined"
1149
+ size="large"
1150
+ items={items}
1151
+ value={period}
1152
+ onChange={setPeriod}
1153
+ />
1154
+ ```
1155
+
1156
+ **아이콘 + 텍스트 (`icon=true`)**
1157
+
1158
+ ```tsx
1159
+ <SegmentedControl
1160
+ icon
1161
+ items={[
1162
+ { value: "list", label: "목록", icon: <ListIcon /> },
1163
+ { value: "grid", label: "그리드", icon: <GridIcon /> },
1164
+ { value: "map", label: "지도", icon: <MapIcon /> },
1165
+ ]}
1166
+ value={view}
1167
+ onChange={setView}
1168
+ />
1169
+ ```
1170
+
1171
+ **아이콘 전용 (`variant="icon"`)**
1172
+
1173
+ ```tsx
1174
+ <SegmentedControl
1175
+ variant="icon"
1176
+ label="뷰 전환"
1177
+ items={[
1178
+ { value: "list", icon: <ListIcon />, ariaLabel: "목록 보기" },
1179
+ { value: "grid", icon: <GridIcon />, ariaLabel: "그리드 보기" },
1180
+ { value: "map", icon: <MapIcon />, ariaLabel: "지도 보기" },
1181
+ ]}
1182
+ value={view}
1183
+ onChange={setView}
1184
+ />
1185
+ ```
1186
+
1187
+ | Prop | 타입 | 기본값 | 설명 |
1188
+ | ------------- | ------------------------------------ | ---------- | ------------------------------------------------- |
1189
+ | `items` | `SegmentedControlItem[]` | — | **(필수)** 세그먼트 목록 |
1190
+ | `value` | `string` | — | **(필수)** 현재 선택된 세그먼트 값 |
1191
+ | `onChange` | `(value: string) => void` | — | 세그먼트 변경 콜백 |
1192
+ | `variant` | `"basic"` \| `"icon"` | `"basic"` | `"icon"`: 아이콘 전용 정사각형 세그먼트 |
1193
+ | `type` | `"fill"` \| `"outlined"` | `"fill"` | 컴포넌트 외형 |
1194
+ | `size` | `"small"` \| `"medium"` \| `"large"` | `"medium"` | 크기. small: 32px, medium: 40px, large: 48px |
1195
+ | `icon` | `boolean` | `false` | `variant="basic"`에서 아이콘을 텍스트와 함께 표시 |
1196
+ | `label` | `string` | — | 스크린 리더용 그룹 레이블 (`aria-label`) |
1197
+ | `customStyle` | `CSSProperties` | — | 추가 인라인 스타일 |
1198
+
1199
+ **`SegmentedControlItem`**
1200
+
1201
+ | 필드 | 타입 | 설명 |
1202
+ | ----------- | ----------- | --------------------------------------------- |
1203
+ | `value` | `string` | **(필수)** 세그먼트 고유 값 |
1204
+ | `label` | `ReactNode` | 텍스트 라벨 (`variant="basic"`에서 사용) |
1205
+ | `icon` | `ReactNode` | 아이콘 (`icon=true` 또는 `variant="icon"`) |
1206
+ | `disabled` | `boolean` | 비활성화 |
1207
+ | `ariaLabel` | `string` | `variant="icon"` 시 스크린 리더용 버튼 레이블 |
1208
+
1209
+ 유의사항:
1210
+
1211
+ - `variant="icon"` 사용 시 각 item에 `ariaLabel`을 반드시 지정해야 합니다. 미지정 시 개발 모드에서 경고가 출력됩니다.
1212
+ - `variant="basic"`에서 `icon=true`이면 세그먼트 왼쪽에 아이콘, 나머지 공간에 텍스트가 배치됩니다.
1213
+ - `value`에 해당하는 item이 없으면 슬라이딩 인디케이터가 숨겨지고, 첫 번째 활성 항목에 키보드 포커스가 유지됩니다.
1214
+ - 키보드 ArrowLeft/Right(또는 Up/Down)로 세그먼트 이동, Home/End로 첫/끝 이동을 지원합니다.
1215
+ - 비활성화된 세그먼트는 키보드 이동에서 건너뜁니다.
1216
+
1217
+ ---
1218
+
1121
1219
  ## 테이블
1122
1220
 
1123
1221
  `TableContainer`, `Table`, `Pagination` 3개의 컴포넌트로 구성됩니다. 내부적으로 [TanStack Table v8](https://tanstack.com/table/v8)을 사용하므로 `@tanstack/react-table` 패키지가 필요합니다.
@@ -1505,6 +1603,13 @@ import type {
1505
1603
  DropdownType,
1506
1604
  DropdownAlign,
1507
1605
 
1606
+ // SegmentedControl
1607
+ SegmentedControlProps,
1608
+ SegmentedControlVariant,
1609
+ SegmentedControlType,
1610
+ SegmentedControlSize,
1611
+ SegmentedControlItem,
1612
+
1508
1613
  // Table
1509
1614
  TableProps,
1510
1615
  TableVariant,
@@ -0,0 +1,27 @@
1
+ import { type CSSProperties, type ReactNode } from "react";
2
+ export type SegmentedControlVariant = "basic" | "icon";
3
+ export type SegmentedControlType = "fill" | "outlined";
4
+ export type SegmentedControlSize = "small" | "medium" | "large";
5
+ export interface SegmentedControlItem {
6
+ value: string;
7
+ label?: ReactNode;
8
+ icon?: ReactNode;
9
+ disabled?: boolean;
10
+ /** variant="icon"일 때 스크린 리더용 레이블 */
11
+ ariaLabel?: string;
12
+ }
13
+ export interface SegmentedControlProps {
14
+ variant?: SegmentedControlVariant;
15
+ type?: SegmentedControlType;
16
+ size?: SegmentedControlSize;
17
+ /** basic variant에서 icon을 함께 표시할지 여부 */
18
+ icon?: boolean;
19
+ /** 스크린 리더용 그룹 레이블 */
20
+ label?: string;
21
+ items: SegmentedControlItem[];
22
+ value: string;
23
+ onChange?: (value: string) => void;
24
+ customStyle?: CSSProperties;
25
+ }
26
+ declare function SegmentedControl({ variant, type, size, icon, label, items, value, onChange, customStyle, }: SegmentedControlProps): import("react/jsx-runtime").JSX.Element;
27
+ export default SegmentedControl;
package/dist/index.d.ts CHANGED
@@ -54,6 +54,8 @@ export type { FilterChipProps } from "./components/Chip/FilterChip/FilterChip";
54
54
  export type { FilterBarProps, FilterBarSize, } from "./components/Chip/FilterBar/FilterBar";
55
55
  export { default as Tooltip } from "./components/Tooltip/Tooltip";
56
56
  export type { TooltipProps, TooltipPosition, TooltipVariant, TooltipTrigger, TooltipContent, } from "./components/Tooltip/Tooltip.types";
57
+ export { default as SegmentedControl } from "./components/SegmentedControl/SegmentedControl";
58
+ export type { SegmentedControlProps, SegmentedControlVariant, SegmentedControlType, SegmentedControlSize, SegmentedControlItem, } from "./components/SegmentedControl/SegmentedControl";
57
59
  export { default as Table } from "./components/Table/Table";
58
60
  export type { TableProps, TableVariant, } from "./components/Table/Table.types";
59
61
  export { default as TableContainer } from "./components/Table/TableContainer";