@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.
Files changed (73) hide show
  1. package/README.md +10 -0
  2. package/bundle/components/AlertContext.md +268 -0
  3. package/bundle/components/BodyPage.md +186 -0
  4. package/bundle/components/Button.md +93 -85
  5. package/bundle/components/ButtonDropdown.md +36 -70
  6. package/bundle/components/ButtonDropdownExtended.md +422 -0
  7. package/bundle/components/ButtonIcon.md +41 -48
  8. package/bundle/components/Caption.md +291 -0
  9. package/bundle/components/Checkbox.md +43 -122
  10. package/bundle/components/CheckboxXGroup.md +109 -46
  11. package/bundle/components/CheckboxYGroup.md +77 -49
  12. package/bundle/components/CodeText.md +197 -0
  13. package/bundle/components/Col.md +311 -162
  14. package/bundle/components/CollapsibleTree.md +584 -0
  15. package/bundle/components/CollapsibleTreeExtended.md +422 -0
  16. package/bundle/components/Dropdown.md +748 -346
  17. package/bundle/components/EmptyView.md +14 -15
  18. package/bundle/components/FooterPage.md +203 -0
  19. package/bundle/components/Gap.md +115 -57
  20. package/bundle/components/HeaderPage.md +226 -0
  21. package/bundle/components/HelpBox.md +45 -84
  22. package/bundle/components/ImageGallery.md +423 -0
  23. package/bundle/components/ImageGalleryExtended.md +606 -0
  24. package/bundle/components/LightBox.md +2252 -233
  25. package/bundle/components/List.md +216 -183
  26. package/bundle/components/ListActionItem.md +157 -0
  27. package/bundle/components/ListItem.md +276 -0
  28. package/bundle/components/ListItemControlsButton.md +103 -0
  29. package/bundle/components/ListItemControlsButtonDropdown.md +107 -0
  30. package/bundle/components/ListItemSelectable.md +99 -0
  31. package/bundle/components/ListItemTable.md +390 -0
  32. package/bundle/components/ListMaster.md +876 -156
  33. package/bundle/components/ListMasterFooter.md +80 -0
  34. package/bundle/components/ListMasterHeader.md +86 -0
  35. package/bundle/components/ListSortable.md +153 -0
  36. package/bundle/components/ListSortableItem.md +175 -0
  37. package/bundle/components/ListTableItem.md +391 -0
  38. package/bundle/components/ModalWindow.md +427 -237
  39. package/bundle/components/MonthYearField.md +145 -109
  40. package/bundle/components/Notification.md +625 -155
  41. package/bundle/components/Overlay.md +271 -170
  42. package/bundle/components/Page.md +284 -186
  43. package/bundle/components/Pagination.md +206 -229
  44. package/bundle/components/Portal.md +131 -67
  45. package/bundle/components/Row.md +171 -69
  46. package/bundle/components/Text.md +320 -0
  47. package/bundle/components/TextField.md +364 -97
  48. package/bundle/components/Title.md +296 -0
  49. package/bundle/guides/codestyle.md +38 -11
  50. package/bundle/guides/commits.md +119 -26
  51. package/bundle/guides/context.md +34 -30
  52. package/bundle/guides/stories.md +110 -40
  53. package/bundle/guides/template.md +3 -7
  54. package/bundle/guides/tests.md +48 -2
  55. package/bundle/manifest.json +275 -30
  56. package/bundle/release-notes/1.26.0.mdx +33 -2
  57. package/bundle/release-notes/1.27.0.mdx +43 -0
  58. package/bundle/release-notes/1.28.0.mdx +25 -0
  59. package/bundle/release-notes/1.29.0.mdx +47 -0
  60. package/bundle/release-notes/1.30.0.mdx +56 -0
  61. package/bundle/release-notes/1.31.0.mdx +52 -0
  62. package/bundle/release-notes/1.32.0.mdx +35 -0
  63. package/bundle/release-notes/1.33.0.mdx +61 -0
  64. package/bundle/release-notes/1.34.0.mdx +35 -0
  65. package/bundle/release-notes/1.35.0.mdx +21 -0
  66. package/bundle/release-notes/1.35.1.mdx +11 -0
  67. package/bundle/release-notes/1.36.0.mdx +21 -0
  68. package/bundle/release-notes/1.37.0.mdx +71 -0
  69. package/bundle/release-notes/1.38.0.mdx +36 -0
  70. package/bundle/release-notes/1.39.0.mdx +66 -0
  71. package/bundle/release-notes/1.40.0.mdx +27 -0
  72. package/bundle/release-notes/1.41.0.mdx +7 -0
  73. package/package.json +1 -1
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  component: Button
3
3
  category: Buttons
4
- figma-node: "1-328"
5
- figma-file: "https://www.figma.com/design/MeAqaaLV9acAgoBOkZC9C2/-W--LIB-DSN-01-Components-DCB-Next-v.1.3.0"
6
4
  related: [ButtonIcon, ButtonDropdown, ButtonDropdownExtended]
7
5
  tokens:
8
6
  - --triplex-next-Button-General_Background_Default
@@ -64,42 +62,17 @@ version: "1.0"
64
62
 
65
63
  ---
66
64
 
67
- ## Файловая структура
68
-
69
- ```text
70
- src/components/Button/
71
- ├── Button.tsx # Основной компонент, union type TButtonProps
72
- ├── ButtonBase.tsx # Базовый <button>, extends HTML attrs
73
- ├── ButtonIcon.tsx # Иконочная кнопка (squircle / circle)
74
- ├── ButtonDropdown.tsx # Кнопка с выпадающим меню
75
- ├── ButtonDropdownExtended.tsx # Контейнер с кастомным dropdown
76
- ├── enums.ts # EButtonTheme, EButtonDotsTheme, EButtonIconShape
77
- ├── index.ts # Barrel exports
78
- └── styles/
79
- ├── Button.module.less # Размеры, block, loading, base layout
80
- ├── ButtonGeneral.module.less # Тема GENERAL
81
- ├── ButtonSecondary.module.less
82
- ├── ButtonSecondaryLight.module.less
83
- ├── ButtonDanger.module.less
84
- ├── ButtonLink.module.less # Тема LINK — нет min-width, нет bg
85
- ├── ButtonIcon.module.less # Стили ButtonIcon
86
- ├── ButtonDropdown.module.less
87
- └── ButtonDropdownExtended.module.less
88
- ```
89
-
90
- ---
91
-
92
65
  ## Варианты и props
93
66
 
94
67
  ### Темы (`EButtonTheme`)
95
68
 
96
- | Значение | Описание | Поддерживает loading/icon/block |
97
- |---|---|---|
98
- | `GENERAL` | Основной стиль (primary) | Да |
99
- | `SECONDARY` | Вторичный | Да |
100
- | `SECONDARY_LIGHT` | Вторичный светлый (для тёмных фонов) | Да |
101
- | `DANGER` | Деструктивное действие | Да |
102
- | `LINK` | Текстовая ссылка | Нет — `loading`, `icon`, `block` запрещены через `never` |
69
+ | Значение | Описание |
70
+ |---|---|
71
+ | `GENERAL` | Основной стиль (primary) |
72
+ | `SECONDARY` | Вторичный |
73
+ | `SECONDARY_LIGHT` | Вторичный светлый (для тёмных фонов) |
74
+ | `DANGER` | Деструктивное действие |
75
+ | `LINK` | Текстовая ссылка |
103
76
 
104
77
  ### Размеры (`EComponentSize`)
105
78
 
@@ -109,17 +82,22 @@ src/components/Button/
109
82
  | `MD` | 40px | 0 20px | 8px | 14px |
110
83
  | `LG` | 56px | 0 24px | 10px | 16px |
111
84
 
112
- ### Props компонента `Button`
85
+ ### Обязательные props (`Button`)
86
+
87
+ | Prop | Тип | Описание |
88
+ |---|---|---|
89
+ | `theme` | `EButtonTheme` | Визуальный стиль |
90
+
91
+ ### Опциональные props (`Button`)
113
92
 
114
- | Prop | Тип | Обязателен | Описание |
93
+ | Prop | Тип | По умолчанию | Описание |
115
94
  |---|---|---|---|
116
- | `theme` | `EButtonTheme` | Да | Визуальный стиль |
117
- | `size` | `EComponentSize` | Да | Размер |
118
- | `block` | `boolean` | Нет | Полноширинный режим (только не-LINK темы) |
119
- | `loading` | `boolean` | Нет | Состояние загрузки: скрывает контент, показывает спиннер (только не-LINK темы) |
120
- | `icon` | `React.ReactElement` | Нет | Иконка слева от текста; если без `children` — кнопка становится квадратной |
121
- | `children` | `React.ReactNode` | Нет | Текст кнопки |
122
- | `...HTMLButtonAttributes` | — | — | Все стандартные атрибуты `<button>` |
95
+ | `size` | `EComponentSize` | `MD` | Размер |
96
+ | `block` | `boolean` | `false` | Полноширинный режим |
97
+ | `loading` | `boolean` | `false` | Состояние загрузки: скрывает контент через `visibility: hidden`, показывает спиннер, ставит `tabIndex={-1}` |
98
+ | `icon` | `React.ReactElement` | — | Иконка слева от текста; если без `children` — кнопка становится квадратной (icon-only) |
99
+ | `children` | `React.ReactNode` | — | Текст кнопки |
100
+ | `...HTMLButtonAttributes` | — | — | Все стандартные атрибуты `<button>`, включая `aria-expanded` (см. Accessibility) |
123
101
 
124
102
  ### Props компонента `ButtonIcon`
125
103
 
@@ -129,45 +107,11 @@ src/components/Button/
129
107
  | `active` | `boolean` | `false` | Визуальное активное состояние |
130
108
  | `...HTMLButtonAttributes` | — | — | Включая `disabled` |
131
109
 
132
- ---
133
-
134
- ## Ключевые особенности реализации
135
-
136
- ### Иконка без текста
137
- Если передан `icon` без `children` — добавляется класс `.icon`, который делает кнопку квадратной:
138
- ```tsx
139
- // Button.tsx — логика определения icon-only режима
140
- const iconOnly = Boolean(icon) && !children;
141
- <button className={clsx(styles.button, { [styles.icon]: iconOnly })}>
142
- ```
143
-
144
- ### Состояние загрузки
145
- - `loading` скрывает контент через `visibility: hidden` (не `display: none`) — сохраняет размеры,
146
- - устанавливает `tabIndex={-1}` — кнопка недоступна с клавиатуры
147
- - Тема лоадера: `SECONDARY` и `SECONDARY_LIGHT` → `ELoaderSmallTheme.BRAND`, остальные → `ELoaderSmallTheme.NEUTRAL`
110
+ ### Ограничения по темам
148
111
 
149
- ### `aria-expanded` управляет визуалом
150
- Состояние "раскрыто" (например, когда кнопка открывает dropdown) управляется через `aria-expanded`:
151
- ```tsx
152
- <Button aria-expanded={true} ...> → добавляет CSS-классы .expanded и .active
153
- ```
154
- Отдельного prop `expanded` нет — используй стандартный HTML-атрибут.
155
-
156
- ### Тема LINK
157
- - Нет `min-width`
158
- - `background: transparent`
159
- - `padding` по вертикали отличается от других тем (меньше)
160
- - `block`, `loading`, `icon` — тип `never` в интерфейсе, TypeScript запрещает передачу
161
-
162
- ---
163
-
164
- ## Accessibility
165
-
166
- - Нативный `<button>` — полная поддержка клавиатуры (Tab, Enter, Space) без дополнительных атрибутов.
167
- - **`ButtonIcon`**: иконочная кнопка без видимого текста — потребитель **обязан** передать `aria-label` через `...rest`. Библиотека мультиязычная, текст не хардкодится.
168
- - **`loading`**: устанавливает `tabIndex={-1}` — кнопка исключается из tab-порядка. Если нужна доступность состояния загрузки для скринридеров, потребитель добавляет `aria-busy="true"` через props.
169
- - **`aria-expanded`**: управляет визуальным состоянием "раскрыто" (добавляет CSS-классы `.expanded`, `.active`). Передаётся потребителем при использовании кнопки как триггера dropdown.
170
- - Фокус-стиль через `:focus-visible` — виден только при клавиатурной навигации.
112
+ - `block`, `loading`, `icon` недоступны для темы `LINK` — тип `never` в интерфейсе, TypeScript запрещает передачу.
113
+ - Тема `LINK` не имеет `min-width`, фона (`background: transparent`) и использует уменьшенный вертикальный `padding`.
114
+ - Тема лоадера (`loading`) для `SECONDARY` и `SECONDARY_LIGHT` — `ELoaderSmallTheme.BRAND`, для остальных — `ELoaderSmallTheme.NEUTRAL`.
171
115
 
172
116
  ---
173
117
 
@@ -175,12 +119,12 @@ const iconOnly = Boolean(icon) && !children;
175
119
 
176
120
  Паттерн: `--triplex-next-Button-{Theme}_{Property}_{State}`
177
121
 
178
- Каждая тема (кроме LINK) имеет полный набор:
122
+ Каждая тема (кроме `LINK`) имеет полный набор:
179
123
  - `_Background_Default/Hover/Active/Disabled`
180
124
  - `_Color_Default/Hover/Active/Disabled`
181
125
  - `_Shadow_Focus`
182
126
 
183
- Тема LINK — только `_Color_*` и `_Shadow_Focus` (нет фона).
127
+ Тема `LINK` — только `_Color_*` и `_Shadow_Focus` (нет фона).
184
128
 
185
129
  При добавлении нового визуального состояния нужен новый токен в `src/generated/themesCssVariables.css`.
186
130
 
@@ -192,7 +136,17 @@ const iconOnly = Boolean(icon) && !children;
192
136
  - **`TButtonProps` union type** — должен включать все тематические интерфейсы. При добавлении новой темы — добавь интерфейс в union.
193
137
  - **`EButtonTheme` значения** — не переименовывать. Это публичное API.
194
138
  - **`EComponentSize`** — общий enum из `src/enums/EComponentSize`, не делай локальный аналог.
195
- - **Размеры (28px/40px/56px)** — не менять без согласования с дизайнером, другие компоненты ориентируются на эти размеры.
139
+ - **Размеры (28px / 40px / 56px)** — не менять без согласования с дизайнером, другие компоненты ориентируются на эти размеры.
140
+
141
+ ---
142
+
143
+ ## Accessibility
144
+
145
+ - Нативный `<button>` — полная поддержка клавиатуры (Tab, Enter, Space) без дополнительных атрибутов.
146
+ - **`ButtonIcon`**: иконочная кнопка без видимого текста — потребитель **обязан** передать `aria-label` через `...rest`. Библиотека мультиязычная, текст не хардкодится.
147
+ - **`loading`**: устанавливает `tabIndex={-1}` — кнопка исключается из tab-порядка. Если нужна доступность состояния загрузки для скринридеров, потребитель добавляет `aria-busy="true"` через props.
148
+ - **`aria-expanded`**: управляет визуальным состоянием «раскрыто» (добавляет CSS-классы `.expanded`, `.active`). Раскрытым считается только значение `true` или `"true"` — строковое `"false"` трактуется как закрытое состояние (тип атрибута `Booleanish`). Передаётся потребителем при использовании кнопки как триггера dropdown. Отдельного prop `expanded` нет — используй стандартный HTML-атрибут.
149
+ - Фокус-стиль через `:focus-visible` — виден только при клавиатурной навигации.
196
150
 
197
151
  ---
198
152
 
@@ -208,7 +162,7 @@ const iconOnly = Boolean(icon) && !children;
208
162
 
209
163
  ## Stories
210
164
 
211
- `stories/Buttons/Button.stories.tsx`
165
+ Основные истории: `stories/Buttons/Button.stories.tsx`
212
166
  Файлы примеров: `stories/Buttons/examples/Button/`
213
167
 
214
168
  | Story | Example file | Что демонстрирует |
@@ -219,7 +173,9 @@ const iconOnly = Boolean(icon) && !children;
219
173
  | `Sizes` | `SizesExample.tsx` | SM / MD / LG для всех тем |
220
174
  | `Themes` | `ThemesExample.tsx` | Все пять тем |
221
175
  | `WithIcon` | `WithIconExample.tsx` | Icon-only и text+icon |
176
+ | `WithNotificationIcon` | `WithNotificationIconExample.tsx` | Иконка с индикатором уведомления |
222
177
  | `BlockMode` | `BlockModeExample.tsx` | Полноширинный режим |
178
+ | `TextWithIcon` | `TextWithIconExample.tsx` | Текст вместе с иконкой |
223
179
 
224
180
  ---
225
181
 
@@ -228,6 +184,10 @@ const iconOnly = Boolean(icon) && !children;
228
184
  | Дата | Изменение |
229
185
  |---|---|
230
186
  | 2026-03-31 | Создан документ (пилот AI-Ready) |
187
+ | 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убраны секции «Файловая структура» и «Ключевые особенности реализации», переструктурированы props, добавлена колонка `Example file` в таблице Stories |
188
+ | 2026-07-15 | Добавлен `vertical-align: middle` корневому классу `.button` — icon-only кнопка (`icon` без `children`) смещалась по вертикали относительно соседней текстовой кнопки из-за baseline-выравнивания inline-элементов; `middle` также центрирует кнопку относительно строки инлайн-текста |
189
+ | 2026-07-28 | AI-рефакторинг (TRI-13): codestyle-чистка `Button.tsx` (JSDoc компонента, поясняющие комментарии, эквивалентные упрощения в `clsx`), unit-тесты расширены с 10 до 24 кейсов; публичный API и поведение не изменены |
190
+ | 2026-07-28 | Правки по ревью PR #481 (TRI-13): исправлена трактовка строкового `aria-expanded="false"` (больше не считается раскрытым состоянием); `size` стал опциональным с default `EComponentSize.MD` (типы приведены в соответствие с реализацией); `ButtonBase` убран из barrel-экспорта `index.ts` — импорт только по прямому пути `components/Button/ButtonBase` |
231
191
 
232
192
  ---
233
193
 
@@ -475,6 +435,27 @@ export const WithIconExample = () => (
475
435
  );
476
436
  ```
477
437
 
438
+ ### WithNotificationIcon
439
+
440
+ `stories/Buttons/examples/Button/WithNotificationIconExample.tsx`
441
+
442
+ ```tsx
443
+ import React from "react";
444
+ import { Badge, Button, EButtonTheme, EComponentSize } from "@sberbusiness/triplex-next";
445
+ import { BellStrokeNavIcon20 } from "@sberbusiness/icons-next";
446
+
447
+ export const WithNotificationIconExample = () => (
448
+ <div style={{ position: "relative", display: "inline-flex" }}>
449
+ <Button
450
+ icon={<BellStrokeNavIcon20 paletteIndex={0} />}
451
+ size={EComponentSize.MD}
452
+ theme={EButtonTheme.SECONDARY}
453
+ />
454
+ <Badge.Dot size={EComponentSize.MD} style={{ position: "absolute", top: 4, right: 4 }} />
455
+ </div>
456
+ );
457
+ ```
458
+
478
459
  ### BlockMode
479
460
 
480
461
  `stories/Buttons/examples/Button/BlockModeExample.tsx`
@@ -508,3 +489,30 @@ export const BlockModeExample = () => (
508
489
  );
509
490
  ```
510
491
 
492
+ ### TextWithIcon
493
+
494
+ `stories/Buttons/examples/Button/TextWithIconExample.tsx`
495
+
496
+ ```tsx
497
+ import React from "react";
498
+ import { DefaulticonStrokePrdIcon16, DefaulticonStrokePrdIcon20 } from "@sberbusiness/icons-next";
499
+ import { Button, EButtonTheme, EComponentSize } from "@sberbusiness/triplex-next";
500
+
501
+ export const TextWithIconExample = () => (
502
+ <div style={{ display: "flex", alignItems: "flex-start", gap: 16 }}>
503
+ <Button theme={EButtonTheme.LINK} size={EComponentSize.SM}>
504
+ <DefaulticonStrokePrdIcon16 paletteIndex={5} />
505
+ <span style={{ marginLeft: 8 }}>Button text</span>
506
+ </Button>
507
+ <Button theme={EButtonTheme.LINK} size={EComponentSize.MD}>
508
+ <DefaulticonStrokePrdIcon20 paletteIndex={5} />
509
+ <span style={{ marginLeft: 8 }}>Button text</span>
510
+ </Button>
511
+ <Button theme={EButtonTheme.LINK} size={EComponentSize.LG}>
512
+ <DefaulticonStrokePrdIcon20 paletteIndex={5} />
513
+ <span style={{ marginLeft: 8 }}>Button text</span>
514
+ </Button>
515
+ </div>
516
+ );
517
+ ```
518
+
@@ -1,8 +1,6 @@
1
1
  ---
2
2
  component: ButtonDropdown
3
3
  category: Buttons
4
- figma-node: ""
5
- figma-file: ""
6
4
  related: [Button, ButtonDropdownExtended, Dropdown]
7
5
  tokens: []
8
6
  stories: stories/Buttons/ButtonDropdown.stories.tsx
@@ -13,25 +11,10 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Кнопка-триггер с выпадающим списком действий.
17
- Поддерживает два визуальных режима: обычная кнопка (`EButtonTheme`) и dots-вариант (`EButtonDotsTheme`).
14
+ Кнопка-триггер с выпадающим списком действий. Поддерживает два визуальных режима: обычная кнопка (`EButtonTheme`) и dots-вариант (`EButtonDotsTheme`).
18
15
 
19
16
  Используй когда: нужно сгруппировать несколько действий под один триггер и дать выбор опции из списка.
20
- Не используй когда: нужна одиночная кнопка без списка - используй `Button`.
21
-
22
- ---
23
-
24
- ## Файловая структура
25
-
26
- ```text
27
- src/components/Button/
28
- ├── ButtonDropdown.tsx # Основной компонент (forwardRef, рендер button + dropdown)
29
- ├── ButtonDropdownExtended.tsx # Базовый контейнер с контролем opened/close и outside click
30
- ├── styles/
31
- │ ├── ButtonDropdown.module.less # Стили caret, active-состояния, block-режима
32
- │ └── ButtonDropdownExtended.module.less
33
- └── index.ts # Публичный экспорт ButtonDropdown
34
- ```
17
+ Не используй когда: нужна одиночная кнопка без списка — используй `Button`.
35
18
 
36
19
  ---
37
20
 
@@ -49,18 +32,16 @@ src/components/Button/
49
32
 
50
33
  | Prop | Тип | По умолчанию | Описание |
51
34
  |---|---|---|---|
52
- | `children` | `React.ReactNode` | `undefined` | Текст/контент кнопки (используется также в mobile header) |
53
- | `selected` | `IButtonDropdownOption` | `undefined` | Предвыбранная опция для подсветки в списке |
35
+ | `children` | `React.ReactNode` | — | Текст/контент кнопки (используется также в mobile header) |
36
+ | `selected` | `IButtonDropdownOption` | — | Предвыбранная опция для подсветки в списке |
54
37
  | `disabled` | `boolean` | `false` | Блокирует кнопку и открытие списка |
55
- | `buttonAttributes` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | `undefined` | Дополнительные HTML-атрибуты нативной кнопки |
56
- | `block` | `boolean` | `false` | Доступен только для non-dots тем |
38
+ | `buttonAttributes` | `React.ButtonHTMLAttributes<HTMLButtonElement>` | — | Дополнительные HTML-атрибуты нативной кнопки (включая `aria-label`) |
39
+ | `dropdownAttributes` | `React.HTMLAttributes<HTMLDivElement> & DataAttributes` | — | HTML-атрибуты выпадающего блока, включая `data-*`; `className` мержится с внутренними классами; применяется в desktop-отображении |
40
+ | `block` | `boolean` | `false` | Полноширинный режим (только для non-dots тем) |
41
+ | `opened` | `boolean` | — | Управляемое состояние открытости dropdown (controlled-режим); задаётся в паре с `setOpened`, без него состояние зафиксировано |
42
+ | `setOpened` | `(opened: boolean) => void` | — | Обработчик изменения состояния открытости (пара к `opened`) |
57
43
  | `className` | `string` | — | Дополнительный CSS-класс контейнера |
58
- | `...rest` | `React.HTMLAttributes<HTMLDivElement>` | — | Атрибуты корневого `div` компонента |
59
-
60
- ### Ограничения по темам
61
-
62
- - Для `EButtonDotsTheme` prop `block` запрещен типизацией (`never`).
63
- - Dots-режим использует иконку `Dotshorizontal*` вместо текстового контента кнопки.
44
+ | `...rest` | `React.HTMLAttributes<HTMLDivElement>` | — | Атрибуты корневого `<div>` компонента |
64
45
 
65
46
  ### Структура опции (`IButtonDropdownOption`)
66
47
 
@@ -69,50 +50,19 @@ src/components/Button/
69
50
  | `id` | `string` | Уникальный идентификатор опции |
70
51
  | `label` | `React.ReactNode` | Видимый контент пункта меню |
71
52
  | `onSelect` | `() => void` | Callback выбора опции |
72
- | `...rest` | `IDropdownListItemProps` (без ряда запрещенных полей) | Остальные настройки `DropdownList.Item` |
73
-
74
- ---
75
-
76
- ## Ключевые особенности реализации
77
-
78
- ### Композиция через `ButtonDropdownExtended`
79
-
80
- - `ButtonDropdown` делегирует управление opened-state и close-on-outside в `ButtonDropdownExtended`.
81
- - Передает две render-функции: `renderButton` и `renderDropdown`.
82
-
83
- ### Desktop + mobile dropdown
84
-
85
- - Desktop: рендерится `DropdownList` с `DropdownList.Item`.
86
- - Mobile: через `mobileViewProps` рендерится `DropdownMobileHeader` + `DropdownMobileList`.
87
- - После выбора любого пункта вызывается `option.onSelect?.()` и dropdown закрывается.
53
+ | `...rest` | `IDropdownListItemProps` (без ряда запрещённых полей) | Остальные настройки `DropdownList.Item` |
88
54
 
89
- ### Управление клавиатурой
90
-
91
- - На кнопке перехватываются `Space`, `ArrowUp`, `ArrowDown` с `preventDefault`.
92
- - `ArrowUp/ArrowDown` открывают dropdown, если он закрыт.
93
- - В `ButtonDropdownExtended` dropdown закрывается по `Escape` и (из-за `closeOnTab`) по `Tab`.
94
-
95
- ### ARIA-связка trigger/list
96
-
97
- - Кнопка получает `aria-haspopup="menu"`, `aria-expanded`, `aria-controls`.
98
- - `aria-controls` и `DropdownList` связываются через `instanceId` (`uniqueId()`).
99
- - `aria-activedescendant` синхронизируется через `DropdownListContext`.
100
-
101
- ---
102
-
103
- ## Accessibility
55
+ ### Ограничения по темам
104
56
 
105
- - Триггер строится на `Button` (нативный `button`), базовая keyboard-навигация сохраняется.
106
- - Компонент не хардкодит aria-тексты: при необходимости `aria-label` нужно передавать через `buttonAttributes`.
107
- - На mobile-заголовке dropdown отображается `children` триггера; если в продукте нужен локализованный отдельный заголовок, его нужно задавать на уровне композиции (через `ButtonDropdownExtended`).
108
- - Для корректной доступности меню потребитель должен передавать понятные `label` для `options`.
57
+ - Для `EButtonDotsTheme` prop `block` запрещён типизацией (`never`).
58
+ - Dots-режим использует иконку `Dotshorizontal*` вместо текстового контента кнопки.
59
+ - Desktop рендерит `DropdownList` с `DropdownList.Item`; mobile через `mobileViewProps` рендерит `DropdownMobileHeader` + `DropdownMobileList`.
109
60
 
110
61
  ---
111
62
 
112
63
  ## Дизайн-токены
113
64
 
114
- `ButtonDropdown` не использует собственных CSS color-токенов в `ButtonDropdown.module.less`.
115
- Визуальные токены берутся из `Button` и `Dropdown`, которые рендерятся внутри.
65
+ `ButtonDropdown` не использует собственных CSS color-токенов. Визуальные токены берутся из `Button` и `Dropdown`, которые рендерятся внутри.
116
66
 
117
67
  ---
118
68
 
@@ -126,17 +76,27 @@ src/components/Button/
126
76
 
127
77
  ---
128
78
 
79
+ ## Accessibility
80
+
81
+ - Триггер строится на `Button` (нативный `<button>`), базовая keyboard-навигация сохраняется.
82
+ - Кнопка получает `aria-haspopup="menu"`, `aria-expanded`, `aria-controls`. Связка trigger/list осуществляется через `instanceId` (`uniqueId()`); `aria-activedescendant` синхронизируется через `DropdownListContext`.
83
+ - На кнопке перехватываются `Space`, `ArrowUp`, `ArrowDown` с `preventDefault` (сравнение по `event.code`, как в `ButtonDropdownExtended`). `Space` явно переключает dropdown (нативная click-активация отменена `preventDefault`), `ArrowUp` / `ArrowDown` открывают его, если закрыт. Dropdown закрывается по `Escape` и (из-за `closeOnTab`) по `Tab`.
84
+ - Компонент **не хардкодит** aria-тексты: при необходимости `aria-label` нужно передавать через `buttonAttributes`. Для корректной доступности меню потребитель должен передавать понятные `label` для `options`.
85
+ - На mobile-заголовке dropdown отображается `children` триггера; если в продукте нужен локализованный отдельный заголовок, его нужно задавать на уровне композиции (через `ButtonDropdownExtended`).
86
+
87
+ ---
88
+
129
89
  ## Связанные компоненты
130
90
 
131
- - `Button` (`src/components/Button/Button.tsx`) - базовый триггер, на котором построен `ButtonDropdown`.
132
- - `ButtonDropdownExtended` (`src/components/Button/ButtonDropdownExtended.tsx`) - управляет открытием/закрытием dropdown.
133
- - `Dropdown` (`src/components/Dropdown`) - контейнер и пункты списка для desktop/mobile представления.
91
+ - `Button` (`src/components/Button/Button.tsx`) — базовый триггер, на котором построен `ButtonDropdown`.
92
+ - `ButtonDropdownExtended` (`src/components/Button/ButtonDropdownExtended.tsx`) — управляет открытием/закрытием dropdown через render-функции `renderButton` и `renderDropdown`.
93
+ - `Dropdown` (`src/components/Dropdown`) — контейнер и пункты списка для desktop/mobile представления.
134
94
 
135
95
  ---
136
96
 
137
97
  ## Stories
138
98
 
139
- `stories/Buttons/ButtonDropdown.stories.tsx`
99
+ Основные истории: `stories/Buttons/ButtonDropdown.stories.tsx`
140
100
  Файлы примеров: `stories/Buttons/examples/ButtonDropdown/`
141
101
 
142
102
  | Story | Example file | Что демонстрирует |
@@ -157,6 +117,12 @@ src/components/Button/
157
117
  | Дата | Изменение |
158
118
  |---|---|
159
119
  | 2026-04-15 | Создан документ AI-ready для `ButtonDropdown`. |
120
+ | 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убраны секции «Файловая структура» и «Ключевые особенности реализации», их содержимое перенесено в `Ограничения по темам` и `Accessibility`, добавлена колонка `Example file`. |
121
+ | 2026-07-09 | Добавлено свойство `dropdownAttributes` — HTML-атрибуты выпадающего блока (в том числе возможность поднять `z-index` через `style`). |
122
+ | 2026-07-15 | В `ButtonDropdownExtended` `vertical-align: top` заменён на `middle` (синхронно с `Button`) — общая опорная точка для кнопок разной высоты и центрирование относительно строки инлайн-текста. |
123
+ | 2026-07-28 | AI-рефакторинг: dots- и обычный триггер объединены в один `renderButton` (общая a11y-обвязка), тема кнопки и палитра каретки выведены через мапы вместо `as`-каста и `switch`, удалено обращение к несуществующему CSS-классу `buttonDropdownMenu` (в LESS его не было, в сборке значение было `undefined`). Публичный API и разметка не изменились. Unit-тесты расширены до 32 кейсов. |
124
+ | 2026-07-29 | Правки по ревью PR #482: типы триггера и props-интерфейсы вариантов теперь экспортируются (`TButtonDropdownButtonTheme`, `TButtonDropdownTheme`, `IButtonDropdownBaseProps`, `IButtonDotsProps`) — по конвенции все типы barrel-компонентов публичны; поведение не изменилось. |
125
+ | 2026-07-29 | Отработка находок AI-рефакторинга: починен перехват пробела на триггере (сравнение по `event.code`; `Space` явно переключает dropdown), `label` опции больше не утекает в DOM-атрибут элемента списка, легализован controlled-режим — публичные props `opened` / `setOpened` (ранее `opened` работал только через нетипизированный spread). |
160
126
 
161
127
  ---
162
128