@sberbusiness/triplex-next-mcp-server 0.24.0-beta1

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 (140) hide show
  1. package/README.md +124 -0
  2. package/bundle/.gitkeep +0 -0
  3. package/bundle/components/AbstractTree.md +198 -0
  4. package/bundle/components/AccordionBase.md +227 -0
  5. package/bundle/components/Alert.md +317 -0
  6. package/bundle/components/Amount.md +225 -0
  7. package/bundle/components/AmountField.md +289 -0
  8. package/bundle/components/Avatar.md +209 -0
  9. package/bundle/components/Badge.md +277 -0
  10. package/bundle/components/Body.md +167 -0
  11. package/bundle/components/Button.md +230 -0
  12. package/bundle/components/ButtonDropdown.md +159 -0
  13. package/bundle/components/ButtonIcon.md +122 -0
  14. package/bundle/components/Calendar.md +445 -0
  15. package/bundle/components/Card.md +374 -0
  16. package/bundle/components/CarouselExtended.md +250 -0
  17. package/bundle/components/Checkbox.md +126 -0
  18. package/bundle/components/CheckboxTree.md +280 -0
  19. package/bundle/components/CheckboxTreeExtended.md +321 -0
  20. package/bundle/components/CheckboxXGroup.md +68 -0
  21. package/bundle/components/CheckboxYGroup.md +67 -0
  22. package/bundle/components/Chip.md +404 -0
  23. package/bundle/components/ChipGroup.md +179 -0
  24. package/bundle/components/Col.md +221 -0
  25. package/bundle/components/CollapsableTree.md +255 -0
  26. package/bundle/components/Confirm.md +343 -0
  27. package/bundle/components/DateField.md +371 -0
  28. package/bundle/components/DatePickerExtended.md +342 -0
  29. package/bundle/components/DateRange.md +275 -0
  30. package/bundle/components/DesignTokens.md +385 -0
  31. package/bundle/components/Divider.md +196 -0
  32. package/bundle/components/DocumentNumberEdit.md +280 -0
  33. package/bundle/components/Dropdown.md +433 -0
  34. package/bundle/components/Ellipsis.md +208 -0
  35. package/bundle/components/EmptyView.md +99 -0
  36. package/bundle/components/ExpandAnimation.md +281 -0
  37. package/bundle/components/Footer.md +339 -0
  38. package/bundle/components/FormField.md +326 -0
  39. package/bundle/components/FormGroup.md +99 -0
  40. package/bundle/components/Gap.md +113 -0
  41. package/bundle/components/Header.md +280 -0
  42. package/bundle/components/HelpBox.md +154 -0
  43. package/bundle/components/IconWrapper.md +145 -0
  44. package/bundle/components/Island.md +197 -0
  45. package/bundle/components/IslandAccordion.md +230 -0
  46. package/bundle/components/IslandWidget.md +233 -0
  47. package/bundle/components/KeyDownListener.md +157 -0
  48. package/bundle/components/LightBox.md +322 -0
  49. package/bundle/components/Link.md +161 -0
  50. package/bundle/components/List.md +247 -0
  51. package/bundle/components/ListMaster.md +204 -0
  52. package/bundle/components/Loader.md +161 -0
  53. package/bundle/components/LoaderScreen.md +134 -0
  54. package/bundle/components/Marker.md +127 -0
  55. package/bundle/components/MarkerStatus.md +148 -0
  56. package/bundle/components/MediaWidth.md +169 -0
  57. package/bundle/components/MobileView.md +120 -0
  58. package/bundle/components/ModalWindow.md +308 -0
  59. package/bundle/components/MonthYearField.md +168 -0
  60. package/bundle/components/MultiselectField.md +213 -0
  61. package/bundle/components/Notification.md +233 -0
  62. package/bundle/components/NumberField.md +178 -0
  63. package/bundle/components/OrderedList.md +169 -0
  64. package/bundle/components/Overlay.md +237 -0
  65. package/bundle/components/Page.md +246 -0
  66. package/bundle/components/Pagination.md +298 -0
  67. package/bundle/components/Portal.md +119 -0
  68. package/bundle/components/Radio.md +174 -0
  69. package/bundle/components/Row.md +125 -0
  70. package/bundle/components/SMSField.md +160 -0
  71. package/bundle/components/SegmentedControl.md +235 -0
  72. package/bundle/components/SelectExtendedField.md +322 -0
  73. package/bundle/components/SelectField.md +213 -0
  74. package/bundle/components/Skeleton.md +129 -0
  75. package/bundle/components/Slider.md +157 -0
  76. package/bundle/components/SliderExtended.md +210 -0
  77. package/bundle/components/SliderRange.md +160 -0
  78. package/bundle/components/SmallInput.md +101 -0
  79. package/bundle/components/Spoiler.md +121 -0
  80. package/bundle/components/StatusTracker.md +151 -0
  81. package/bundle/components/Step.md +121 -0
  82. package/bundle/components/Stepper.md +163 -0
  83. package/bundle/components/Suggest.md +160 -0
  84. package/bundle/components/SuggestField.md +157 -0
  85. package/bundle/components/SwipeableArea.md +144 -0
  86. package/bundle/components/Table.md +199 -0
  87. package/bundle/components/Tabs.md +152 -0
  88. package/bundle/components/TabsExtended.md +273 -0
  89. package/bundle/components/TabsLine.md +189 -0
  90. package/bundle/components/Tag.md +135 -0
  91. package/bundle/components/TagColor.md +121 -0
  92. package/bundle/components/TagGroup.md +100 -0
  93. package/bundle/components/TextField.md +152 -0
  94. package/bundle/components/TextareaField.md +124 -0
  95. package/bundle/components/ThemeProvider.md +181 -0
  96. package/bundle/components/Tooltip.md +254 -0
  97. package/bundle/components/TopOverlay.md +145 -0
  98. package/bundle/components/TreeView.md +224 -0
  99. package/bundle/components/Triggers.md +121 -0
  100. package/bundle/guides/codestyle.md +205 -0
  101. package/bundle/guides/commits.md +166 -0
  102. package/bundle/guides/context.md +277 -0
  103. package/bundle/guides/stories.md +618 -0
  104. package/bundle/guides/template.md +154 -0
  105. package/bundle/guides/tests.md +301 -0
  106. package/bundle/icons.json +4156 -0
  107. package/bundle/manifest.json +796 -0
  108. package/bundle/release-notes/1.1.0.mdx +26 -0
  109. package/bundle/release-notes/1.1.1.mdx +14 -0
  110. package/bundle/release-notes/1.10.0.mdx +43 -0
  111. package/bundle/release-notes/1.11.0.mdx +19 -0
  112. package/bundle/release-notes/1.12.0.mdx +21 -0
  113. package/bundle/release-notes/1.13.0.mdx +43 -0
  114. package/bundle/release-notes/1.14.0.mdx +29 -0
  115. package/bundle/release-notes/1.15.0.mdx +56 -0
  116. package/bundle/release-notes/1.16.0.mdx +55 -0
  117. package/bundle/release-notes/1.17.0.mdx +15 -0
  118. package/bundle/release-notes/1.18.0.mdx +24 -0
  119. package/bundle/release-notes/1.19.0.mdx +48 -0
  120. package/bundle/release-notes/1.19.1.mdx +9 -0
  121. package/bundle/release-notes/1.2.0.mdx +80 -0
  122. package/bundle/release-notes/1.20.0.mdx +48 -0
  123. package/bundle/release-notes/1.21.0.mdx +66 -0
  124. package/bundle/release-notes/1.22.0.mdx +75 -0
  125. package/bundle/release-notes/1.23.0.mdx +50 -0
  126. package/bundle/release-notes/1.24.0.mdx +59 -0
  127. package/bundle/release-notes/1.25.0.mdx +52 -0
  128. package/bundle/release-notes/1.26.0.mdx +11 -0
  129. package/bundle/release-notes/1.3.0.mdx +21 -0
  130. package/bundle/release-notes/1.4.0.mdx +37 -0
  131. package/bundle/release-notes/1.5.0.mdx +24 -0
  132. package/bundle/release-notes/1.6.0.mdx +37 -0
  133. package/bundle/release-notes/1.6.1.mdx +11 -0
  134. package/bundle/release-notes/1.7.0.mdx +29 -0
  135. package/bundle/release-notes/1.8.0.mdx +38 -0
  136. package/bundle/release-notes/1.9.0.mdx +28 -0
  137. package/dist/index.d.ts +2 -0
  138. package/dist/index.js +324 -0
  139. package/dist/index.js.map +1 -0
  140. package/package.json +51 -0
@@ -0,0 +1,404 @@
1
+ ---
2
+ component: Chip
3
+ category: Chips
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [ChipGroup, Badge, IconWrapper, SelectField, MultiselectField]
7
+ tokens:
8
+ - --triplex-next-Chip-Background_Default
9
+ - --triplex-next-Chip-Background_Hover
10
+ - --triplex-next-Chip-Background_Active
11
+ - --triplex-next-Chip-Background_Disabled
12
+ - --triplex-next-Chip-Background_Selected_Default
13
+ - --triplex-next-Chip-Background_Selected_Hover
14
+ - --triplex-next-Chip-Background_Selected_Active
15
+ - --triplex-next-Chip-Background_Selected_Disabled
16
+ - --triplex-next-Chip-Color_Default
17
+ - --triplex-next-Chip-Color_Hover
18
+ - --triplex-next-Chip-Color_Active
19
+ - --triplex-next-Chip-Color_Disabled
20
+ - --triplex-next-Chip-Color_Selected_Default
21
+ - --triplex-next-Chip-Color_Selected_Hover
22
+ - --triplex-next-Chip-Color_Selected_Active
23
+ - --triplex-next-Chip-Color_Selected_Disabled
24
+ - --triplex-next-Chip-Shadow_Focus
25
+ stories: stories/Chips/Chip.stories.tsx (+ 8 других файлов)
26
+ version: "1.0"
27
+ ---
28
+
29
+ # Chip
30
+
31
+ ## Назначение
32
+
33
+ Семейство интерактивных "таблеток" (chips): прямоугольные элементы со
34
+ скруглением для выбора, сортировки, фильтрации. Включает **базовый `Chip`**
35
+ и **9 вариантов на его основе**. Чипы обычно кладутся внутрь `ChipGroup`
36
+ (горизонтальный список с gap'ами и переносом).
37
+
38
+ Базовый `Chip` — `<span role="button">`, реагирует на клавиатуру (Space
39
+ блокирует скролл), поддерживает selected/disabled, prefix/postfix иконки
40
+ и "точку уведомления" через `Badge.Dot`.
41
+
42
+ Варианты:
43
+ - **`ChipIcon`** — чип только с иконкой (иконка в prefix, пустой span в postfix для симметрии).
44
+ - **`ChipMultiselect`** — target-чип для `MultiselectField` с ClearButton / DropdownArrow.
45
+ - **`ChipSelect`** (в subfolder) — target-чип для `SelectExtendedField`.
46
+ - **`ChipOptions`** — чип с иконкой опций + clear button.
47
+ - **`ChipSort`** — чип-иконка для сортировки + selectExtendedField dropdown.
48
+ - **`ChipSuggest`** (в subfolder) — чип-input с саджестами.
49
+ - **`ChipDatePicker`** (в subfolder) — чип с календарным попапом.
50
+ - **`ChipClearButton`** — кнопка "×" для очистки выбранного.
51
+ - **`ChipDropdownArrow`** — стрелка dropdown (ротируется при opened).
52
+
53
+ Используй когда: нужен фильтр/сортировка/мультивыбор в линейном наборе.
54
+ Рекомендуется всегда внутри `ChipGroup`.
55
+ Не используй когда: нужна "метка-значок" без интерактива (бери `Badge`/`Tag`);
56
+ нужен input поля формы (бери `TextField`/`SelectField`).
57
+
58
+ ---
59
+
60
+ ## Файловая структура
61
+
62
+ ```text
63
+ src/components/Chip/
64
+ ├── Chip.tsx # Базовый, React.forwardRef
65
+ ├── ChipClearButton.tsx # ButtonIcon-обёртка с крестиком по size
66
+ ├── ChipDropdownArrow.tsx # Стрелка, rotate при rotated
67
+ ├── ChipIcon.tsx # Chip с prefix=children и postfix=<span />
68
+ ├── ChipMultiselect.tsx # MultiselectField target
69
+ ├── ChipOptions.tsx # Chip + OptionsIcon + ChipClearButton
70
+ ├── ChipSort.tsx # SelectExtendedField target с SortIcon
71
+ ├── ChipDatePicker/
72
+ │ ├── ChipDatePicker.tsx
73
+ │ ├── ChipDatePickerTarget.tsx
74
+ │ └── index.ts
75
+ ├── ChipSelect/
76
+ │ ├── ChipSelect.tsx
77
+ │ ├── ChipSelectTarget.tsx
78
+ │ └── index.ts
79
+ ├── ChipSuggest/
80
+ │ ├── ChipSuggest.tsx
81
+ │ ├── ChipSuggestTarget.tsx
82
+ │ ├── ChipSuggestDropdown.tsx
83
+ │ ├── desktop/
84
+ │ ├── types.ts
85
+ │ └── index.ts
86
+ ├── index.ts # Barrel всех вариантов
87
+ ├── styles/
88
+ │ ├── Chip.module.less # Root чипа
89
+ │ ├── ChipClearButton.module.less
90
+ │ ├── ChipDropdownArrow.module.less
91
+ │ ├── ChipOptions.module.less
92
+ │ └── ChipSuggest.module.less
93
+ └── __tests__/
94
+ ```
95
+
96
+ Особенности:
97
+ - **Нет общего enum/типов файла** — каждый чип декларирует свой интерфейс
98
+ через `extends IChipProps` / `Omit<IChipProps, ...>` / подобное.
99
+ - **`ChipGroup` — отдельный компонент** (в `src/components/ChipGroup`). Большинство
100
+ чипов получают `styles.chipGroupItem` класс, чтобы быть валидным flex-item
101
+ внутри ChipGroup.
102
+ - **`ChipIcon` делает `postfix={<span />}`** — трюк для симметричных
103
+ паддингов, так как Chip меняет padding при наличии postfix.
104
+
105
+ ---
106
+
107
+ ## Варианты и props
108
+
109
+ ### Base `Chip` — `IChipProps extends Omit<HTMLAttributes<HTMLSpanElement>, "prefix">, DataAttributes`
110
+
111
+ | Prop | Тип | Default | Описание |
112
+ |---|---|---|---|
113
+ | `size` | `EComponentSize` | `MD` | SM=28px, MD=40px, LG=56px. |
114
+ | `disabled` | `boolean` | — | Визуальный disabled + `tabIndex=-1`. |
115
+ | `selected` | `boolean` | — | "Активен" (галочка-выбор). |
116
+ | `prefix` | `ReactNode` | — | Контент слева (обычно иконка). Оборачивается в `IconWrapper`. |
117
+ | `postfix` | `ReactNode` | — | Контент справа. |
118
+ | `showNotificationIcon` | `boolean` | — | Отрисовать `Badge.Dot` в правом-верхнем углу. |
119
+ | `children` | `ReactNode` | — | Основной контент. |
120
+ | `...HTMLSpanAttributes` | — | — | Все кроме `prefix` (HTML-атрибут переопределён). |
121
+
122
+ ### `ChipIcon` — `IChipIconProps extends Omit<IChipProps, "prefix" | "postfix">`
123
+
124
+ Принимает `children` (иконку), кладёт в `prefix`, форсирует `postfix=<span/>`
125
+ для симметричных паддингов.
126
+
127
+ ### `ChipClearButton` — `IChipClearButtonProps extends Omit<IButtonIconProps, "children">`
128
+
129
+ Кнопка `<button>` с крестиком. Иконка выбирается по `size`:
130
+ - SM → `CrossStrokeSrvIcon16`
131
+ - MD → `CrossStrokeSrvIcon20`
132
+ - LG → `CrossStrokeSrvIcon24`
133
+
134
+ ### `ChipDropdownArrow`
135
+
136
+ | Prop | Тип | Описание |
137
+ |---|---|---|
138
+ | `rotated` | `boolean` | `true` → rotate(180deg). |
139
+ | `size` | `EComponentSize` | Выбирает иконку Caret 16/20/24. |
140
+
141
+ ### `ChipMultiselect` — `extends Omit<IMultiselectFieldProps, "renderTarget">`
142
+
143
+ Обёртка над `MultiselectField`, где `renderTarget` рендерит `Chip` с
144
+ `ClearButton` (если selected) или `DropdownArrow` (если нет).
145
+
146
+ | Доп. prop | Тип | Описание |
147
+ |---|---|---|
148
+ | `clearSelected` | `() => void` | Коллбек на крестик. |
149
+ | `disabled` | `boolean` | Форвардится в Chip и MultiselectField. |
150
+ | `selected` | `boolean` | Включает "выбранное" состояние + ClearButton. |
151
+ | `label` | `ReactNode` | Текст при пустом выборе. |
152
+ | `displayedValue` | `ReactNode` | Текст при выборе (fallback на label). |
153
+
154
+ ### `ChipOptions` — `extends Omit<IChipProps, "prefix" | "postfix">`
155
+
156
+ Иконка `OptionsStrokeSrvIcon24` слева. Справа ClearButton только если
157
+ selected.
158
+
159
+ | Доп. prop | Тип | Описание |
160
+ |---|---|---|
161
+ | `clearSelected` | `() => void` | Коллбек крестика. |
162
+
163
+ ### `ChipSort` — SelectExtendedField target с `SortStrokeSrvIcon24`
164
+
165
+ `selected = Boolean(value) && !isEqual(defaultValue, value)` — в отличие от
166
+ простого `value`: если текущее значение равно дефолту, чип не подсвечивается
167
+ как изменённый. **Это ключевое поведение Sort-чипа** — дефолтная сортировка
168
+ не должна выглядеть как "активный фильтр".
169
+
170
+ ### `ChipSelect`, `ChipSuggest`, `ChipDatePicker` — см. соответствующие
171
+ файлы в subfolder (компонентно большие). Смотри их `<Name>Target.tsx` для
172
+ того, как они рендерят базовый Chip.
173
+
174
+ ---
175
+
176
+ ## Ключевые особенности реализации
177
+
178
+ ### Space preventDefault в Chip
179
+
180
+ ```ts
181
+ if (isKey(event.code, "SPACE")) {
182
+ event.preventDefault();
183
+ }
184
+ onKeyDown?.(event);
185
+ ```
186
+
187
+ Блокирует скролл страницы. Не добавляет toggle-логики — это задача
188
+ потребителя. Потребители обычно через свой `onKeyDown` обрабатывают ENTER/SPACE
189
+ для активации.
190
+
191
+ ### `role="button"` + `tabIndex={disabled ? -1 : 0}`
192
+
193
+ Chip — span с ARIA-ролью button. Disabled → вне tab-order. Переопределение
194
+ `role` через `{...rest}` — возможно (например, ChipMultiselect передаёт
195
+ `role="listbox"`).
196
+
197
+ ### Notification dot = Badge.Dot
198
+
199
+ ```tsx
200
+ {showNotificationIcon && <Badge.Dot size={size} className={styles.notificationIcon} />}
201
+ ```
202
+
203
+ Тот же `Badge.Dot` из семейства Badge. Size — тот же. Позиция абсолютная,
204
+ настраивается в LESS по размерам (SM=3px/3px, MD=4px/4px, LG=6px/6px).
205
+
206
+ ### `prefix`/`postfix` через `IconWrapper`
207
+
208
+ ```tsx
209
+ <IconWrapper className={styles.prefix} disabled={Boolean(disabled)}>
210
+ {prefix}
211
+ </IconWrapper>
212
+ ```
213
+
214
+ `IconWrapper` управляет цветом иконки через `disabled`. Если внутри prefix
215
+ SVG с `paletteIndex` — подстраивается под текущую тему.
216
+
217
+ ### ChipIcon и `postfix={<span />}` — симметричные паддинги
218
+
219
+ ```tsx
220
+ <Chip {...rest} prefix={children} postfix={<span />} ref={ref} />
221
+ ```
222
+
223
+ Пустой span чтобы `styles.withPostfix` класс применился. Без этого padding-right
224
+ был бы по обычному правилу, и чип выглядел бы асимметрично. **Hack, но
225
+ намеренный.**
226
+
227
+ ### ChipMultiselect — role="listbox" на чипе
228
+
229
+ ```tsx
230
+ <Chip role="listbox" aria-expanded={opened} ...>
231
+ ```
232
+
233
+ Нестандартно — обычно listbox это UL. Это решение MultiselectField:
234
+ chip-таргет действует как listbox button. Screen reader-ы разного качества
235
+ по-разному интерпретируют. Если нужна более строгая семантика — потребителю
236
+ надо делать свой renderTarget.
237
+
238
+ ### ChipSort — `isEqual` с defaultValue
239
+
240
+ ```ts
241
+ const selected = Boolean(value) && !isEqual(defaultValue, value);
242
+ ```
243
+
244
+ Использует `lodash` (не `-es`). Не менять без общего рефакторинга импортов.
245
+ Deep equal нужен, потому что options — объекты (value, label).
246
+
247
+ ### `aria-expanded` → `.chip[aria-expanded="true"]` стили
248
+
249
+ ```less
250
+ &:active,
251
+ &[aria-expanded="true"] {
252
+ background: var(--triplex-next-Chip-Background_Active);
253
+ }
254
+ ```
255
+
256
+ CSS-селектор на атрибут. Когда dropdown раскрыт, чип выглядит "нажатым" без
257
+ дополнительного className. Умный приём.
258
+
259
+ ### `styles.chipGroupItem` — маркер для ChipGroup
260
+
261
+ Почти все варианты получают этот класс:
262
+ ```less
263
+ .chipGroupItem { display: inline-block; }
264
+ ```
265
+
266
+ ChipGroup рендерит flex-контейнер и ожидает inline-block детей. **Не
267
+ удалять класс** — иначе чипы сломают layout в ChipGroup.
268
+
269
+ ### `uniqueId()` в ChipSort для `aria-controls`
270
+
271
+ ```ts
272
+ const instanceId = useRef(uniqueId());
273
+ ```
274
+
275
+ Связывает ChipIcon (role=combobox) и dropdown. Если через useRef(uniqueId())
276
+ — значение стабильно между рендерами, но каждый инстанс получит свой id.
277
+
278
+ ---
279
+
280
+ ## Инварианты
281
+
282
+ - **`Chip` — forwardRef**, не удалять.
283
+ - **`role="button"` и `tabIndex` на Chip** — не менять семантику без
284
+ согласования.
285
+ - **`Space preventDefault`** в `handleKeyDown` — не удалять (скролл
286
+ страницы).
287
+ - **`Omit<HTMLAttributes, "prefix">`** — нужно, т.к. `prefix` — HTML
288
+ устаревший атрибут (RDFa).
289
+ - **`IconWrapper` для prefix/postfix** — не замена на div. `IconWrapper`
290
+ управляет цветом иконок по disabled.
291
+ - **`styles.chipGroupItem`** — на каждом root-элементе вариантов чипов.
292
+ Ожидается ChipGroup'ом.
293
+ - **`ChipIcon` → `postfix={<span />}`** — не удалять span. Нужен для
294
+ симметричных паддингов.
295
+ - **`ChipSort` — `!isEqual(defaultValue, value)` для selected** — не
296
+ упрощать до `Boolean(value)`. Это UX-правило (дефолт не "активный фильтр").
297
+ - **`Badge.Dot` для notification icon** — не заменять на произвольный
298
+ элемент, размер синхронизирован с size чипа.
299
+ - **Базовые токены `--triplex-next-Chip-*`** — не дублировать для вариантов.
300
+ Варианты используют одни и те же токены (цвета).
301
+ - **Варианты (ChipSelect/ChipSuggest/ChipDatePicker) обёртки над
302
+ SelectExtendedField/SuggestField/подобными** — не инвертировать зависимость
303
+ (не Chip оборачивает Field, а наоборот).
304
+ - **`lodash` (не `-es`) в ChipSort** — исторически, не менять точечно.
305
+
306
+ ---
307
+
308
+ ## Accessibility
309
+
310
+ - **`role="button"`** на Chip — работает с screen reader'ом как кнопка.
311
+ - **`tabIndex` управляется через disabled** — disabled чип вне tab-order.
312
+ - **`aria-expanded`** на Chip в ChipMultiselect / ChipSort — для dropdown
313
+ состояния. Screen reader озвучит "раскрыто"/"свёрнуто".
314
+ - **`aria-controls`** в ChipSort связывает чип с dropdown через
315
+ `instanceId`.
316
+ - **Клавиатура**:
317
+ - Space — preventDefault (против скролла), потребитель обрабатывает
318
+ активацию.
319
+ - Enter — bubble up, потребитель вешает handler через `onKeyDown`.
320
+ - ChipMultiselect/ChipSort — свои `handleKeyDown` обрабатывают Enter/Space
321
+ для toggle opened.
322
+ - **Notification icon `Badge.Dot`** — чисто визуальный, без ARIA. Если
323
+ означает "есть новые" — потребитель должен добавить `aria-label` на
324
+ Chip (например, "Фильтр, есть новые").
325
+ - **Nested interactive**: ClearButton внутри Chip — кнопка в "кнопке".
326
+ Решается `event.stopPropagation()` на ClearButton, чтобы клик на крестик
327
+ не триггерил родительский toggle.
328
+
329
+ ---
330
+
331
+ ## Дизайн-токены
332
+
333
+ **Базовые (разделяемые всеми вариантами):**
334
+ ```
335
+ --triplex-next-Chip-Background_Default
336
+ --triplex-next-Chip-Background_Hover
337
+ --triplex-next-Chip-Background_Active
338
+ --triplex-next-Chip-Background_Disabled
339
+ --triplex-next-Chip-Color_Default
340
+ --triplex-next-Chip-Color_Hover
341
+ --triplex-next-Chip-Color_Active
342
+ --triplex-next-Chip-Color_Disabled
343
+ --triplex-next-Chip-Shadow_Focus # focus-visible
344
+ ```
345
+
346
+ **Selected (включённое состояние):**
347
+ ```
348
+ --triplex-next-Chip-Background_Selected_Default
349
+ --triplex-next-Chip-Background_Selected_Hover
350
+ --triplex-next-Chip-Background_Selected_Active
351
+ --triplex-next-Chip-Background_Selected_Disabled
352
+ --triplex-next-Chip-Color_Selected_Default
353
+ --triplex-next-Chip-Color_Selected_Hover
354
+ --triplex-next-Chip-Color_Selected_Active
355
+ --triplex-next-Chip-Color_Selected_Disabled
356
+ ```
357
+
358
+ Размеры (высоты, radius, padding, font-size) — hardcoded в LESS по size-
359
+ классам, не токенизированы.
360
+
361
+ ---
362
+
363
+ ## Связанные компоненты
364
+
365
+ - `ChipGroup` (`src/components/ChipGroup`) — контейнер для чипов с
366
+ горизонтальным скроллом/переносом.
367
+ - `Badge` (`src/components/Badge`) — notification dot (`Badge.Dot`) —
368
+ та же реализация.
369
+ - `IconWrapper` (`src/components/IconWrapper`) — обёртка для prefix/postfix
370
+ иконок.
371
+ - `ButtonIcon` (`src/components/Button`) — основа для `ChipClearButton`.
372
+ - `MultiselectField`, `SelectExtendedField`, `SuggestField` — варианты
373
+ чипов обёртки над этими field'ами.
374
+ - `EComponentSize`, `createSizeToClassNameMap` — общий паттерн size'ов.
375
+
376
+ ---
377
+
378
+ ## Stories
379
+
380
+ Отдельная story-файл для каждого варианта:
381
+
382
+ | File | Variant |
383
+ |---|---|
384
+ | `stories/Chips/Chip.stories.tsx` | Base Chip |
385
+ | `stories/Chips/ChipIcon.stories.tsx` | ChipIcon |
386
+ | `stories/Chips/ChipGroup.stories.tsx` | ChipGroup (отдельный компонент) |
387
+ | `stories/Chips/ChipMultiselect.stories.tsx` | ChipMultiselect |
388
+ | `stories/Chips/ChipOptions.stories.tsx` | ChipOptions |
389
+ | `stories/Chips/ChipSelect.stories.tsx` | ChipSelect |
390
+ | `stories/Chips/ChipSort.stories.tsx` | ChipSort |
391
+ | `stories/Chips/ChipSuggest.stories.tsx` | ChipSuggest |
392
+ | `stories/Chips/ChipDatePicker.stories.tsx` | ChipDatePicker |
393
+
394
+ Примеры в `stories/Chips/examples/<Name>/`. Typical: `Default`, `Playground`,
395
+ `Sizes`, специфичные для варианта (`States`, `WithNotificationIcon`,
396
+ `WithPrefixAndPostfix` для base Chip).
397
+
398
+ ---
399
+
400
+ ## История изменений
401
+
402
+ | Дата | Изменение |
403
+ |---|---|
404
+ | 2026-04-18 | Создан документ |
@@ -0,0 +1,179 @@
1
+ ---
2
+ component: ChipGroup
3
+ category: Chips
4
+ figma-node: ""
5
+ figma-file: ""
6
+ related: [Chip, TagGroup]
7
+ tokens: []
8
+ stories: stories/Chips/ChipGroup.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # ChipGroup
13
+
14
+ ## Назначение
15
+
16
+ Контейнер для набора `Chip` (и любых `Chip*`-вариантов). Управляет
17
+ расстоянием между чипами (`gap` по size), способом переноса (`flex-wrap`)
18
+ или горизонтальным скроллом (`oneLine`), и скрывает скроллбар.
19
+
20
+ Это **layout-only** обёртка: не передаёт `size` детям, не синхронизирует
21
+ disabled/selected — только стайлит контейнер. Размер чипов потребитель
22
+ задаёт на каждом Chip индивидуально (но обычно ставит тот же, что в
23
+ ChipGroup).
24
+
25
+ Используй когда: есть 2+ чипа в одной строке или блоке фильтров.
26
+ Не используй когда: один чип (без обёртки он тоже валиден); нужен вертикальный
27
+ список (ChipGroup только горизонтальный); нужны теги-метки — бери `TagGroup`.
28
+
29
+ ---
30
+
31
+ ## Файловая структура
32
+
33
+ ```text
34
+ src/components/ChipGroup/
35
+ ├── ChipGroup.tsx # React.forwardRef
36
+ ├── index.ts # Barrel
37
+ └── styles/ChipGroup.module.less # flex + oneLine (hidden scrollbar) / multiLine (wrap)
38
+ ```
39
+
40
+ Особенности:
41
+ - **Нет `__tests__`**, нет subcomponents — компонент максимально тонкий.
42
+ - **`size` — prop, но НЕ форвардится детям**. Влияет только на `gap`.
43
+ Размер чипов — ответственность потребителя.
44
+
45
+ ---
46
+
47
+ ## Варианты и props
48
+
49
+ ### `IChipGroupProps extends React.HTMLAttributes<HTMLDivElement>`
50
+
51
+ | Prop | Тип | Default | Описание |
52
+ |---|---|---|---|
53
+ | `oneLine` | `boolean` | `false` | `true` → `flex` + `overflow: auto` (горизонтальный скролл, скроллбар скрыт). `false` → `flex-wrap: wrap` (многострочный). |
54
+ | `size` | `EComponentSize` | `MD` | Управляет gap: SM=8px, MD=8px, LG=12px. **Не передаётся в Chip.** |
55
+ | `children` | `ReactNode` | — | Обычно набор Chip/ChipIcon/ChipSelect etc. |
56
+ | `className` | `string` | — | Dop class через `clsx`. |
57
+ | `...HTMLDivAttributes` | — | — | Все стандартные. |
58
+
59
+ ---
60
+
61
+ ## Ключевые особенности реализации
62
+
63
+ ### `oneLine` → горизонтальный скролл со скрытым скроллбаром
64
+
65
+ ```less
66
+ &.oneLine {
67
+ overflow: auto;
68
+ scrollbar-width: none;
69
+ -ms-overflow-style: none;
70
+ &::-webkit-scrollbar { display: none; }
71
+ }
72
+ ```
73
+
74
+ Скроллбар скрыт во всех браузерах. Пользователь скроллит свайпом (touch)
75
+ или shift+wheel. **Без отдельной кнопки "стрелка"** — в отличие от
76
+ `CarouselExtended`. Если нужны стрелки — оборачивай ChipGroup в
77
+ `CarouselExtended`.
78
+
79
+ ### `multiLine` по умолчанию
80
+
81
+ ```less
82
+ &.multiLine { flex-wrap: wrap; }
83
+ ```
84
+
85
+ Без wrap — инлайновые чипы проталкивали бы родителя в overflow. Multi-line
86
+ — стандартное поведение фильтров.
87
+
88
+ ### `gap` зависит от size
89
+
90
+ - SM / MD: 8px
91
+ - LG: 12px
92
+
93
+ SM и MD одинаковы — это дизайн-решение. **Не объединять** в `& { gap: 8px }`
94
+ и `&.lg { gap: 12px }` — поменяет интенсивность спецификации, может
95
+ сломать override'ы потребителей.
96
+
97
+ ### `createSizeToClassNameMap(styles)` — тот же паттерн
98
+
99
+ Тот же `classNameMaps.ts` утилита, что в Badge / Chip / многих других.
100
+ Если добавить XS/XL в EComponentSize — нужно обновить и mapping, и LESS.
101
+
102
+ ### `data-tx={process.env.npm_package_version}` — есть
103
+
104
+ Стандарт библиотеки. Не удалять.
105
+
106
+ ### size не передаётся детям
107
+
108
+ **Это отличие от многих других групповых компонентов** (CheckboxXGroup/YGroup
109
+ передают size через контекст). ChipGroup намеренно не передаёт — потребители
110
+ могут иметь чипы разных размеров в одной группе (например, ChipIcon LG +
111
+ Chip MD — визуально смотрится как отдельная подсвеченная кнопка).
112
+
113
+ ---
114
+
115
+ ## Инварианты
116
+
117
+ - **`forwardRef`** — обязателен.
118
+ - **`display: flex`** на root — не менять на grid. Потребители могут
119
+ полагаться на flex-item поведение чипов (`styles.chipGroupItem`
120
+ декларирует `display: inline-block`).
121
+ - **Скрытый скроллбар в `oneLine`** — три вендор-префикса, не удалять.
122
+ - **`gap` только на root-класе `.chipGroup`** — дети (чипы) не должны
123
+ иметь собственных margin'ов.
124
+ - **`size` не прокидывается детям** — осознанное решение. Не добавлять
125
+ контекст "для консистентности".
126
+ - **`data-tx`** — не удалять.
127
+
128
+ ---
129
+
130
+ ## Accessibility
131
+
132
+ - **Нет ARIA-ролей** — ChipGroup семантически нейтрален. Если это набор
133
+ фильтров — потребитель может обернуть в `<fieldset>` с `<legend>` или
134
+ добавить `role="group"` + `aria-label`.
135
+ - **Клавиатурная навигация** — **не реализована**. Tab перемещается
136
+ линейно через tabbable-чипы внутри. Arrow keys не поддерживаются. Если
137
+ нужен roving-tabindex с arrow keys — это задача потребителя (или бери
138
+ `RadioGroup`/`TabsLine`-семейства).
139
+ - **Скроллбар в oneLine скрыт визуально**, но работает клавиатурой (можно
140
+ кликнуть в ChipGroup и использовать arrow-left/right для скролла). Screen
141
+ reader-ы обычно читают содержимое независимо от видимости скроллбара.
142
+
143
+ ---
144
+
145
+ ## Дизайн-токены
146
+
147
+ Нет. Компонент структурный — gap'ы жёстко в LESS.
148
+
149
+ ---
150
+
151
+ ## Связанные компоненты
152
+
153
+ - `Chip` и все `Chip*` варианты (`src/components/Chip`) — типичные дети.
154
+ - `TagGroup` (`src/components/Tag`) — аналогичный контейнер для тегов
155
+ (разная стилистика и семантика).
156
+ - `CarouselExtended` — может обёртывать ChipGroup для добавления стрелок
157
+ prev/next при `oneLine` overflow.
158
+ - `EComponentSize`, `createSizeToClassNameMap` — общий паттерн.
159
+
160
+ ---
161
+
162
+ ## Stories
163
+
164
+ `stories/Chips/ChipGroup.stories.tsx`
165
+ Примеры: `stories/Chips/examples/ChipGroup/`
166
+
167
+ Типовые stories:
168
+ - `Default` — многострочный набор чипов
169
+ - `OneLine` — горизонтальный скролл
170
+ - `Sizes` — MD vs LG gap
171
+ - `Playground` — интерактивный контроль `oneLine` и `size`
172
+
173
+ ---
174
+
175
+ ## История изменений
176
+
177
+ | Дата | Изменение |
178
+ |---|---|
179
+ | 2026-04-18 | Создан документ |