@wishket/design-system 3.6.0 → 3.8.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.
Files changed (33) hide show
  1. package/dist/ai/components/AutoCompleteList.md +86 -0
  2. package/dist/ai/components/Autocomplete.md +83 -0
  3. package/dist/ai/components/Button.md +205 -0
  4. package/dist/ai/components/Calendar.md +91 -0
  5. package/dist/ai/components/Checkbox.md +96 -0
  6. package/dist/ai/components/CheckboxCard.md +116 -0
  7. package/dist/ai/components/CheckboxList.md +102 -0
  8. package/dist/ai/components/ChoiceChip.md +127 -0
  9. package/dist/ai/components/CommentArea.md +112 -0
  10. package/dist/ai/components/FileUploader.md +146 -0
  11. package/dist/ai/components/FilterChip.md +133 -0
  12. package/dist/ai/components/FilterList.md +75 -0
  13. package/dist/ai/components/IconButton.md +97 -0
  14. package/dist/ai/components/IconButtonDropdown.md +103 -0
  15. package/dist/ai/components/InputChip.md +95 -0
  16. package/dist/ai/components/List.md +104 -0
  17. package/dist/ai/components/MultiColumnList.md +87 -0
  18. package/dist/ai/components/Radio.md +140 -0
  19. package/dist/ai/components/RadioCard.md +134 -0
  20. package/dist/ai/components/RadioList.md +150 -0
  21. package/dist/ai/components/RangeSlider.md +139 -0
  22. package/dist/ai/components/SearchField.md +117 -0
  23. package/dist/ai/components/SegmentedControl.md +131 -0
  24. package/dist/ai/components/Switch.md +114 -0
  25. package/dist/ai/components/TextButton.md +123 -0
  26. package/dist/ai/components/TextButtonDropdown.md +101 -0
  27. package/dist/ai/components/TextField.md +129 -0
  28. package/dist/ai/components/TextFieldDropdown.md +123 -0
  29. package/dist/ai/components/Textarea.md +154 -0
  30. package/dist/ai/components/index.json +324 -0
  31. package/dist/ai/tokens.json +1 -1
  32. package/dist/config/tailwind.config.js +15 -15
  33. package/package.json +5 -2
@@ -0,0 +1,133 @@
1
+ ---
2
+ id: INPUT-14
3
+ component: FilterChip
4
+ version: 0.0.3
5
+ status: draft
6
+ figma.componentKey: e8312181be77ff4c3558346242ade83baa4bb13f
7
+ ---
8
+
9
+ # 14. FilterChip
10
+
11
+ **개정 이력**
12
+
13
+ - v0.0.1 (2026.09.23): 초안 작성
14
+ - v0.0.2 (2026.10.01): 프론트매터 추가, Properties를 코드(`FilterChipProps`)·스토리북 기준으로 정리, 피그마 ↔ 코드 상태 대응표 추가, 용도를 정렬(단일)에서 필터(다중)로 확정하고 정의·4-1·4-2·Do/Don't 수정, 미결 항목을 `Z. 미결`로 분리
15
+ - v0.0.3 (2026.10.02): Anatomy의 Leading Icon "기본값" 정정(코드에 기본값 없음), Properties 안내 문구와 `children` · `onClick` · `className` 추가, 4절 제목을 "배열 규칙"으로 (#1295 리뷰 반영)
16
+
17
+ ## A. Anatomy
18
+
19
+ FilterChip은 **Container**와 **Text**로 구성되며, **Leading Icon**과 **Trailing Icon**, 선택 시 **Count Badge**를 가질 수 있습니다.
20
+
21
+ | 요소 | 필수 여부 | 설명 |
22
+ | --- | --- | --- |
23
+ | Container | 필수 | 배경·테두리를 담당하는 알약(pill) 형태의 영역. 전체가 클릭 영역 |
24
+ | Leading Icon | 선택 | 라벨 앞 아이콘. **기본값이 없어** 지정하지 않으면 나타나지 않습니다. 보통 Filter 아이콘(`medium_filter`)을 씁니다 |
25
+ | Text | 필수 | 필터 그룹의 이름 (`카테고리`, `근무 형태`) |
26
+ | Trailing Icon | 선택 | 라벨 뒤 아이콘. 목록이 열린다는 것을 알리는 Chevron |
27
+ | Count Badge | 선택 | 우측 상단의 개수 표시. 선택된 항목 수를 알립니다 |
28
+
29
+ > `FilterChip`은 **Chip의 UI만 담당**합니다. 실제 선택 목록은 `FilterList`를 children으로 따로 전달합니다.
30
+
31
+ ## B. Description
32
+
33
+ ### 1. 정의
34
+
35
+ 사용자가 여러 조건을 선택해 콘텐츠를 걸러낼 수 있도록, 필터 목록(FilterList)을 열고 적용된 조건의 개수를 보여주는 칩 형태의 트리거 컴포넌트입니다.
36
+
37
+ ### 2. 사용 시점
38
+
39
+ - 목록 상단에서 **필터 조건을 고르거나 바꿀 때** 사용합니다.
40
+ - 조건을 **여러 개 동시에** 고를 수 있을 때 사용합니다. 고른 개수는 Count Badge로 보여줍니다.
41
+ - 조건이 **적용되어 있는지 항상 보여야** 할 때 사용합니다. 조건이 하나라도 적용되면 Chip이 선택 상태로 바뀝니다.
42
+ - FilterChip을 트리거로 쓰고 **FilterList**를 띄웁니다.
43
+ - **정렬(최신순·인기순처럼 하나만 고르는 선택)에는 사용하지 않습니다.** 선택하면 항상 숫자 배지가 붙기 때문입니다.
44
+ - 선택지를 처음부터 모두 펼쳐 보여줘야 한다면 **ChoiceChip**을 사용합니다.
45
+ - FilterChip은 **낮은 시각 위계**를 가집니다.
46
+ - 너비는 **콘텐츠에 맞춰 늘어납니다.** 고정 너비를 지정하지 않습니다.
47
+
48
+ **ChoiceChip과 FilterChip**
49
+
50
+ | | ChoiceChip | FilterChip |
51
+ | --- | --- | --- |
52
+ | 역할 | 선택지 자체 | 선택 목록을 여는 **트리거** |
53
+ | 배치 | 여러 개를 펼쳐 나열 | 목록 상단에 1~3개 |
54
+ | 선택 표현 | 배경색으로 구분 | 테두리 + Count Badge |
55
+ | 함께 쓰는 것 | 없음 | FilterList |
56
+
57
+ ### 3. 키워드
58
+
59
+ FilterChip, 필터칩, 칩, Chip, 필터, 필터 조건, 다중 선택, Filter
60
+
61
+ ### 4. 배열 규칙
62
+
63
+ 1. FilterChip 사이 간격은 **최소 16**을 유지합니다. 클릭 오류를 막기 위한 기준입니다.
64
+ 2. 목록 상단에 나란히 두며, 한 줄에 **3개 이내**를 권장합니다.
65
+ 3. 한 줄을 넘으면 줄바꿈합니다. 가로 스크롤하지 않습니다.
66
+
67
+ ### 4-1. 선택과 적용
68
+
69
+ - FilterList 안에서 조건을 **여러 개** 고를 수 있습니다.
70
+ - 고른 조건은 FilterList의 **Apply(적용하기)를 눌렀을 때** 결과와 Count Badge에 반영합니다.
71
+ - 목록을 열었다가 적용하지 않고 닫으면 **직전 상태를 유지**합니다.
72
+
73
+ ### 4-2. Count Badge
74
+
75
+ - Count Badge는 **조건이 1개 이상 적용되었을 때만** 노출합니다. 0개면 숨깁니다.
76
+ - 두 자리 수를 넘어가는 경우의 표기(`99+` 등)를 정해둡니다.
77
+
78
+ ### 5. Do / Don't
79
+
80
+ **Do**
81
+
82
+ - 라벨에는 **필터 그룹 이름**을 적고(`카테고리`), 적용된 개수는 Count Badge로 보여줍니다.
83
+ - 목록을 여는 Chip에는 Chevron을 함께 표시합니다.
84
+ - Chip 사이 간격 16을 유지합니다.
85
+ - 조건이 해제되면 Count Badge도 함께 사라지게 합니다.
86
+
87
+ **Don't**
88
+
89
+ - 정렬처럼 하나만 고르는 선택에 FilterChip을 쓰지 않습니다. 의미 없는 배지 `1`이 항상 붙습니다.
90
+ - 라벨을 2줄로 표시하지 않습니다.
91
+ - 선택된 상태를 테두리 색만으로 알리지 않습니다. 굵기·텍스트 색을 함께 바꿉니다.
92
+ - 목록이 열려 있는 동안 Chip이 화면 밖으로 밀려나게 두지 않습니다.
93
+
94
+ ## C. Properties
95
+
96
+ 스토리북(코드) 이름 기준입니다. 표의 Property는 읽기 쉽게 첫 글자를 대문자로 적었고, **코드에서는 첫 글자가 소문자**입니다 (`BadgeCount` → `badgeCount`). 화면에 보이는 속성뿐 아니라 **동작용(`on…`)·개발용 prop도 적습니다.** 비고에 피그마 이름을 함께 적었습니다.
97
+
98
+ | Property | Type | Values | 비고 |
99
+ | --- | --- | --- | --- |
100
+ | Text | String | | **필수.** 칩 라벨 · 피그마 추가 |
101
+ | Children | ReactNode | | **열렸을 때 보여줄 목록(FilterList)을 넣는 자리.** `isOpen`이 True일 때 칩 아래에 나타납니다 |
102
+ | OnClick | Function | | 칩을 눌렀을 때 호출. 보통 여기서 `isOpen`을 바꿔 목록을 열고 닫습니다 · 동작용 |
103
+ | LeadingIcon | Instance | System Icon 이름 | 켜고 끄는 값이 아니라 **아이콘 이름**을 넣습니다. **기본값 없음** (스토리북 예시는 `medium_filter`) |
104
+ | TrailingIcon | Instance | System Icon 이름 | 위와 동일. 표준은 `medium_arrow_right`(`›` 모양 Chevron) — 피그마·스토리북 동일 |
105
+ | BadgeCount | String | 숫자 문자열 (예: `"3"`) | 배지에 **표시할 숫자**. `0`보다 크면 배지가 나타나고 Chip이 선택 상태가 됩니다. 피그마 `Checked = True`에 해당 |
106
+ | IsOpen | Boolean | True / False | FilterList가 열려 있는 상태. 피그마 `State = Focused`에 해당 |
107
+ | ClassName | String | | 개발용 스타일 지정 |
108
+
109
+ **피그마 ↔ 코드 대응** (피그마 Filter Chip `Checked` × `State` 6종 기준)
110
+
111
+ | 피그마 | 코드 | 모습 |
112
+ | --- | --- | --- |
113
+ | `State = Enabled` | 기본 | 회색 테두리, 검정 텍스트 |
114
+ | `State = Hovered` | 마우스 hover (자동) | 테두리만 Primary, 텍스트는 검정 유지 |
115
+ | `State = Focused` | `isOpen = true` | 테두리 + 텍스트·아이콘 Primary |
116
+ | `Checked = True` | `badgeCount`가 0보다 큼 | 2px Primary 테두리 + 연한 Primary 배경 + 우측 상단 Count Badge |
117
+
118
+ > **`Checked` prop은 없습니다.** 선택 상태는 따로 켜는 값이 아니라 **`BadgeCount`가 0보다 크면 자동으로** 선택 표시가 됩니다. 그래서 코드에서는 **배지 없이 선택된 모습을 만들 수 없습니다.** FilterChip을 필터 전용으로 쓰는 이유입니다.
119
+ >
120
+ > ```tsx
121
+ > <FilterChip text="선택 항목" leadingIcon="medium_filter" trailingIcon="medium_arrow_right"
122
+ > isOpen={isOpen} badgeCount={String(selected.length)} onClick={toggle}>
123
+ > <FilterList ... />
124
+ > </FilterChip>
125
+ > ```
126
+
127
+ ## Z. 미결 (구현하지 말 것)
128
+
129
+ > 아래는 **결정되지 않은 제안**입니다. 구현 기준은 위 A~C입니다. 결정되면 본문으로 옮기고 여기서 지웁니다.
130
+
131
+ 1. **피그마 속성 이름 정리**: 피그마 `Checked` / `State = Focused`는 코드의 `badgeCount` / `isOpen`에 해당합니다(위 대응표). 피그마 이름을 코드 기준으로 바꿀지 결정. `docs/design/mapping.md` 예외 목록에 기록됨
132
+ 2. **피그마 문서 갱신**: FilterChip은 **필터(다중 선택) 용도로 확정**했습니다(2026-10-01). 피그마 페이지의 헤더 정의("정렬 기준을 선택…")와 Policy("단일 활성화", `최신순 / 인기순` 예시)는 아직 정렬 기준이라 필터 기준으로 고쳐야 합니다
133
+ 3. **정렬용 컴포넌트**: 정렬(하나만 선택)에 무엇을 쓸지는 아직 정하지 않았습니다
@@ -0,0 +1,75 @@
1
+ ---
2
+ id: INPUT-02
3
+ component: FilterList
4
+ version: 0.0.1
5
+ status: draft
6
+ figma.componentKey: 596c307f009c0867d19ba510bdaac5112443b351
7
+ ---
8
+
9
+ # 2. FilterList
10
+
11
+ **개정 이력**
12
+
13
+ - v0.0.1 (2026.09.22): 초안 작성
14
+
15
+ ## A. Anatomy
16
+
17
+ FilterList는 **Container** 안에 **Title**과 **Checkbox List**, 하단 **Button 영역(Reset / Apply)** 으로 구성됩니다. 필요에 따라 **Select All**, **View Only**를 추가합니다.
18
+
19
+ | 요소 | 필수 여부 | 설명 |
20
+ | --- | --- | --- |
21
+ | Container | 필수 | 배경·모서리·그림자를 담당하는 영역. 팝오버/드롭다운으로 띄우는 기준 |
22
+ | Title | 필수 | 필터 그룹의 이름. 무엇을 거르는지 알려줍니다 |
23
+ | Checkbox List | 필수 | 선택 가능한 필터 조건 목록 |
24
+ | View Only | 선택 | `선택한 카테고리만 보기`. 목록을 선택된 항목만으로 줄이는 보조 옵션 |
25
+ | Select All | 선택 | Title 우측의 `전체 선택` / `선택 해제` 토글 |
26
+ | Reset Button | 필수 | 선택을 초기 상태로 되돌립니다 |
27
+ | Apply Button | 필수 | 선택한 조건을 실제 결과에 반영합니다 |
28
+
29
+ ## B. Description
30
+
31
+ ### 1. 정의
32
+
33
+ 사용자가 여러 조건을 선택하거나 해제하여, 원하는 기준으로 필터링할 수 있도록 돕는 컴포넌트입니다.
34
+
35
+ ### 2. 사용 시점
36
+
37
+ - 조건을 **여러 개 동시에** 선택해야 할 때 사용합니다.
38
+ - 조건을 고르는 즉시 반영하지 않고 **Apply로 한 번에 적용**해야 할 때 사용합니다. (결과 재조회 비용이 클 때)
39
+ - 조건이 1개만 선택되는 단일 선택이라면 **Select**를 사용합니다.
40
+ - 조건 수가 적고(대략 5개 이하) 즉시 반영해도 된다면 **Chip / Tab**을 사용합니다.
41
+ - 조건을 텍스트로 검색해 찾아야 한다면 **Autocomplete**를 사용합니다.
42
+
43
+ ### 3. 키워드
44
+
45
+ FilterList, 필터, 필터링, 조건 선택, 다중 선택, Checkbox Filter, 필터 팝오버
46
+
47
+ ### 4. Size
48
+
49
+ - 기본 너비는 **360**입니다.
50
+ - 트리거(필터 버튼) 너비와 무관하게 **FilterList 자체 너비를 유지**합니다.
51
+ - 모바일에서는 바텀시트로 전환하고 화면 너비를 100% 채웁니다.
52
+
53
+ ### 5. Do / Don't
54
+
55
+ **Do**
56
+
57
+ - Title에는 필터 그룹의 이름을 명사로 적습니다. (`카테고리`, `근무 형태`)
58
+ - 선택 항목은 사용 빈도 또는 가나다순 등 **예측 가능한 순서**로 정렬합니다.
59
+ - Apply를 누르기 전까지 결과를 바꾸지 않습니다.
60
+ - Reset은 **초기 상태**로 되돌립니다. 전체 해제가 아닙니다. (기본 선택값이 있다면 그 값으로 복원)
61
+
62
+ **Don't**
63
+
64
+ - 체크할 때마다 결과를 즉시 갱신하지 않습니다. (즉시 반영이 목적이면 Chip을 사용)
65
+ - 조건이 2~3개뿐인데 FilterList를 쓰지 않습니다.
66
+ - Apply 버튼을 비활성화한 채로 두지 않습니다. 변경이 없으면 닫기로 동작시킵니다.
67
+ - Reset과 Apply의 위치를 바꾸지 않습니다. (좌 Reset · 우 Apply 고정)
68
+
69
+ ## C. Properties
70
+
71
+ | Property | Type | Values | 비고 |
72
+ | --- | --- | --- | --- |
73
+ | Variant | Text | Label | 피그마 삭제 |
74
+ | **isAllSelected** | Boolean | True / False | 피그마 수정 |
75
+ | **isViewOnly** | Boolean | True / False | 피그마 수정 |
@@ -0,0 +1,97 @@
1
+ ---
2
+ id: INPUT-07
3
+ component: IconButton
4
+ version: 0.0.4
5
+ status: draft
6
+ figma.componentKey: 1c474f68b330cd24b07deeb4db5ecd0727cfa1c3
7
+ ---
8
+
9
+ # 7. IconButton
10
+
11
+ **개정 이력**
12
+
13
+ - v0.0.1 (2026.09.22): 초안 작성
14
+ - v0.0.2 (2026.09.30): New Badge 색상을 토큰명으로 표기 (#1293 리뷰 반영)
15
+ - v0.0.3 (2026.10.02): Properties를 코드(`IconButtonProps`)와 일치시킴 — `Outlined` → `outline`, Icon 행 제거(children 사용), Disabled 추가 (#1292 리뷰 반영)
16
+ - v0.0.4 (2026.10.16): Property 이름을 코드 이름 그대로 소문자로 통일 (피그마 전용 속성 포함)
17
+
18
+ ## A. Anatomy
19
+
20
+ IconButton은 **Icon**을 감싸는 **Container**로 구성되며, 선택적으로 **New Badge**를 가집니다.
21
+
22
+
23
+ | 요소 | 필수 여부 | 설명 |
24
+ | --------- | ----- | -------------------------------------- |
25
+ | Container | 필수 | 배경·테두리·모서리를 담당하는 영역. 터치/클릭 영역의 기준 |
26
+ | Icon | 필수 | 액션을 의미하는 아이콘. 라벨이 없으므로 의미를 단독으로 전달해야 함 |
27
+ | New Badge | 선택 | 우측 상단의 점 표시. 확인하지 않은 변화가 있음을 알림 |
28
+
29
+
30
+ ## B. Description
31
+
32
+ ### 1. 정의
33
+
34
+ 사용자가 아이콘만으로 기능을 확인할 수 있으며, 직관적이고 빠른 인터랙션을 제공하는 컴포넌트입니다.
35
+
36
+ ### 2. 사용 시점
37
+
38
+ - 아이콘만으로 **의미가 분명하게 통하는 액션**일 때 사용합니다. (좋아요, 닫기, 공유, 더보기)
39
+ - 공간이 좁아 라벨을 넣을 수 없는 자리에 사용합니다. (툴바, 카드 우측 상단, 테이블 행, 모달 닫기)
40
+ - 의미가 아이콘만으로 통하지 않으면 **Button(Leading Icon 포함)** 을 사용합니다.
41
+ - 화면의 주요 액션(Primary)에는 사용하지 않습니다. 라벨이 있는 Button을 사용합니다.
42
+ - 의미가 즉시 통하지 않는 아이콘에는 **Tooltip을 반드시 함께** 제공합니다.
43
+
44
+
45
+ | Variant | 형태 | 사용 상황 |
46
+ | ------------ | -------------- | --------------------------------- |
47
+ | **Outlined** | 흰 배경 + 1px 테두리 | 버튼임을 분명히 알려야 할 때. 카드·리스트 위의 독립 액션 |
48
+ | **Filled** | 배경·테두리 없이 아이콘만 | 이미 버튼임이 문맥으로 드러날 때. 툴바, 모달 닫기 |
49
+
50
+
51
+ ### 3. 키워드
52
+
53
+ IconButton, 아이콘 버튼, 아이콘, Icon, 뱃지, Badge, Icon Only
54
+
55
+ ### 4. Size
56
+
57
+ - Container는 **항상 정사각형**입니다. 아이콘 길이에 따라 너비가 달라지지 않습니다.
58
+ - New Badge는 **4 × 4**, `w-orange-500` 입니다.
59
+
60
+ ### 5. Do / Don't
61
+
62
+ **Do**
63
+
64
+ - 보편적으로 통용되는 아이콘만 사용합니다. (× 닫기, ⋯ 더보기, ♡ 좋아요)
65
+ - 한 화면에서 같은 아이콘은 **항상 같은 동작**을 하게 합니다.
66
+ - 대체 텍스트를 반드시 제공합니다.
67
+ - 나란히 놓이는 IconButton은 동일한 Size·Variant로 맞춥니다.
68
+ - IconButton과 Plain Tooltip을 함께 사용하는 경우, 시각적 조화를 위해 **상·하·좌·우 8 간격으로 정렬**하여 배치합니다.
69
+
70
+ **Don't**
71
+
72
+ - 의미가 모호한 아이콘을 라벨 없이 쓰지 않습니다.
73
+ - New Badge를 장식이나 강조 용도로 쓰지 않습니다. **확인하지 않은 변화**가 있을 때만 사용합니다.
74
+ - 아이콘 안에 텍스트를 넣지 않습니다.
75
+ - Container를 직사각형으로 늘리지 않습니다.
76
+
77
+ ## C. Properties
78
+
79
+ Property 이름은 **코드에 쓰는 이름 그대로**(소문자로 시작) 적었습니다. 피그마에만 있는 속성도 같은 방식으로 적고, 비고에 `피그마에만 존재`라고 표시했습니다.
80
+
81
+ | Property | Type | Values | 비고 |
82
+ | --- | --- | --- | --- |
83
+ | size | Variant | `sm` / `md` / `lg` | 24 / 36 / 50 · 피그마 Small / Medium / Large 로 수정 |
84
+ | outline | Boolean | True / False | `Outlined` 아님 · 피그마 수정 |
85
+ | hasNew | Boolean | True / False | New Badge 표시 · 피그마 이름 **New Badge** 와 통일 필요 |
86
+ | disabled | Boolean | True / False | |
87
+ | state | Variant | Enabled / Hovered / Pressed / Disabled | 피그마에만 존재. Hovered·Pressed는 마우스 동작으로 자동 처리 |
88
+
89
+
90
+ > **아이콘은 prop이 아닙니다.** `icon` 같은 prop은 코드에 없습니다. 아이콘은 **children으로** 넣습니다.
91
+ >
92
+ > ```tsx
93
+ > <IconButton size="md" outline aria-label="닫기">
94
+ > <SystemIcon name="medium_delete" />
95
+ > </IconButton>
96
+ > ```
97
+
@@ -0,0 +1,103 @@
1
+ ---
2
+ id: INPUT-21
3
+ component: IconButtonDropdown
4
+ version: 0.0.2
5
+ status: draft
6
+ ---
7
+
8
+ # 21. IconButtonDropdown
9
+
10
+ **개정 이력**
11
+
12
+ - v0.0.1 (2026.10.02): 초안 작성
13
+ - v0.0.2 (2026.10.16): 선택된 항목 표시를 코드에 맞춤 — 색만 바뀌고 굵기는 그대로 (#1299 리뷰 반영)
14
+
15
+ ## A. Anatomy
16
+
17
+ IconButtonDropdown은 **Icon Button**과, 버튼을 누르면 그 아래 8px 간격으로 열리는 **List**로 구성됩니다. 두 요소 모두 기존 컴포넌트(**IconButton**, **List**)를 그대로 씁니다.
18
+
19
+ | 요소 | 필수 여부 | 설명 |
20
+ | --- | --- | --- |
21
+ | Icon Button | 필수 | 목록을 여는 버튼. 24×24만 사용 (`size = sm`), 아이콘은 System Icon Small(14) |
22
+ | List | 조건부 | 버튼을 눌렀을 때만 표시. 최소 너비 160, 버튼 사이 간격 8px |
23
+ | List Item | 필수 | 목록의 선택지. 텍스트 + 선택적 Leading Icon(Medium 16) |
24
+ | Leading Icon | 선택 | 항목별로 지정. 없으면 텍스트만 표시 |
25
+
26
+ **항목 상태** (List 컴포넌트 기준)
27
+
28
+ | 상태 | 표시 |
29
+ | --- | --- |
30
+ | 기본 | 텍스트 `w-gray-600`, Regular |
31
+ | 선택됨 | 텍스트 `primary-500`. **굵기는 기본과 같은 Regular** (색만 바뀜) |
32
+ | Hover / 키보드 포커스 | 배경 `primary-10` |
33
+
34
+ ## B. Description
35
+
36
+ ### 1. 정의
37
+
38
+ 아이콘 클릭을 통해 드롭다운을 표시하는 선택형 컴포넌트입니다. 라벨 없이 아이콘 하나만 보여 공간을 적게 차지하고, 누르면 선택지 목록이 열립니다.
39
+
40
+ ### 2. 사용 시점
41
+
42
+ - 공간이 좁아 **텍스트 없이 아이콘만** 두고 선택지를 숨길 때 사용합니다. (카드·테이블 행의 더보기 `⋯`, 목록 상단의 정렬)
43
+ - 목록에서 **하나를 골라 즉시 반영**할 때 사용합니다. 항목을 고르면 목록이 닫힙니다.
44
+ - 현재 선택값을 버튼에 **텍스트로 보여야** 한다면 **TextButtonDropdown**을 사용합니다.
45
+ - 폼 안에서 값을 고르게 한다면 **TextFieldDropdown**을 사용합니다.
46
+ - 선택지가 2~4개로 적고 항상 보여도 된다면 **SegmentedControl**이나 **ChoiceChip**을 사용합니다.
47
+
48
+ **유형**
49
+
50
+ | 유형 | 설명 |
51
+ | --- | --- |
52
+ | **Left** | 목록의 왼쪽 끝을 버튼 왼쪽에 맞춥니다. 기본값. 화면 왼쪽에 놓인 버튼에 씁니다. |
53
+ | **Right** | 목록의 오른쪽 끝을 버튼 오른쪽에 맞춥니다. 화면·카드 오른쪽 끝에 놓인 버튼에 써서 목록이 밖으로 잘리지 않게 합니다. |
54
+ | **Disabled** | 버튼을 눌러도 목록이 열리지 않고, 아이콘이 `w-gray-300`으로 표시됩니다. 키보드(`Tab` · `Enter`)로도 열리지 않습니다. |
55
+
56
+ ### 3. 키워드
57
+
58
+ IconButtonDropdown, 아이콘 버튼 드롭다운, 드롭다운, Dropdown, 더보기, More, 옵션 메뉴
59
+
60
+ ### 4. Do / Don't
61
+
62
+ **Do**
63
+
64
+ - 아이콘은 **무엇이 열릴지 알 수 있는 것**을 씁니다. (더보기 `⋯`, 정렬, 필터)
65
+ - 버튼이 화면·카드의 오른쪽 끝에 있으면 `align = right`를 씁니다.
66
+ - 항목 텍스트는 짧은 한 줄로 씁니다. (`금액 높은 순`, `마감 임박 순`)
67
+ - Leading Icon을 쓸 거면 **모든 항목에** 넣어 텍스트 시작 위치를 맞춥니다.
68
+
69
+ **Don't**
70
+
71
+ - 항목을 너무 많이 넣지 않습니다. 목록에 높이 제한과 스크롤이 없어 항목 수만큼 길어집니다. (피그마 예시 최대 10개, Z-2)
72
+ - 버튼을 누르자마자 실행되는 동작에 쓰지 않습니다. 그 경우는 **IconButton**입니다.
73
+ - 삭제처럼 되돌릴 수 없는 동작을 항목 선택만으로 바로 실행하지 않습니다. 확인 **Dialog**를 한 번 더 띄웁니다.
74
+
75
+ ## C. Properties
76
+
77
+ 스토리북(코드) 이름 기준입니다. 표의 Property는 읽기 쉽게 첫 글자를 대문자로 적었고, **코드에서는 첫 글자가 소문자**입니다 (`SelectedItem` → `selectedItem`). 화면에 보이는 속성뿐 아니라 **동작용(`on…`)·개발용 prop도 적습니다.** 비고에 피그마 이름을 함께 적었습니다.
78
+
79
+ | Property | Type | Values | 비고 |
80
+ | --- | --- | --- | --- |
81
+ | Icon | Instance | System Icon 이름 (Small) | **필수.** 피그마에 속성 없음 · 인스턴스 교체로만 바꿈 → Instance 속성 추가 필요 |
82
+ | Items | Array | `{ key, value, leadingIcon? }` 목록 | **필수.** `value` = 항목 텍스트, `leadingIcon` = System Icon 이름 (Medium) |
83
+ | SelectedItem | Object | Items 중 하나 | **필수.** 선택된 항목을 강조 표시. 피그마는 첫 항목이 선택된 모습으로 고정 |
84
+ | Align | Variant | `left` / `right` | 기본값 `left`. 피그마 `Variant` (Left / Right) → **`Align`으로 개명 필요** |
85
+ | Size | Variant | `sm` / `md` / `lg` | **드롭다운은 `sm`(24)만 사용** (기본값). 아이콘을 감싼 **버튼 영역** 크기이며, 아이콘 크기는 `icon`에 넣는 아이콘으로 정해짐 · 코드는 `md`(36) · `lg`(50)도 받지만 쓰지 않음 |
86
+ | Disabled | Boolean | True / False | 피그마 `Disabled` · 키보드로도 열리면 안 됨. **현재 코드는 Tab 포커스 후 `Enter`로 열림 → 수정 요청 필요** |
87
+ | OnItemClick | Function | | **필수.** 항목을 고를 때 호출 · 동작용 |
88
+ | State | Variant | Enabled / Focused | 피그마에만 존재. Focused = 목록이 열린 모습. 코드는 클릭으로 자동 처리 (Z-1) |
89
+
90
+ > `ClassName` · `TestId`는 이 컴포넌트에 **없습니다.** 다른 Input 컴포넌트와 달리 바깥에서 스타일을 지정할 수 없습니다.
91
+ >
92
+ > ```tsx
93
+ > <IconButtonDropdown icon="small_more_options" align="right"
94
+ > items={items} selectedItem={selected} onItemClick={setSelected} />
95
+ > ```
96
+
97
+ ## Z. 미결 (구현하지 말 것)
98
+
99
+ > 아래는 **결정되지 않은 제안**입니다. 구현 기준은 위 A~C입니다. 결정되면 본문으로 옮기고 여기서 지웁니다.
100
+
101
+ 1. **State 중복**: 피그마 `State = Focused`는 목록이 열린 모습을 그린 것이고, 코드에는 넣는 값이 없습니다. 이름을 `Open`으로 바꿀지 검토 (키보드 포커스와 헷갈림)
102
+ 2. **목록 최대 높이 지정 필요**: List 기본값(최대 240, 스크롤)을 이 컴포넌트가 끄고 있어 항목 수만큼 길어집니다. 최대 높이는 지정하기로 했고, 값(List 기본 240을 따를지 등)은 미정
103
+ 3. **선택 표시가 필요 없는 메뉴**: 더보기(`⋯`) 메뉴는 '현재 선택값'이 없지만 `selectedItem`이 필수라 어떤 항목이든 강조됩니다. 선택 없는 메뉴 용도를 지원할지 결정
@@ -0,0 +1,95 @@
1
+ ---
2
+ id: INPUT-15
3
+ component: InputChip
4
+ version: 0.0.3
5
+ status: draft
6
+ figma.componentKey: 1c485e69144656d4ceb5c6f57615e36baf07a341
7
+ ---
8
+
9
+ # 15. InputChip
10
+
11
+ **개정 이력**
12
+
13
+ - v0.0.1 (2026.09.23): 초안 작성
14
+ - v0.0.2 (2026.10.01): 프론트매터 추가, Properties를 코드(`InputChipProps`)·스토리북 기준으로 정리, Size(높이 24·최대 너비·말줄임, 피그마 Hug/Fixed 대응) 추가, Chip 3종 비교표의 FilterChip 선택 상태 정정, 미결 항목을 `Z. 미결`로 분리
15
+ - v0.0.3 (2026.10.02): Properties 안내 문구 추가, `DeleteLabel` 기본값 예외(문자가 아닐 때 `"삭제"`) 명시, `className` 추가 (#1295 리뷰 반영)
16
+
17
+ ## A. Anatomy
18
+
19
+ InputChip은 **Container**와 **Text**, **Delete**로 구성됩니다.
20
+
21
+ | 요소 | 필수 여부 | 설명 |
22
+ | --- | --- | --- |
23
+ | Container | 필수 | 배경·모서리를 담당하는 영역 |
24
+ | Text | 필수 | 사용자가 입력하거나 선택한 값 |
25
+ | Delete | 조건부 | 값을 제거하는 × 아이콘. 삭제 동작(`onDelete`)을 연결했을 때만 나타납니다 |
26
+
27
+ ## B. Description
28
+
29
+ ### 1. 정의
30
+
31
+ 사용자가 직접 입력한 텍스트 값이 텍스트로 표시되며, 필요 시 삭제 버튼을 통해 제거할 수 있는 컴포넌트입니다.
32
+
33
+ ### 2. 사용 시점
34
+
35
+ - 사용자가 **입력하거나 선택한 값이 누적**될 때, 그 값을 하나씩 보여주기 위해 사용합니다.
36
+ - 각 값을 **개별적으로 지울 수 있어야** 할 때 사용합니다.
37
+ - **Autocomplete의 입력 필드 안**에서 선택된 항목을 표시하는 용도가 대표적입니다.
38
+ - 선택지를 **고르게 하는 것**이 목적이라면 **ChoiceChip**을 사용합니다. InputChip은 이미 정해진 값을 보여줄 뿐 선택 기능이 없습니다.
39
+ - 지울 수 없는 읽기 전용 표시라면 **Badge / Label**을 사용합니다.
40
+ - InputChip은 세 Chip 중 **가장 낮은 시각 위계**를 가집니다. 값을 보여주는 것이 목적이지 누르라고 있는 요소가 아닙니다.
41
+
42
+ **Chip 3종 비교**
43
+
44
+ | | InputChip | ChoiceChip | FilterChip |
45
+ | --- | --- | --- | --- |
46
+ | 역할 | 입력·선택된 값 **표시** | 선택지 **고르기** | 필터 목록 **열기** |
47
+ | 상호작용 | 삭제만 | 선택 / 해제 | 클릭 시 FilterList |
48
+ | 선택 상태 | 없음 | 있음 (`checked`) | 있음 (`badgeCount`가 0보다 클 때) |
49
+ | 높이 | 24 (Z-2) | 40 | 40 |
50
+
51
+ ### 3. 키워드
52
+
53
+ InputChip, 인풋칩, 칩, Chip, 태그, 입력값, 선택값, 삭제
54
+
55
+ ### 4. Size
56
+
57
+ - 높이는 **24**입니다.
58
+ - 너비는 **콘텐츠에 맞춰 늘어나며(Hug), 최대 100**입니다.
59
+ - 최대 너비를 넘는 값은 **너비 100에 고정(Fixed)** 되고 **1줄로 말줄임(`…`)** 처리합니다. 줄바꿈하지 않습니다.
60
+
61
+ > 피그마의 `Variant = Hug / Fixed`는 코드에 따로 넣는 값이 없습니다. 값이 짧으면 Hug, 100을 넘으면 Fixed가 **자동으로** 됩니다.
62
+
63
+ ### 5. Do / Don't
64
+
65
+ **Do**
66
+
67
+ - 값은 사용자가 **입력·선택한 그대로** 보여줍니다. 임의로 줄이거나 바꾸지 않습니다. (최대 너비를 넘을 때의 말줄임은 예외)
68
+ - 삭제할 수 있는 칩이라면 삭제 아이콘을 **항상 노출**합니다. Hover에만 보이게 하지 않습니다.
69
+
70
+ **Don't**
71
+
72
+ - Chip 안에 두 개 이상의 액션을 넣지 않습니다.
73
+
74
+ ## C. Properties
75
+
76
+ 스토리북(코드) 이름 기준입니다. 표의 Property는 읽기 쉽게 첫 글자를 대문자로 적었고, **코드에서는 첫 글자가 소문자**입니다 (`OnDelete` → `onDelete`). 화면에 보이는 속성뿐 아니라 **동작용(`on…`)·개발용 prop도 적습니다.** 비고에 피그마 이름을 함께 적었습니다.
77
+
78
+ | Property | Type | Values | 비고 |
79
+ | --- | --- | --- | --- |
80
+ | Children | ReactNode | | 칩에 표시할 값 · 피그마 `Label` → `Children`으로 이름 통일 |
81
+ | OnDelete | Function | | 연결하면 Delete(×) 아이콘이 나타납니다. 없으면 삭제 아이콘 없는 칩 |
82
+ | DeleteLabel | String | | 삭제 버튼을 스크린리더가 읽는 이름. 비우면 `Children`이 **문자·숫자일 때** `"{값} 삭제"`, **그 외(아이콘 등 요소)일 때** `"삭제"` · 코드에만 존재(시각 변화 없음) |
83
+ | DeleteButtonProps | Object | | 여러 칩을 방향키로 이동하게 만들 때 쓰는 개발용 값 · 코드에만 존재 |
84
+ | ClassName | String | | 개발용 스타일 지정 |
85
+
86
+ > ```tsx
87
+ > <InputChip onDelete={() => remove('React')}>React</InputChip>
88
+ > ```
89
+
90
+ ## Z. 미결 (구현하지 말 것)
91
+
92
+ > 아래는 **결정되지 않은 제안**입니다. 구현 기준은 위 A~C입니다. 결정되면 본문으로 옮기고 여기서 지웁니다.
93
+
94
+ 1. **Hovered 상태**: 피그마·코드 모두 없습니다(초안 비고 "스토리북 추가 / 피그마에 없음"). 추가할지 검토
95
+ 2. **높이 26 vs 24 (피그마 수정)**: 피그마 Input Chip은 높이 **26**, 코드는 **24**(`h-6`)입니다. 이 레포는 코드가 기준이라 문서는 24로 적었습니다. 피그마를 24로 맞출지, 26이 의도라면 디자인 변경 요청 이슈로 코드를 바꿀지 결정
@@ -0,0 +1,104 @@
1
+ ---
2
+ id: INPUT-03
3
+ component: List
4
+ version: 0.0.2
5
+ status: draft
6
+ figma.componentKey: 21008b60db4c57dfd5bee66b980d9725d9c327c8
7
+ ---
8
+
9
+ # 3. List
10
+
11
+ **개정 이력**
12
+
13
+ - v0.0.1 (2026.09.22): 초안 작성
14
+ - v0.0.2 (2026.10.02): Properties를 코드(`ListRootProps` · `ListItemProps`)와 일치시킴 — Root / Item 표 분리, `LeadingIcon` 타입 정정, `Checked` → `selected`, `text` · `canceled` · `isFocused` 추가, FilterList 속성(`isAllSelected` · `isViewOnly`) 제거 (#1292 리뷰 반영)
15
+
16
+ ## A. Anatomy
17
+
18
+ List는 **Item**을 담는 **Container**로 구성되며, 목록이 길어질 때 **Scrollbar**를 함께 사용합니다.
19
+
20
+ | 요소 | 필수 여부 | 설명 |
21
+ | --- | --- | --- |
22
+ | Container | 필수 | 배경·모서리·그림자를 담당하는 영역. 항목을 담는 기준 |
23
+ | Item | 필수 | 선택 가능한 개별 항목. Leading Icon과 Label로 구성 |
24
+ | Scrollbar | 선택 | Scrollable 유형에서 현재 위치를 알려주는 표시 |
25
+
26
+ ## B. Description
27
+
28
+ ### 1. 정의
29
+
30
+ 여러 항목을 일관된 구조로 정렬하여, 정보를 효율적으로 탐색하고 선택할 수 있도록 돕는 컴포넌트입니다.
31
+
32
+ ### 2. 사용 시점
33
+
34
+ - 같은 성격의 항목을 **동일한 구조로 나열**하고, 그중 하나를 고르게 할 때 사용합니다.
35
+ - 항목 수가 정해져 있고 전부 보여줘도 될 때는 **Fixed**, 항목이 많아 영역을 넘길 때는 **Scrollable**을 사용합니다.
36
+ - 조건을 여러 개 동시에 켜고 꺼야 한다면 **FilterList**를 사용합니다.
37
+
38
+ ### 3. 키워드
39
+
40
+ List, 리스트, 목록, 항목 목록, Option List, 선택 목록, Menu List
41
+
42
+ ### 4. Size
43
+
44
+ ### 4-1. Width
45
+
46
+ - List는 **부모 컨테이너 너비를 100% 채웁니다.**
47
+ - Item도 Container 너비를 채우며, 개별 항목의 길이에 따라 너비가 달라지지 않습니다.
48
+
49
+ ### 4-2. Overflow (라벨이 넘칠 때)
50
+
51
+ 1. Item 라벨은 **1줄로 고정**하고 넘치면 말줄임(`…`) 처리합니다.
52
+ 2. 말줄임된 항목은 **툴팁으로 전체 문구**를 제공합니다.
53
+ 3. 항목 이름이 구조적으로 길 수밖에 없다면(경로·주소 등) 말줄임 대신 List 너비를 넓히는 것을 먼저 검토합니다.
54
+
55
+ ### 5. Do / Don't
56
+
57
+ **Do**
58
+
59
+ - 항목은 가나다순·사용 빈도 등 **예측 가능한 순서**로 정렬합니다.
60
+ - Leading Icon은 항목의 **성격을 구분해야 할 때만** 사용하고, 쓸 경우 모든 항목에 동일하게 적용합니다.
61
+ - 선택된 항목(Checked)은 목록을 닫은 뒤에도 알아볼 수 있게 유지합니다.
62
+ - 선택 불가한 항목은 숨기지 말고 **Disabled로 남겨** 왜 고를 수 없는지 알 수 있게 합니다.
63
+
64
+ **Don't**
65
+
66
+ - 한 목록 안에서 아이콘이 있는 항목과 없는 항목을 섞지 않습니다.
67
+ - Item 안에 버튼·체크박스 등 별도 조작 요소를 넣지 않습니다.
68
+ - 항목 라벨을 2줄로 표시하지 않습니다.
69
+ - 항목이 3개 이하인데 Scrollable을 쓰지 않습니다.
70
+
71
+ ## C. Properties
72
+
73
+ List는 **`List.Root`(목록 컨테이너)** 와 **`List.Item`(항목)** 두 부분으로 씁니다. 표의 이름이 코드와 다르면 비고에 코드 이름을 적었습니다.
74
+
75
+ ### C-1. List.Root
76
+
77
+ | Property | Type | Values | 비고 |
78
+ | --- | --- | --- | --- |
79
+ | DisableScroll | Boolean | True / False | 코드 `disableScroll`. True면 Fixed(스크롤 없음), False면 Scrollable · 피그마 `Variant = Scrollable / Fixed`에 해당 → Boolean으로 피그마 수정 |
80
+
81
+ ### C-2. List.Item
82
+
83
+ | Property | Type | Values | 비고 |
84
+ | --- | --- | --- | --- |
85
+ | Text | String | | 코드 `text`. 항목 라벨 · 피그마 추가 |
86
+ | LeadingIcon | Instance | System Icon 이름 | 코드 `leadingIcon`. 켜고 끄는 값이 아니라 **아이콘 이름**을 넣습니다 |
87
+ | Selected | Boolean | True / False | 코드 `selected`. 선택된 항목 · 피그마 `Checked` → `Selected`로 수정 |
88
+ | Disabled | Boolean | True / False | 코드 `disabled` |
89
+ | Canceled | Boolean | True / False | 코드 `canceled`. 텍스트가 Red로 바뀜 · 피그마 `Errored`에 해당하는 것으로 보임 (Z-1) |
90
+ | IsFocused | Boolean | True / False | 코드 `isFocused`. 키보드 등으로 지목된 항목에 연한 Primary 배경 · 코드에만 존재 |
91
+ | State | Variant | Enabled / Hovered | 피그마에만 존재. Hovered는 마우스 hover로 자동 처리 |
92
+
93
+ > ```tsx
94
+ > <List.Root>
95
+ > <List.Item text="최신순" leadingIcon="medium_check" selected />
96
+ > <List.Item text="인기순" />
97
+ > </List.Root>
98
+ > ```
99
+
100
+ ## Z. 미결 (구현하지 말 것)
101
+
102
+ > 아래는 **결정되지 않은 제안**입니다. 구현 기준은 위 A~C입니다. 결정되면 본문으로 옮기고 여기서 지웁니다.
103
+
104
+ 1. **피그마 `Errored`와 코드 `canceled`**: 둘 다 텍스트를 Red로 표시하는 상태로 보입니다. 같은 것이라면 이름을 하나로 맞출지 결정