@sberbusiness/triplex-next-mcp-server 0.24.0-beta2 → 0.36.0-beta0

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 (55) hide show
  1. package/README.md +10 -0
  2. package/bundle/components/BodyPage.md +186 -0
  3. package/bundle/components/Button.md +90 -85
  4. package/bundle/components/ButtonDropdown.md +28 -70
  5. package/bundle/components/ButtonIcon.md +35 -48
  6. package/bundle/components/Checkbox.md +43 -122
  7. package/bundle/components/CheckboxXGroup.md +109 -46
  8. package/bundle/components/CheckboxYGroup.md +77 -49
  9. package/bundle/components/CollapsibleTree.md +581 -0
  10. package/bundle/components/CollapsibleTreeExtended.md +418 -0
  11. package/bundle/components/EmptyView.md +14 -15
  12. package/bundle/components/FooterPage.md +203 -0
  13. package/bundle/components/Gap.md +115 -57
  14. package/bundle/components/HeaderPage.md +226 -0
  15. package/bundle/components/HelpBox.md +45 -84
  16. package/bundle/components/ImageGallery.md +423 -0
  17. package/bundle/components/ImageGalleryExtended.md +606 -0
  18. package/bundle/components/List.md +194 -186
  19. package/bundle/components/ListItem.md +251 -0
  20. package/bundle/components/ListItemControlsButton.md +103 -0
  21. package/bundle/components/ListItemControlsButtonDropdown.md +107 -0
  22. package/bundle/components/ListItemSelectable.md +99 -0
  23. package/bundle/components/ListItemTable.md +390 -0
  24. package/bundle/components/ListMaster.md +877 -156
  25. package/bundle/components/ListMasterFooter.md +80 -0
  26. package/bundle/components/ListMasterHeader.md +86 -0
  27. package/bundle/components/ListSortable.md +153 -0
  28. package/bundle/components/ListSortableItem.md +175 -0
  29. package/bundle/components/ModalWindow.md +427 -237
  30. package/bundle/components/MonthYearField.md +145 -109
  31. package/bundle/components/Notification.md +625 -155
  32. package/bundle/components/Overlay.md +271 -170
  33. package/bundle/components/Page.md +283 -186
  34. package/bundle/components/Pagination.md +206 -229
  35. package/bundle/guides/codestyle.md +38 -11
  36. package/bundle/guides/commits.md +1 -2
  37. package/bundle/guides/context.md +34 -30
  38. package/bundle/guides/stories.md +110 -40
  39. package/bundle/guides/template.md +3 -7
  40. package/bundle/guides/tests.md +6 -2
  41. package/bundle/manifest.json +194 -24
  42. package/bundle/release-notes/1.26.0.mdx +33 -2
  43. package/bundle/release-notes/1.27.0.mdx +43 -0
  44. package/bundle/release-notes/1.28.0.mdx +25 -0
  45. package/bundle/release-notes/1.29.0.mdx +47 -0
  46. package/bundle/release-notes/1.30.0.mdx +56 -0
  47. package/bundle/release-notes/1.31.0.mdx +52 -0
  48. package/bundle/release-notes/1.32.0.mdx +35 -0
  49. package/bundle/release-notes/1.33.0.mdx +61 -0
  50. package/bundle/release-notes/1.34.0.mdx +35 -0
  51. package/bundle/release-notes/1.35.0.mdx +21 -0
  52. package/bundle/release-notes/1.35.1.mdx +11 -0
  53. package/bundle/release-notes/1.36.0.mdx +21 -0
  54. package/bundle/release-notes/1.37.0.mdx +30 -0
  55. package/package.json +1 -1
@@ -0,0 +1,251 @@
1
+ ---
2
+ component: ListItem
3
+ category: List
4
+ related: [List, ListItemContent, ListItemSelectable, ListItemTable, ListSortableItem]
5
+ tokens:
6
+ - --triplex-next-ListItem-Background
7
+ - --triplex-next-ListItem-Background_Selected
8
+ stories: stories/List/ListItem.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # ListItem
13
+
14
+ ## Назначение
15
+
16
+ Базовый элемент списка `<li>` — обёртка вокруг произвольного содержимого
17
+ (`ListItemContent`, `ListItemSelectable`, `SwipeableArea` и т.п.). Создаёт
18
+ React-контекст `ListItemContext` с состояниями `selected` и `selectable`:
19
+ `selected` управляет подсветкой `ListItemContent`, `selectable` сообщает
20
+ дочернему `ListItemContent`, что элемент выбираемый — для применения
21
+ скругления углов (`border-radius`). Оба флага пишутся `ListItemSelectable`
22
+ через `useEffect`.
23
+
24
+ Используй `ListItem` когда: нужен произвольный layout строки списка.
25
+ Используй `ListItemTable` когда: нужна готовая табличная строка с support'ом
26
+ swipe-actions и selectable.
27
+
28
+ ---
29
+
30
+ ## Варианты и props
31
+
32
+ ### Опциональные props
33
+
34
+ | Prop | Тип | По умолчанию | Описание |
35
+ |---|---|---|---|
36
+ | `children` | `React.ReactNode` | — | Содержимое строки |
37
+ | `...HTMLLIElementAttributes` | — | — | Все стандартные атрибуты `<li>` |
38
+
39
+ ---
40
+
41
+ ## Дизайн-токены
42
+
43
+ Сами стили `ListItem.tsx` пустые — токены применяются в подкомпонентах
44
+ (`ListItemContent`, `ListItemSelectable`):
45
+
46
+ ```text
47
+ --triplex-next-ListItem-Background // фон по умолчанию
48
+ --triplex-next-ListItem-Background_Selected // фон, когда selected=true
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Инварианты
54
+
55
+ - **`forwardRef`** — обязателен, target — `HTMLLIElement`. Не убирать.
56
+ - **`ListItemContext`** — провайдер на каждом `ListItem`. Не выносить наружу — context используется парой `ListItemSelectable` (writer для `selected` и `selectable`) ↔ `ListItemContent` (reader) внутри одной строки.
57
+ - **Поля контекста `selected` / `selectable`** — оба `boolean`, дефолт `false`. `selectable` всегда выставляется в `true` из `ListItemSelectable` (через `useEffect`), `selected` синхронизируется с одноимённым prop'ом `ListItemSelectable`. Сеттеры (`setSelected`, `setSelectable`) предназначены только для внутренних консьюмеров.
58
+ - **Корневой элемент `<li>`** — не менять. Семантика важна для accessibility.
59
+
60
+ ---
61
+
62
+ ## Связанные компоненты
63
+
64
+ - `ListItemContent` — внутренняя обёртка для контента, читает `selected` из контекста.
65
+ - `ListItemSelectable` — добавляет чекбокс выбора, синхронизирует `selected` в контекст через `useEffect`.
66
+ - `ListItemLoading` — элемент-спиннер для пагинации (используется как последний элемент).
67
+ - `ListItemControls`, `ListItemControlsButton`, `ListItemControlsButtonDropdown` — кнопки действий, обычно внутри `SwipeableArea.rightSwipeableArea`.
68
+ - `ListItemTailLeft` / `ListItemTailRight` — декоративные хвосты для `SwipeableArea`.
69
+ - `ListItemTable` — комбинированная высокоуровневая обёртка.
70
+
71
+ ---
72
+
73
+ ## Stories
74
+
75
+ Основные истории: `stories/List/ListItem.stories.tsx`
76
+ Файлы примеров: `stories/List/examples/ListItem/`
77
+
78
+ | Story | Example file | Что демонстрирует |
79
+ |---|---|---|
80
+ | `Default` | `Default.tsx` | Базовый элемент с произвольным контентом |
81
+ | `Loading` | `Loading.tsx` | `ListItemLoading` как последний элемент при пагинации |
82
+ | `Selectable` | `Selectable.tsx` | Использование `ListItemSelectable` внутри `ListItem` |
83
+ | `Swipeable` | `Swipeable.tsx` | `ListItem` внутри `SwipeableArea` с `ListItemControls` |
84
+
85
+ ---
86
+
87
+ ## История изменений
88
+
89
+ | Дата | Изменение |
90
+ |---|---|
91
+ | 2026-04-29 | Создан документ |
92
+ | 2026-05-21 | `ListItemContext` расширен полями `selectable` / `setSelectable`. Исправлен цвет токена `Background_Selected` в тёмной теме (`ColorDarkNeutral.10` → `ColorDarkNeutral.60`). |
93
+
94
+ ---
95
+
96
+ ## Примеры использования
97
+
98
+ ### Default
99
+
100
+ `stories/List/examples/ListItem/Default.tsx`
101
+
102
+ ```tsx
103
+ import React from "react";
104
+ import { List, ListItem, ListItemContent } from "@sberbusiness/triplex-next";
105
+
106
+ export const Default = () => (
107
+ <div style={{ maxWidth: "500px" }}>
108
+ <List>
109
+ <ListItem>
110
+ <ListItemContent>Элемент списка</ListItemContent>
111
+ </ListItem>
112
+ </List>
113
+ </div>
114
+ );
115
+ ```
116
+
117
+ ### Loading
118
+
119
+ `stories/List/examples/ListItem/Loading.tsx`
120
+
121
+ ```tsx
122
+ import React from "react";
123
+ import { List, ListItem, ListItemLoading } from "@sberbusiness/triplex-next";
124
+
125
+ export const Loading = () => (
126
+ <div style={{ maxWidth: "500px" }}>
127
+ <List>
128
+ <ListItem>
129
+ <ListItemLoading />
130
+ </ListItem>
131
+ </List>
132
+ </div>
133
+ );
134
+ ```
135
+
136
+ ### Selectable
137
+
138
+ `stories/List/examples/ListItem/Selectable.tsx`
139
+
140
+ ```tsx
141
+ import React, { useState } from "react";
142
+ import { List, ListItem, ListItemContent, ListItemSelectable } from "@sberbusiness/triplex-next";
143
+
144
+ export const Selectable = () => {
145
+ const [selected, setSelected] = useState(false);
146
+
147
+ return (
148
+ <div style={{ maxWidth: "500px" }}>
149
+ <List>
150
+ <ListItem>
151
+ <ListItemSelectable selected={selected} onSelect={setSelected}>
152
+ <ListItemContent>Элемент списка</ListItemContent>
153
+ </ListItemSelectable>
154
+ </ListItem>
155
+ </List>
156
+ </div>
157
+ );
158
+ };
159
+ ```
160
+
161
+ ### Swipeable
162
+
163
+ `stories/List/examples/ListItem/Swipeable.tsx`
164
+
165
+ ```tsx
166
+ import React from "react";
167
+ import {
168
+ ISwipeableAreaRef,
169
+ List,
170
+ ListItem,
171
+ ListItemContent,
172
+ ListItemControls,
173
+ ListItemControlsButton,
174
+ ListItemControlsButtonDropdown,
175
+ ListItemTailRight,
176
+ SwipeableArea,
177
+ } from "@sberbusiness/triplex-next";
178
+ import { DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
179
+
180
+ export const Swipeable = () => {
181
+ const options = [
182
+ {
183
+ id: "list-item-swipe-controls-dropdown-option-1",
184
+ label: "Текст пункта меню 1",
185
+ onSelect: () => alert("Выбран пункт меню 1."),
186
+ },
187
+ {
188
+ id: "list-item-swipe-controls-dropdown-option-2",
189
+ label: "Текст пункта меню 2",
190
+ onSelect: () => alert("Выбран пункт меню 2."),
191
+ },
192
+ {
193
+ id: "list-item-swipe-controls-dropdown-option-3",
194
+ label: "Текст пункта меню 3",
195
+ onSelect: () => alert("Выбран пункт меню 3."),
196
+ },
197
+ ];
198
+
199
+ const ref = React.useRef<ISwipeableAreaRef>(null);
200
+
201
+ return (
202
+ <div style={{ maxWidth: "500px" }}>
203
+ <button
204
+ onClick={() => {
205
+ if (ref.current) {
206
+ ref.current.swipeLeft();
207
+ }
208
+ }}
209
+ >
210
+ swipe
211
+ </button>
212
+ <button
213
+ onClick={() => {
214
+ if (ref.current) {
215
+ ref.current.closeSwipe();
216
+ }
217
+ }}
218
+ >
219
+ close
220
+ </button>
221
+ <br />
222
+
223
+ <List>
224
+ <ListItem>
225
+ <SwipeableArea
226
+ ref={ref}
227
+ rightSwipeableArea={
228
+ <ListItemControls>
229
+ <ListItemControlsButton icon={<DefaulticonStrokePrdIcon20 paletteIndex={0} />}>
230
+ Button name
231
+ </ListItemControlsButton>
232
+ <ListItemControlsButtonDropdown
233
+ icon={<DefaulticonStrokePrdIcon20 paletteIndex={0} />}
234
+ options={options}
235
+ >
236
+ Button name
237
+ </ListItemControlsButtonDropdown>
238
+ </ListItemControls>
239
+ }
240
+ >
241
+ <ListItemTailRight />
242
+ {/* Минимальная высота, из-за блока Action с кнопками при свайпе. */}
243
+ <ListItemContent style={{ minHeight: "56px" }}>Свайп влево</ListItemContent>
244
+ </SwipeableArea>
245
+ </ListItem>
246
+ </List>
247
+ </div>
248
+ );
249
+ };
250
+ ```
251
+
@@ -0,0 +1,103 @@
1
+ ---
2
+ component: ListItemControlsButton
3
+ category: List
4
+ related: [ListItemControls, ListItemControlsButtonDropdown, IconWrapper]
5
+ tokens:
6
+ - --triplex-next-ListItemControlsButton-Background_Default
7
+ - --triplex-next-ListItemControlsButton-Background_Hover
8
+ - --triplex-next-ListItemControlsButton-Background_Active
9
+ - --triplex-next-ListItemControlsButton-Color_Default
10
+ - --triplex-next-ListItemControlsButton-Color_Hover
11
+ - --triplex-next-ListItemControlsButton-Color_Active
12
+ stories: stories/List/ListItemControls.stories.tsx
13
+ version: "1.0"
14
+ ---
15
+
16
+ # ListItemControlsButton
17
+
18
+ ## Назначение
19
+
20
+ Кнопка действия для области под свайпом списка. Рендерит вертикальную
21
+ композицию `icon` + `children` (текст), оборачивает их в `IconWrapper`,
22
+ который автоматически меняет цвет иконки/текста в hover/active состоянии.
23
+
24
+ Используй `ListItemControlsButton` когда: нужно одно действие в swipe-actions.
25
+ Используй `ListItemControlsButtonDropdown` когда: нужен выбор из нескольких
26
+ действий через dropdown.
27
+
28
+ ---
29
+
30
+ ## Варианты и props
31
+
32
+ ### Опциональные props
33
+
34
+ | Prop | Тип | По умолчанию | Описание |
35
+ |---|---|---|---|
36
+ | `icon` | `React.ReactNode` | — | Иконка, отображается над текстом. Добавляет класс `withIcon` |
37
+ | `children` | `React.ReactNode` | — | Текст кнопки (рендерится через `<Text size={B4} weight={SEMIBOLD}>`). Добавляет класс `withText` |
38
+ | `disabled` | `boolean` | — | Стандартный атрибут `<button>`. Передаётся в `IconWrapper.disabled` |
39
+ | `aria-expanded` | `boolean` | — | Стандартный ARIA-атрибут. Если `true` — `IconWrapper` получает класс `active` (визуальное состояние «нажато») |
40
+ | `...HTMLButtonAttributes` | — | — | Все стандартные атрибуты `<button>`. `type` по умолчанию `"button"` |
41
+
42
+ ---
43
+
44
+ ## Дизайн-токены
45
+
46
+ Паттерн: `--triplex-next-ListItemControlsButton-{Property}_{State}`
47
+
48
+ ```text
49
+ --triplex-next-ListItemControlsButton-Background_Default
50
+ --triplex-next-ListItemControlsButton-Background_Hover
51
+ --triplex-next-ListItemControlsButton-Background_Active // применяется при :active или классе .expanded (если выставлен снаружи)
52
+ --triplex-next-ListItemControlsButton-Color_Default
53
+ --triplex-next-ListItemControlsButton-Color_Hover
54
+ --triplex-next-ListItemControlsButton-Color_Active
55
+ ```
56
+
57
+ Цвет лейбла переопределяет токен `Color_*` через `!important`, потому что
58
+ `<Text>` имеет свой `color`-стиль.
59
+
60
+ ---
61
+
62
+ ## Инварианты
63
+
64
+ - **`forwardRef`** — обязателен, target — `HTMLButtonElement`. Не убирать.
65
+ - **`type="button"`** по умолчанию — не убирать, иначе кнопка внутри `<form>` будет сабмитить.
66
+ - **Классы `withIcon` / `withText`** — выставляются автоматически по наличию `icon` / `children`. Не передавать вручную.
67
+ - **Лейбл оборачивается в `<Text>`** — не заменять на `<span>`, иначе сломается типографика и переопределение цвета через токены.
68
+
69
+ ---
70
+
71
+ ## Accessibility
72
+
73
+ - Нативный `<button>` — полная поддержка клавиатуры (Tab, Enter, Space).
74
+ - **Иконочный режим** (без `children`) — потребитель **обязан** передать `aria-label` через `...rest`. Библиотека мультиязычная, текст не хардкодится.
75
+ - **`aria-expanded`** — используется когда кнопка является триггером dropdown (см. `ListItemControlsButtonDropdown`); визуально активирует подсветку иконки/текста через `IconWrapper.active`.
76
+
77
+ ---
78
+
79
+ ## Связанные компоненты
80
+
81
+ - `ListItemControls` — обёртка-контейнер для группы `ListItemControlsButton`.
82
+ - `ListItemControlsButtonDropdown` — расширение, добавляющее dropdown.
83
+ - `IconWrapper` — обёртка для иконки, управляет цветом через `hoverable` / `active` / `disabled`.
84
+ - `Text` — типографический компонент для лейбла.
85
+
86
+ ---
87
+
88
+ ## Stories
89
+
90
+ Основные истории: `stories/List/ListItemControls.stories.tsx`
91
+ Файл примера: `stories/List/examples/ListItemControls/Default.tsx`
92
+
93
+ | Story | Example file | Что демонстрирует |
94
+ |---|---|---|
95
+ | `Default` | `Default.tsx` | Несколько кнопок (icon-only, text-only, icon+text) и `ListItemControlsButtonDropdown` внутри `ListItemControls` |
96
+
97
+ ---
98
+
99
+ ## История изменений
100
+
101
+ | Дата | Изменение |
102
+ |---|---|
103
+ | 2026-04-29 | Создан документ |
@@ -0,0 +1,107 @@
1
+ ---
2
+ component: ListItemControlsButtonDropdown
3
+ category: List
4
+ related: [ListItemControlsButton, ButtonDropdownExtended, Dropdown]
5
+ tokens:
6
+ - --triplex-next-ListItemControlsButton-Background_Default
7
+ - --triplex-next-ListItemControlsButton-Background_Hover
8
+ - --triplex-next-ListItemControlsButton-Background_Active
9
+ - --triplex-next-ListItemControlsButton-Color_Default
10
+ - --triplex-next-ListItemControlsButton-Color_Hover
11
+ - --triplex-next-ListItemControlsButton-Color_Active
12
+ stories: stories/List/ListItemControls.stories.tsx
13
+ version: "1.0"
14
+ ---
15
+
16
+ # ListItemControlsButtonDropdown
17
+
18
+ ## Назначение
19
+
20
+ Кнопка-триггер для dropdown-меню в swipe-actions списка. Использует
21
+ `ListItemControlsButton` как кнопку и `ButtonDropdownExtended` для
22
+ выпадающего списка опций. На мобильном — bottom sheet, на десктопе — обычный
23
+ dropdown.
24
+
25
+ Используй когда: в swipe-actions нужно несколько действий, объединённых под
26
+ одной кнопкой (обычно «Действия» / «Ещё»).
27
+
28
+ ---
29
+
30
+ ## Варианты и props
31
+
32
+ Тип props: `Omit<IButtonDropdownProps, "size"> & Pick<IListItemControlsButtonProps, "icon">`
33
+
34
+ ### Обязательные props
35
+
36
+ | Prop | Тип | Описание |
37
+ |---|---|---|
38
+ | `options` | `IButtonDropdownOption[]` | Список опций dropdown. Каждая опция: `{ id, label, onSelect?, ...IDropdownListItemProps }` |
39
+ | `children` | `React.ReactNode` | Текст кнопки (становится заголовком mobile-bottom-sheet) |
40
+
41
+ ### Опциональные props
42
+
43
+ | Prop | Тип | Описание |
44
+ |---|---|---|
45
+ | `icon` | `React.ReactNode` | Иконка кнопки (как в `ListItemControlsButton`) |
46
+ | `selected` | `IButtonDropdownOption` | Текущая выбранная опция (отмечается в dropdown) |
47
+ | `disabled` | `boolean` | Блокирует кнопку и открытие dropdown |
48
+ | `buttonAttributes` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | Атрибуты, пробрасываемые на `<button>` |
49
+ | `...HTMLDivAttributes` | — | Атрибуты внешнего `<div>` контейнера |
50
+
51
+ ---
52
+
53
+ ## Дизайн-токены
54
+
55
+ Использует те же токены, что и `ListItemControlsButton`. Дополнительно — стиль
56
+ `.buttonDropdownMenuItem` для опций dropdown (ellipsis для длинных лейблов).
57
+
58
+ ---
59
+
60
+ ## Инварианты
61
+
62
+ - **`forwardRef`** — обязателен, target — `HTMLButtonElement` (на саму кнопку, не на контейнер).
63
+ - **`aria-haspopup="menu"`, `aria-controls={instanceId}`** — выставляются автоматически. `aria-expanded` синхронизируется с состоянием `opened`.
64
+ - **`closeOnTab`** — включён всегда (Tab закрывает dropdown).
65
+ - **`uniqueId` для `instanceId`** — используется `lodash-es/uniqueId` через `useRef(uniqueId())`. **Не** мигрировать на `useId()` — ветка `release-0` поддерживает React 17, см. `docs/ai/ai-refactoring.md`.
66
+
67
+ ---
68
+
69
+ ## Accessibility
70
+
71
+ - **Клавиатура:**
72
+ - `Space`, `ArrowUp`, `ArrowDown` — `preventDefault` (не скроллит страницу).
73
+ - `ArrowUp` / `ArrowDown` в закрытом состоянии — открывают dropdown.
74
+ - `Escape` / `Tab` — закрывают dropdown (через `ButtonDropdownExtended`).
75
+ - **`aria-haspopup="menu"`** — указывает на наличие меню.
76
+ - **`aria-expanded`** — синхронизирован с `opened` (true/false).
77
+ - **`aria-controls`** — связывает кнопку с id dropdown.
78
+ - **`aria-activedescendant`** — управляется через `DropdownListContext`, указывает на текущий выделенный элемент.
79
+
80
+ ---
81
+
82
+ ## Связанные компоненты
83
+
84
+ - `ListItemControlsButton` — используется как сама кнопка-триггер.
85
+ - `ButtonDropdownExtended` — обвязка для кастомных кнопок + dropdown.
86
+ - `Dropdown`, `DropdownList` (desktop) — выпадающий список на десктопе.
87
+ - `DropdownMobileBody`, `DropdownMobileList`, `DropdownMobileListItem`, `DropdownMobileHeader`, `DropdownMobileClose` — bottom-sheet на мобильном.
88
+ - `DropdownListContext` — управление `activeDescendant`.
89
+
90
+ ---
91
+
92
+ ## Stories
93
+
94
+ Основные истории: `stories/List/ListItemControls.stories.tsx`
95
+ Файл примера: `stories/List/examples/ListItemControls/Default.tsx`
96
+
97
+ | Story | Example file | Что демонстрирует |
98
+ |---|---|---|
99
+ | `Default` | `Default.tsx` | `ListItemControlsButtonDropdown` рядом с `ListItemControlsButton` внутри `ListItemControls` |
100
+
101
+ ---
102
+
103
+ ## История изменений
104
+
105
+ | Дата | Изменение |
106
+ |---|---|
107
+ | 2026-04-29 | Создан документ |
@@ -0,0 +1,99 @@
1
+ ---
2
+ component: ListItemSelectable
3
+ category: List
4
+ related: [ListItem, ListItemContent, Checkbox]
5
+ tokens:
6
+ - --triplex-next-ListItem-Background
7
+ - --triplex-next-ListItem-Background_Selected
8
+ stories: stories/List/ListItem.stories.tsx
9
+ version: "1.0"
10
+ ---
11
+
12
+ # ListItemSelectable
13
+
14
+ ## Назначение
15
+
16
+ Контейнер выбора элемента списка. Рендерит контент + чекбокс справа.
17
+ Управляется снаружи (`selected` + `onSelect`). Через `useEffect` записывает
18
+ в `ListItemContext` два флага: `selected` — для подсветки фона дочернего
19
+ `ListItemContent` (`background_selected`); `selectable: true` — для
20
+ применения скругления углов (`border-radius`) в `ListItemContent`.
21
+
22
+ Используй `ListItemSelectable` когда: нужен выбор отдельного элемента списка
23
+ с собственным чекбоксом (multi-select).
24
+
25
+ ---
26
+
27
+ ## Варианты и props
28
+
29
+ ### Обязательные props
30
+
31
+ | Prop | Тип | Описание |
32
+ |---|---|---|
33
+ | `selected` | `boolean` | Состояние «выбран». Управляется снаружи |
34
+ | `onSelect` | `(selected: boolean) => void` | Вызывается при изменении состояния чекбокса |
35
+
36
+ ### Опциональные props
37
+
38
+ | Prop | Тип | Описание |
39
+ |---|---|---|
40
+ | `disabled` | `boolean` | Блокирует встроенный `Checkbox` (передаётся в `Checkbox` как есть) |
41
+ | `children` | `React.ReactNode` | Контент строки (рендерится в `<div className="childrenWrapper">`) |
42
+ | `...HTMLDivAttributes` | — | Все атрибуты `<div>`, кроме конфликтующего `onSelect` (исключён через `Omit`) |
43
+
44
+ ---
45
+
46
+ ## Дизайн-токены
47
+
48
+ ```text
49
+ --triplex-next-ListItem-Background // фон по умолчанию
50
+ --triplex-next-ListItem-Background_Selected // фон, когда selected=true
51
+ ```
52
+
53
+ ---
54
+
55
+ ## Инварианты
56
+
57
+ - **`forwardRef`** — обязателен, target — `HTMLDivElement`. Не убирать.
58
+ - **Контракт `onSelect: (boolean) => void`** — не путать с нативным `onSelect: SelectionEvent` от `<div>`. Тип специально перекрывает нативный через `Omit<..., "onSelect">`.
59
+ - **Два `useEffect`** — синхронизируют `ListItemContext`:
60
+ - `[selected, setSelected]` → запись `selected` (для подсветки `ListItemContent`).
61
+ - `[setSelectable]` → запись `selectable = true` при монтировании и cleanup в `false` при размонтировании (для скругления углов `ListItemContent`). Не убирать запись — иначе у выбираемого элемента не появится `border-radius`. Не убирать cleanup — иначе при условном размонтировании `ListItemSelectable` внутри живого `ListItem` состояние «прилипнет» в `true`.
62
+ - **Использование внутри `ListItem`** — `setSelected` / `setSelectable` берутся из `ListItemContext`. Если рендерить `ListItemSelectable` без родительского `ListItem`, контекст вернёт no-op сеттеры.
63
+
64
+ ---
65
+
66
+ ## Accessibility
67
+
68
+ - Чекбокс — встроенный `<Checkbox>` из библиотеки, имеет нативный `<input type="checkbox">`.
69
+ - Клик по любой части `.childrenWrapper` **не** переключает чекбокс — только клик по самому чекбоксу или его расширенной области (`.checkboxLabelClickArea`, `+4px` со всех сторон).
70
+ - Если нужен клик по всей строке — оборачивай в `<label>` или используй `ListItemTable` + `onClickItem`.
71
+
72
+ ---
73
+
74
+ ## Связанные компоненты
75
+
76
+ - `ListItem` — родительский `<li>`, провайдер `ListItemContext`.
77
+ - `ListItemContent` — потребитель `ListItemContext.selected` для применения класса `selected`.
78
+ - `Checkbox` — встроенный чекбокс выбора.
79
+ - `ListItemTable` — использует `ListItemSelectable` автоматически в selectable-варианте.
80
+
81
+ ---
82
+
83
+ ## Stories
84
+
85
+ Основные истории: `stories/List/ListItem.stories.tsx`
86
+ Файл примера: `stories/List/examples/ListItem/Selectable.tsx`
87
+
88
+ | Story | Example file | Что демонстрирует |
89
+ |---|---|---|
90
+ | `Selectable` | `Selectable.tsx` | Использование `ListItemSelectable` внутри `ListItem` |
91
+
92
+ ---
93
+
94
+ ## История изменений
95
+
96
+ | Дата | Изменение |
97
+ |---|---|
98
+ | 2026-04-29 | Создан документ |
99
+ | 2026-05-21 | Добавлен опциональный prop `disabled` (пробрасывается в `Checkbox`). Компонент пишет в `ListItemContext` флаг `selectable = true` при монтировании. |