@sberbusiness/triplex-next-mcp-server 0.24.0-beta2 → 1.40.0-beta
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 +10 -0
- package/bundle/components/AlertContext.md +268 -0
- package/bundle/components/BodyPage.md +186 -0
- package/bundle/components/Button.md +93 -85
- package/bundle/components/ButtonDropdown.md +36 -70
- package/bundle/components/ButtonDropdownExtended.md +422 -0
- package/bundle/components/ButtonIcon.md +41 -48
- package/bundle/components/Caption.md +291 -0
- package/bundle/components/Checkbox.md +43 -122
- package/bundle/components/CheckboxXGroup.md +109 -46
- package/bundle/components/CheckboxYGroup.md +77 -49
- package/bundle/components/CodeText.md +197 -0
- package/bundle/components/Col.md +311 -162
- package/bundle/components/CollapsibleTree.md +584 -0
- package/bundle/components/CollapsibleTreeExtended.md +422 -0
- package/bundle/components/Dropdown.md +748 -346
- package/bundle/components/EmptyView.md +14 -15
- package/bundle/components/FooterPage.md +203 -0
- package/bundle/components/Gap.md +115 -57
- package/bundle/components/HeaderPage.md +226 -0
- package/bundle/components/HelpBox.md +45 -84
- package/bundle/components/ImageGallery.md +423 -0
- package/bundle/components/ImageGalleryExtended.md +606 -0
- package/bundle/components/LightBox.md +2252 -233
- package/bundle/components/List.md +216 -183
- package/bundle/components/ListActionItem.md +157 -0
- package/bundle/components/ListItem.md +276 -0
- package/bundle/components/ListItemControlsButton.md +103 -0
- package/bundle/components/ListItemControlsButtonDropdown.md +107 -0
- package/bundle/components/ListItemSelectable.md +99 -0
- package/bundle/components/ListItemTable.md +390 -0
- package/bundle/components/ListMaster.md +876 -156
- package/bundle/components/ListMasterFooter.md +80 -0
- package/bundle/components/ListMasterHeader.md +86 -0
- package/bundle/components/ListSortable.md +153 -0
- package/bundle/components/ListSortableItem.md +175 -0
- package/bundle/components/ListTableItem.md +391 -0
- package/bundle/components/ModalWindow.md +427 -237
- package/bundle/components/MonthYearField.md +145 -109
- package/bundle/components/Notification.md +625 -155
- package/bundle/components/Overlay.md +271 -170
- package/bundle/components/Page.md +284 -186
- package/bundle/components/Pagination.md +206 -229
- package/bundle/components/Portal.md +131 -67
- package/bundle/components/Row.md +171 -69
- package/bundle/components/Text.md +320 -0
- package/bundle/components/TextField.md +364 -97
- package/bundle/components/Title.md +296 -0
- package/bundle/guides/codestyle.md +38 -11
- package/bundle/guides/commits.md +119 -26
- package/bundle/guides/context.md +34 -30
- package/bundle/guides/stories.md +110 -40
- package/bundle/guides/template.md +3 -7
- package/bundle/guides/tests.md +48 -2
- package/bundle/manifest.json +275 -30
- package/bundle/release-notes/1.26.0.mdx +33 -2
- package/bundle/release-notes/1.27.0.mdx +43 -0
- package/bundle/release-notes/1.28.0.mdx +25 -0
- package/bundle/release-notes/1.29.0.mdx +47 -0
- package/bundle/release-notes/1.30.0.mdx +56 -0
- package/bundle/release-notes/1.31.0.mdx +52 -0
- package/bundle/release-notes/1.32.0.mdx +35 -0
- package/bundle/release-notes/1.33.0.mdx +61 -0
- package/bundle/release-notes/1.34.0.mdx +35 -0
- package/bundle/release-notes/1.35.0.mdx +21 -0
- package/bundle/release-notes/1.35.1.mdx +11 -0
- package/bundle/release-notes/1.36.0.mdx +21 -0
- package/bundle/release-notes/1.37.0.mdx +71 -0
- package/bundle/release-notes/1.38.0.mdx +36 -0
- package/bundle/release-notes/1.39.0.mdx +66 -0
- package/bundle/release-notes/1.40.0.mdx +27 -0
- package/bundle/release-notes/1.41.0.mdx +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: ListItem
|
|
3
|
+
category: List
|
|
4
|
+
related: [List, ListItemContent, ListActionItem, ListItemSelectable, ListTableItem, ListSortableItem]
|
|
5
|
+
tokens:
|
|
6
|
+
- --triplex-next-ListItem-Background
|
|
7
|
+
- --triplex-next-ListItem-Background_Selected
|
|
8
|
+
- --triplex-next-ListItem-Background_Hover
|
|
9
|
+
- --triplex-next-ListItem-BorderColor_Focus
|
|
10
|
+
stories: stories/List/ListItem.stories.tsx
|
|
11
|
+
version: "1.0"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# ListItem
|
|
15
|
+
|
|
16
|
+
## Назначение
|
|
17
|
+
|
|
18
|
+
Базовый элемент списка `<li>` — обёртка вокруг произвольного содержимого
|
|
19
|
+
(`ListItemContent`, `ListItemSelectable`, `SwipeableArea` и т.п.). Создаёт
|
|
20
|
+
React-контекст `ListItemContext` с состояниями `selected` и `selectable`:
|
|
21
|
+
`selected` управляет подсветкой `ListItemContent`, `selectable` сообщает
|
|
22
|
+
дочернему `ListItemContent`, что элемент выбираемый — для применения скругления
|
|
23
|
+
углов (`border-radius`). Оба флага пишутся `ListItemSelectable` через `useEffect`.
|
|
24
|
+
|
|
25
|
+
Используй `ListItem` когда: нужен произвольный layout строки списка.
|
|
26
|
+
Используй `ListTableItem` когда: нужна готовая табличная строка с support'ом
|
|
27
|
+
swipe-actions и selectable.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Варианты и props
|
|
32
|
+
|
|
33
|
+
### Опциональные props
|
|
34
|
+
|
|
35
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `children` | `React.ReactNode` | — | Содержимое строки |
|
|
38
|
+
| `...HTMLLIElementAttributes` | — | — | Все стандартные атрибуты `<li>` |
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Дизайн-токены
|
|
43
|
+
|
|
44
|
+
Сами стили `ListItem.tsx` пустые — токены применяются в подкомпонентах
|
|
45
|
+
(`ListItemContent`, `ListItemSelectable`, `ListActionItem`):
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
--triplex-next-ListItem-Background // фон по умолчанию (ListItemContent)
|
|
49
|
+
--triplex-next-ListItem-Background_Selected // фон, когда selected=true (ListItemContent)
|
|
50
|
+
--triplex-next-ListItem-Background_Hover // фон при hover на desktop (ListActionItem на ListItemContent)
|
|
51
|
+
--triplex-next-ListItem-BorderColor_Focus // цвет focus-обводки на desktop (ListActionItem)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Инварианты
|
|
57
|
+
|
|
58
|
+
- **`forwardRef`** — обязателен, target — `HTMLLIElement`. Не убирать.
|
|
59
|
+
- **`ListItemContext`** — провайдер на каждом `ListItem`. Не выносить наружу — context используется парой `ListItemSelectable` (writer для `selected` и `selectable`) ↔ `ListItemContent` (reader) внутри одной строки.
|
|
60
|
+
- **Поля контекста `selected` / `selectable`** — оба `boolean`, дефолт `false`. `selectable` всегда выставляется в `true` из `ListItemSelectable` (через `useEffect`), `selected` синхронизируется с одноимённым prop'ом `ListItemSelectable`. Сеттеры (`setSelected`, `setSelectable`) предназначены только для внутренних консьюмеров.
|
|
61
|
+
- **Корневой элемент `<li>`** — не менять. Семантика важна для accessibility.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Связанные компоненты
|
|
66
|
+
|
|
67
|
+
- `ListItemContent` — внутренняя обёртка для контента, читает `selected` из контекста.
|
|
68
|
+
- `ListActionItem` — самодостаточный интерактивный элемент: сам рендерит `ListItem` + `ListItemContent` (hover, focus по Tab, клик по всей строке — `onClick`, Enter/Space). Используется напрямую внутри `List`. Другие компоненты семейства его не используют.
|
|
69
|
+
- `ListItemSelectable` — добавляет чекбокс выбора, синхронизирует `selected` в контекст через `useEffect`.
|
|
70
|
+
- `ListItemLoading` — элемент-спиннер для пагинации (используется как последний элемент).
|
|
71
|
+
- `ListItemControls`, `ListItemControlsButton`, `ListItemControlsButtonDropdown` — кнопки действий, обычно внутри `SwipeableArea.rightSwipeableArea`.
|
|
72
|
+
- `ListItemTailLeft` / `ListItemTailRight` — декоративные хвосты для `SwipeableArea`.
|
|
73
|
+
- `ListTableItem` — комбинированная высокоуровневая обёртка.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Stories
|
|
78
|
+
|
|
79
|
+
Основные истории: `stories/List/ListItem.stories.tsx`
|
|
80
|
+
Файлы примеров: `stories/List/examples/ListItem/`
|
|
81
|
+
|
|
82
|
+
| Story | Example file | Что демонстрирует |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| `Default` | `Default.tsx` | Базовый элемент с произвольным контентом |
|
|
85
|
+
| `Action` | `Action.tsx` | Использование `ListActionItem` |
|
|
86
|
+
| `Loading` | `Loading.tsx` | `ListItemLoading` как последний элемент при пагинации |
|
|
87
|
+
| `Selectable` | `Selectable.tsx` | Использование `ListItemSelectable` внутри `ListItem` |
|
|
88
|
+
| `Swipeable` | `Swipeable.tsx` | `ListItem` внутри `SwipeableArea` с `ListItemControls` |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## История изменений
|
|
93
|
+
|
|
94
|
+
| Дата | Изменение |
|
|
95
|
+
|---|---|
|
|
96
|
+
| 2026-04-29 | Создан документ |
|
|
97
|
+
| 2026-05-21 | `ListItemContext` расширен полями `selectable` / `setSelectable`. Исправлен цвет токена `Background_Selected` в тёмной теме (`ColorDarkNeutral.10` → `ColorDarkNeutral.60`). |
|
|
98
|
+
| 2026-07-16 | Добавлен самодостаточный компонент `ListActionItem` (сам рендерит `ListItem` + `ListItemContent`; hover, focus по Tab, `onClick` + Enter/Space). Координация фона через контекст не понадобилась — `ListItemContext` без изменений. Другие компоненты семейства его не используют. |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Примеры использования
|
|
103
|
+
|
|
104
|
+
### Default
|
|
105
|
+
|
|
106
|
+
`stories/List/examples/ListItem/Default.tsx`
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import React from "react";
|
|
110
|
+
import { List, ListItem, ListItemContent } from "@sberbusiness/triplex-next";
|
|
111
|
+
|
|
112
|
+
export const Default = () => (
|
|
113
|
+
<div style={{ maxWidth: "500px" }}>
|
|
114
|
+
<List>
|
|
115
|
+
<ListItem>
|
|
116
|
+
<ListItemContent>Элемент списка</ListItemContent>
|
|
117
|
+
</ListItem>
|
|
118
|
+
</List>
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Action
|
|
124
|
+
|
|
125
|
+
`stories/List/examples/ListItem/Action.tsx`
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import React from "react";
|
|
129
|
+
import { List, ListActionItem } from "@sberbusiness/triplex-next";
|
|
130
|
+
|
|
131
|
+
export const Action = () => (
|
|
132
|
+
<div style={{ maxWidth: "500px" }}>
|
|
133
|
+
<List>
|
|
134
|
+
<ListActionItem listItemContentProps={{ onClick: () => alert("Клик по элементу списка") }}>
|
|
135
|
+
Элемент списка
|
|
136
|
+
</ListActionItem>
|
|
137
|
+
</List>
|
|
138
|
+
</div>
|
|
139
|
+
);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Loading
|
|
143
|
+
|
|
144
|
+
`stories/List/examples/ListItem/Loading.tsx`
|
|
145
|
+
|
|
146
|
+
```tsx
|
|
147
|
+
import React from "react";
|
|
148
|
+
import { List, ListItem, ListItemLoading } from "@sberbusiness/triplex-next";
|
|
149
|
+
|
|
150
|
+
export const Loading = () => (
|
|
151
|
+
<div style={{ maxWidth: "500px" }}>
|
|
152
|
+
<List>
|
|
153
|
+
<ListItem>
|
|
154
|
+
<ListItemLoading />
|
|
155
|
+
</ListItem>
|
|
156
|
+
</List>
|
|
157
|
+
</div>
|
|
158
|
+
);
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Selectable
|
|
162
|
+
|
|
163
|
+
`stories/List/examples/ListItem/Selectable.tsx`
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import React, { useState } from "react";
|
|
167
|
+
import { List, ListItem, ListItemContent, ListItemSelectable } from "@sberbusiness/triplex-next";
|
|
168
|
+
|
|
169
|
+
export const Selectable = () => {
|
|
170
|
+
const [selected, setSelected] = useState(false);
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div style={{ maxWidth: "500px" }}>
|
|
174
|
+
<List>
|
|
175
|
+
<ListItem>
|
|
176
|
+
<ListItemSelectable selected={selected} onSelect={setSelected}>
|
|
177
|
+
<ListItemContent>Элемент списка</ListItemContent>
|
|
178
|
+
</ListItemSelectable>
|
|
179
|
+
</ListItem>
|
|
180
|
+
</List>
|
|
181
|
+
</div>
|
|
182
|
+
);
|
|
183
|
+
};
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Swipeable
|
|
187
|
+
|
|
188
|
+
`stories/List/examples/ListItem/Swipeable.tsx`
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
import React from "react";
|
|
192
|
+
import {
|
|
193
|
+
ISwipeableAreaRef,
|
|
194
|
+
List,
|
|
195
|
+
ListItem,
|
|
196
|
+
ListItemContent,
|
|
197
|
+
ListItemControls,
|
|
198
|
+
ListItemControlsButton,
|
|
199
|
+
ListItemControlsButtonDropdown,
|
|
200
|
+
ListItemTailRight,
|
|
201
|
+
SwipeableArea,
|
|
202
|
+
} from "@sberbusiness/triplex-next";
|
|
203
|
+
import { DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
|
|
204
|
+
|
|
205
|
+
export const Swipeable = () => {
|
|
206
|
+
const options = [
|
|
207
|
+
{
|
|
208
|
+
id: "list-item-swipe-controls-dropdown-option-1",
|
|
209
|
+
label: "Текст пункта меню 1",
|
|
210
|
+
onSelect: () => alert("Выбран пункт меню 1."),
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: "list-item-swipe-controls-dropdown-option-2",
|
|
214
|
+
label: "Текст пункта меню 2",
|
|
215
|
+
onSelect: () => alert("Выбран пункт меню 2."),
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
id: "list-item-swipe-controls-dropdown-option-3",
|
|
219
|
+
label: "Текст пункта меню 3",
|
|
220
|
+
onSelect: () => alert("Выбран пункт меню 3."),
|
|
221
|
+
},
|
|
222
|
+
];
|
|
223
|
+
|
|
224
|
+
const ref = React.useRef<ISwipeableAreaRef>(null);
|
|
225
|
+
|
|
226
|
+
return (
|
|
227
|
+
<div style={{ maxWidth: "500px" }}>
|
|
228
|
+
<button
|
|
229
|
+
onClick={() => {
|
|
230
|
+
if (ref.current) {
|
|
231
|
+
ref.current.swipeLeft();
|
|
232
|
+
}
|
|
233
|
+
}}
|
|
234
|
+
>
|
|
235
|
+
swipe
|
|
236
|
+
</button>
|
|
237
|
+
<button
|
|
238
|
+
onClick={() => {
|
|
239
|
+
if (ref.current) {
|
|
240
|
+
ref.current.closeSwipe();
|
|
241
|
+
}
|
|
242
|
+
}}
|
|
243
|
+
>
|
|
244
|
+
close
|
|
245
|
+
</button>
|
|
246
|
+
<br />
|
|
247
|
+
|
|
248
|
+
<List>
|
|
249
|
+
<ListItem>
|
|
250
|
+
<SwipeableArea
|
|
251
|
+
ref={ref}
|
|
252
|
+
rightSwipeableArea={
|
|
253
|
+
<ListItemControls>
|
|
254
|
+
<ListItemControlsButton icon={<DefaulticonStrokePrdIcon20 paletteIndex={0} />}>
|
|
255
|
+
Button name
|
|
256
|
+
</ListItemControlsButton>
|
|
257
|
+
<ListItemControlsButtonDropdown
|
|
258
|
+
icon={<DefaulticonStrokePrdIcon20 paletteIndex={0} />}
|
|
259
|
+
options={options}
|
|
260
|
+
>
|
|
261
|
+
Button name
|
|
262
|
+
</ListItemControlsButtonDropdown>
|
|
263
|
+
</ListItemControls>
|
|
264
|
+
}
|
|
265
|
+
>
|
|
266
|
+
<ListItemTailRight />
|
|
267
|
+
{/* Минимальная высота, из-за блока Action с кнопками при свайпе. */}
|
|
268
|
+
<ListItemContent style={{ minHeight: "56px" }}>Свайп влево</ListItemContent>
|
|
269
|
+
</SwipeableArea>
|
|
270
|
+
</ListItem>
|
|
271
|
+
</List>
|
|
272
|
+
</div>
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
```
|
|
276
|
+
|
|
@@ -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>` или используй `ListTableItem` + `onClickItem`.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Связанные компоненты
|
|
75
|
+
|
|
76
|
+
- `ListItem` — родительский `<li>`, провайдер `ListItemContext`.
|
|
77
|
+
- `ListItemContent` — потребитель `ListItemContext.selected` для применения класса `selected`.
|
|
78
|
+
- `Checkbox` — встроенный чекбокс выбора.
|
|
79
|
+
- `ListTableItem` — использует `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` при монтировании. |
|