@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.
- package/README.md +124 -0
- package/bundle/.gitkeep +0 -0
- package/bundle/components/AbstractTree.md +198 -0
- package/bundle/components/AccordionBase.md +227 -0
- package/bundle/components/Alert.md +317 -0
- package/bundle/components/Amount.md +225 -0
- package/bundle/components/AmountField.md +289 -0
- package/bundle/components/Avatar.md +209 -0
- package/bundle/components/Badge.md +277 -0
- package/bundle/components/Body.md +167 -0
- package/bundle/components/Button.md +230 -0
- package/bundle/components/ButtonDropdown.md +159 -0
- package/bundle/components/ButtonIcon.md +122 -0
- package/bundle/components/Calendar.md +445 -0
- package/bundle/components/Card.md +374 -0
- package/bundle/components/CarouselExtended.md +250 -0
- package/bundle/components/Checkbox.md +126 -0
- package/bundle/components/CheckboxTree.md +280 -0
- package/bundle/components/CheckboxTreeExtended.md +321 -0
- package/bundle/components/CheckboxXGroup.md +68 -0
- package/bundle/components/CheckboxYGroup.md +67 -0
- package/bundle/components/Chip.md +404 -0
- package/bundle/components/ChipGroup.md +179 -0
- package/bundle/components/Col.md +221 -0
- package/bundle/components/CollapsableTree.md +255 -0
- package/bundle/components/Confirm.md +343 -0
- package/bundle/components/DateField.md +371 -0
- package/bundle/components/DatePickerExtended.md +342 -0
- package/bundle/components/DateRange.md +275 -0
- package/bundle/components/DesignTokens.md +385 -0
- package/bundle/components/Divider.md +196 -0
- package/bundle/components/DocumentNumberEdit.md +280 -0
- package/bundle/components/Dropdown.md +433 -0
- package/bundle/components/Ellipsis.md +208 -0
- package/bundle/components/EmptyView.md +99 -0
- package/bundle/components/ExpandAnimation.md +281 -0
- package/bundle/components/Footer.md +339 -0
- package/bundle/components/FormField.md +326 -0
- package/bundle/components/FormGroup.md +99 -0
- package/bundle/components/Gap.md +113 -0
- package/bundle/components/Header.md +280 -0
- package/bundle/components/HelpBox.md +154 -0
- package/bundle/components/IconWrapper.md +145 -0
- package/bundle/components/Island.md +197 -0
- package/bundle/components/IslandAccordion.md +230 -0
- package/bundle/components/IslandWidget.md +233 -0
- package/bundle/components/KeyDownListener.md +157 -0
- package/bundle/components/LightBox.md +322 -0
- package/bundle/components/Link.md +161 -0
- package/bundle/components/List.md +247 -0
- package/bundle/components/ListMaster.md +204 -0
- package/bundle/components/Loader.md +161 -0
- package/bundle/components/LoaderScreen.md +134 -0
- package/bundle/components/Marker.md +127 -0
- package/bundle/components/MarkerStatus.md +148 -0
- package/bundle/components/MediaWidth.md +169 -0
- package/bundle/components/MobileView.md +120 -0
- package/bundle/components/ModalWindow.md +308 -0
- package/bundle/components/MonthYearField.md +168 -0
- package/bundle/components/MultiselectField.md +213 -0
- package/bundle/components/Notification.md +233 -0
- package/bundle/components/NumberField.md +178 -0
- package/bundle/components/OrderedList.md +169 -0
- package/bundle/components/Overlay.md +237 -0
- package/bundle/components/Page.md +246 -0
- package/bundle/components/Pagination.md +298 -0
- package/bundle/components/Portal.md +119 -0
- package/bundle/components/Radio.md +174 -0
- package/bundle/components/Row.md +125 -0
- package/bundle/components/SMSField.md +160 -0
- package/bundle/components/SegmentedControl.md +235 -0
- package/bundle/components/SelectExtendedField.md +322 -0
- package/bundle/components/SelectField.md +213 -0
- package/bundle/components/Skeleton.md +129 -0
- package/bundle/components/Slider.md +157 -0
- package/bundle/components/SliderExtended.md +210 -0
- package/bundle/components/SliderRange.md +160 -0
- package/bundle/components/SmallInput.md +101 -0
- package/bundle/components/Spoiler.md +121 -0
- package/bundle/components/StatusTracker.md +151 -0
- package/bundle/components/Step.md +121 -0
- package/bundle/components/Stepper.md +163 -0
- package/bundle/components/Suggest.md +160 -0
- package/bundle/components/SuggestField.md +157 -0
- package/bundle/components/SwipeableArea.md +144 -0
- package/bundle/components/Table.md +199 -0
- package/bundle/components/Tabs.md +152 -0
- package/bundle/components/TabsExtended.md +273 -0
- package/bundle/components/TabsLine.md +189 -0
- package/bundle/components/Tag.md +135 -0
- package/bundle/components/TagColor.md +121 -0
- package/bundle/components/TagGroup.md +100 -0
- package/bundle/components/TextField.md +152 -0
- package/bundle/components/TextareaField.md +124 -0
- package/bundle/components/ThemeProvider.md +181 -0
- package/bundle/components/Tooltip.md +254 -0
- package/bundle/components/TopOverlay.md +145 -0
- package/bundle/components/TreeView.md +224 -0
- package/bundle/components/Triggers.md +121 -0
- package/bundle/guides/codestyle.md +205 -0
- package/bundle/guides/commits.md +166 -0
- package/bundle/guides/context.md +277 -0
- package/bundle/guides/stories.md +618 -0
- package/bundle/guides/template.md +154 -0
- package/bundle/guides/tests.md +301 -0
- package/bundle/icons.json +4156 -0
- package/bundle/manifest.json +796 -0
- package/bundle/release-notes/1.1.0.mdx +26 -0
- package/bundle/release-notes/1.1.1.mdx +14 -0
- package/bundle/release-notes/1.10.0.mdx +43 -0
- package/bundle/release-notes/1.11.0.mdx +19 -0
- package/bundle/release-notes/1.12.0.mdx +21 -0
- package/bundle/release-notes/1.13.0.mdx +43 -0
- package/bundle/release-notes/1.14.0.mdx +29 -0
- package/bundle/release-notes/1.15.0.mdx +56 -0
- package/bundle/release-notes/1.16.0.mdx +55 -0
- package/bundle/release-notes/1.17.0.mdx +15 -0
- package/bundle/release-notes/1.18.0.mdx +24 -0
- package/bundle/release-notes/1.19.0.mdx +48 -0
- package/bundle/release-notes/1.19.1.mdx +9 -0
- package/bundle/release-notes/1.2.0.mdx +80 -0
- package/bundle/release-notes/1.20.0.mdx +48 -0
- package/bundle/release-notes/1.21.0.mdx +66 -0
- package/bundle/release-notes/1.22.0.mdx +75 -0
- package/bundle/release-notes/1.23.0.mdx +50 -0
- package/bundle/release-notes/1.24.0.mdx +59 -0
- package/bundle/release-notes/1.25.0.mdx +52 -0
- package/bundle/release-notes/1.26.0.mdx +11 -0
- package/bundle/release-notes/1.3.0.mdx +21 -0
- package/bundle/release-notes/1.4.0.mdx +37 -0
- package/bundle/release-notes/1.5.0.mdx +24 -0
- package/bundle/release-notes/1.6.0.mdx +37 -0
- package/bundle/release-notes/1.6.1.mdx +11 -0
- package/bundle/release-notes/1.7.0.mdx +29 -0
- package/bundle/release-notes/1.8.0.mdx +38 -0
- package/bundle/release-notes/1.9.0.mdx +28 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +324 -0
- package/dist/index.js.map +1 -0
- 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 | Создан документ |
|