@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,226 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: HeaderPage
|
|
3
|
+
category: Page
|
|
4
|
+
related: [Page, BodyPage, FooterPage, Header, Island, LightBox]
|
|
5
|
+
tokens: [--triplex-next-HeaderPage-StickyShadow]
|
|
6
|
+
stories: stories/Page/HeaderPage/HeaderPage.stories.tsx
|
|
7
|
+
version: "1.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# HeaderPage
|
|
11
|
+
|
|
12
|
+
## Назначение
|
|
13
|
+
|
|
14
|
+
Заголовок страницы `Page`. Доступен как статическое свойство `Page.Header`. Верхний блок страницы
|
|
15
|
+
с заголовком, табами и подзаголовком, располагается над `Page.Body`.
|
|
16
|
+
|
|
17
|
+
Контент строится через составные части `Page.Header`: `Page.Header.Title` (с областями `Content`
|
|
18
|
+
и `Controls`), `Page.Header.Tabs` (с областями `Content` и `Controls`), `Page.Header.Subhead` и
|
|
19
|
+
`Page.Header.LayoutSidebar` (с областями `Content` и `Sidebar`).
|
|
20
|
+
|
|
21
|
+
Используй когда: нужен верхний блок страницы с заголовком и действиями — как в карточке (Island),
|
|
22
|
+
так и без неё; а также прилипающий к верху заголовок внутри `LightBox`.
|
|
23
|
+
Не используй когда: нужно тело или футер страницы — для этого есть `Page.Body` / `Page.Footer`.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Варианты и props
|
|
28
|
+
|
|
29
|
+
Публичный API — discriminated union по `type`: `IHeaderPageTypeFirstProps | IHeaderPageTypeSecondProps`.
|
|
30
|
+
Оба интерфейса расширяют `IHeaderProps` (≈ `React.HTMLAttributes<HTMLDivElement>`).
|
|
31
|
+
|
|
32
|
+
### Обязательные props
|
|
33
|
+
|
|
34
|
+
| Prop | Тип | Описание |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| `type` | `EHeaderPageType` | `FIRST` — заголовок оборачивается в `Island` (карточка с белым фоном и тенью). `SECOND` — заголовок без карточки. |
|
|
37
|
+
| `children` | `React.ReactNode` | Контент заголовка страницы. |
|
|
38
|
+
|
|
39
|
+
### Опциональные props
|
|
40
|
+
|
|
41
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
42
|
+
|---|---|---|---|
|
|
43
|
+
| `sticky` | `boolean` | `false` | Заголовок прилипает к верхней границе при скролле. **Только для `type=FIRST`** (внутри `LightBox`); для `type=SECOND` типизирован как `never`. |
|
|
44
|
+
| `size` | `EComponentSize` | — | Размер острова (Island). **Доступен только для `type=FIRST`**; для `type=SECOND` типизирован как `never`. |
|
|
45
|
+
|
|
46
|
+
### Ограничения по типам
|
|
47
|
+
|
|
48
|
+
- `size` и `sticky` доступны только при `type=FIRST` (в `SECOND` контент не оборачивается в Island,
|
|
49
|
+
поэтому оба типизированы как `never`).
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Дизайн-токены
|
|
54
|
+
|
|
55
|
+
| Токен | Назначение |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `--triplex-next-HeaderPage-StickyShadow` | Тень прилипшего заголовка (когда `sticky` и заголовок коснулся верхней границы, `data-stuck="true"`). |
|
|
58
|
+
|
|
59
|
+
Внешний вид карточки наследуется от `Island` (`EIslandType.TYPE_1`). Радиус верхних углов при
|
|
60
|
+
прилипании плавно обнуляется через CSS-переменную `--r-top` (управляется хуком
|
|
61
|
+
`useStickyCornerRadius` с `edge="top"`).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Инварианты
|
|
66
|
+
|
|
67
|
+
- `forwardRef<HTMLDivElement>` — не убирать. Ref всегда указывает на корневой элемент
|
|
68
|
+
(Island для FIRST, Header для SECOND).
|
|
69
|
+
- Ручной merge ref (`setIslandRef`) обязателен: ref нужен одновременно хуку
|
|
70
|
+
`useStickyCornerRadius` (внутренний `islandRef`) и наружу (проброшенный `ref`). Не упрощать.
|
|
71
|
+
- `displayName = "HeaderPage"` — не менять.
|
|
72
|
+
- `HeaderPage` собран через `Object.assign(forwardRef(...), { LayoutSidebar, Subhead, Tabs, Title })` —
|
|
73
|
+
статические свойства (= `Header.LayoutSidebar` / `Header.Subhead` / `Header.Tabs` / `Header.Title`)
|
|
74
|
+
должны сохраняться.
|
|
75
|
+
- Discriminated union по `type` и значения `EHeaderPageType` — часть публичного API, менять нельзя.
|
|
76
|
+
- Экспорты `HeaderPage`, `IHeaderPageTypeFirstProps`, `IHeaderPageTypeSecondProps` идут в barrel
|
|
77
|
+
`src/components/Page/index.ts` — сохранять.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Accessibility
|
|
82
|
+
|
|
83
|
+
Особого a11y-поведения нет — это структурный контейнер. Семантику и aria-атрибуты задаёт
|
|
84
|
+
потребитель через проброшенные HTML-атрибуты (`...rest` уходит в `Header`). Интерактивность
|
|
85
|
+
обеспечивают вложенные кнопки/ссылки/табы внутри `Title.Controls` / `Tabs.Controls`.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Связанные компоненты
|
|
90
|
+
|
|
91
|
+
- `Page` — родитель; `HeaderPage` доступен как `Page.Header`.
|
|
92
|
+
- `BodyPage` (`Page.Body`), `FooterPage` (`Page.Footer`) — соседи внутри `Page`.
|
|
93
|
+
- `Header` — внутренний контейнер заголовка; статика `Page.Header.Title` / `Tabs` / `Subhead` /
|
|
94
|
+
`LayoutSidebar` берётся из `Header.*`.
|
|
95
|
+
- `Island` — карточка-обёртка для `type=FIRST`.
|
|
96
|
+
- `LightBox` — типичное место использования с `sticky`.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## Stories
|
|
101
|
+
|
|
102
|
+
Основные истории: `stories/Page/HeaderPage/HeaderPage.stories.tsx`
|
|
103
|
+
Файлы примеров: `stories/Page/HeaderPage/examples/`
|
|
104
|
+
|
|
105
|
+
| Story | Example file | Что демонстрирует |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| `Playground` | `Playground.tsx` | Интерактивный контроль `type` и `size` |
|
|
108
|
+
| `Default` | `Default.tsx` | Минимальный пример (FIRST, заголовок в карточке) |
|
|
109
|
+
| `Types` | `Types.tsx` | Сравнение типов FIRST и SECOND (покрывает скриншот-регрессию) |
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## История изменений
|
|
114
|
+
|
|
115
|
+
| Дата | Изменение |
|
|
116
|
+
|---|---|
|
|
117
|
+
| 2026-06-23 | Создан документ. AI-рефакторинг (clsx order, JSDoc на props, displayName), unit-тесты, миграция stories на modern pattern. |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Примеры использования
|
|
122
|
+
|
|
123
|
+
### Default
|
|
124
|
+
|
|
125
|
+
`stories/Page/HeaderPage/examples/Default.tsx`
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import React from "react";
|
|
129
|
+
import {
|
|
130
|
+
Page,
|
|
131
|
+
EHeaderPageType,
|
|
132
|
+
EComponentSize,
|
|
133
|
+
Button,
|
|
134
|
+
EButtonTheme,
|
|
135
|
+
Title,
|
|
136
|
+
ETitleSize,
|
|
137
|
+
Text,
|
|
138
|
+
ETextSize,
|
|
139
|
+
EFontType,
|
|
140
|
+
Gap,
|
|
141
|
+
} from "@sberbusiness/triplex-next";
|
|
142
|
+
|
|
143
|
+
export const Default = () => (
|
|
144
|
+
<Page.Header type={EHeaderPageType.FIRST}>
|
|
145
|
+
<Page.Header.Title>
|
|
146
|
+
<Page.Header.Title.Content>
|
|
147
|
+
<Title tag="h1" size={ETitleSize.H1}>
|
|
148
|
+
Заголовок страницы
|
|
149
|
+
</Title>
|
|
150
|
+
<Gap size={8} />
|
|
151
|
+
<Text tag="div" size={ETextSize.B3} type={EFontType.SECONDARY}>
|
|
152
|
+
Дополнительное описание страницы
|
|
153
|
+
</Text>
|
|
154
|
+
</Page.Header.Title.Content>
|
|
155
|
+
<Page.Header.Title.Controls>
|
|
156
|
+
<Button size={EComponentSize.MD} theme={EButtonTheme.SECONDARY}>
|
|
157
|
+
Отмена
|
|
158
|
+
</Button>
|
|
159
|
+
<Button size={EComponentSize.MD} theme={EButtonTheme.GENERAL}>
|
|
160
|
+
Сохранить
|
|
161
|
+
</Button>
|
|
162
|
+
</Page.Header.Title.Controls>
|
|
163
|
+
</Page.Header.Title>
|
|
164
|
+
</Page.Header>
|
|
165
|
+
);
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Types
|
|
169
|
+
|
|
170
|
+
`stories/Page/HeaderPage/examples/Types.tsx`
|
|
171
|
+
|
|
172
|
+
```tsx
|
|
173
|
+
import React from "react";
|
|
174
|
+
import {
|
|
175
|
+
Page,
|
|
176
|
+
EHeaderPageType,
|
|
177
|
+
EComponentSize,
|
|
178
|
+
Button,
|
|
179
|
+
EButtonTheme,
|
|
180
|
+
Title,
|
|
181
|
+
ETitleSize,
|
|
182
|
+
Text,
|
|
183
|
+
ETextSize,
|
|
184
|
+
EFontType,
|
|
185
|
+
Gap,
|
|
186
|
+
} from "@sberbusiness/triplex-next";
|
|
187
|
+
|
|
188
|
+
const title = (type: EHeaderPageType) => (
|
|
189
|
+
<Page.Header.Title>
|
|
190
|
+
<Page.Header.Title.Content>
|
|
191
|
+
<Title tag="h1" size={ETitleSize.H1}>
|
|
192
|
+
Заголовок страницы
|
|
193
|
+
</Title>
|
|
194
|
+
<Gap size={8} />
|
|
195
|
+
<Text tag="div" size={ETextSize.B3} type={EFontType.SECONDARY}>
|
|
196
|
+
Дополнительное описание страницы
|
|
197
|
+
</Text>
|
|
198
|
+
</Page.Header.Title.Content>
|
|
199
|
+
<Page.Header.Title.Controls>
|
|
200
|
+
<Button
|
|
201
|
+
size={EComponentSize.MD}
|
|
202
|
+
theme={type === EHeaderPageType.FIRST ? EButtonTheme.SECONDARY : EButtonTheme.SECONDARY_LIGHT}
|
|
203
|
+
>
|
|
204
|
+
Отмена
|
|
205
|
+
</Button>
|
|
206
|
+
<Button size={EComponentSize.MD} theme={EButtonTheme.GENERAL}>
|
|
207
|
+
Сохранить
|
|
208
|
+
</Button>
|
|
209
|
+
</Page.Header.Title.Controls>
|
|
210
|
+
</Page.Header.Title>
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
export const Types = () => (
|
|
214
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
215
|
+
<div>
|
|
216
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>FIRST</div>
|
|
217
|
+
<Page.Header type={EHeaderPageType.FIRST}>{title(EHeaderPageType.FIRST)}</Page.Header>
|
|
218
|
+
</div>
|
|
219
|
+
<div>
|
|
220
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>SECOND</div>
|
|
221
|
+
<Page.Header type={EHeaderPageType.SECOND}>{title(EHeaderPageType.SECOND)}</Page.Header>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
```
|
|
226
|
+
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
component: HelpBox
|
|
3
3
|
category: HelpBox
|
|
4
|
-
figma-node: ""
|
|
5
|
-
figma-file: ""
|
|
6
4
|
related: [Tooltip, ButtonIcon, MobileView, FocusTrap]
|
|
7
5
|
tokens: []
|
|
8
6
|
stories: stories/HelpBox/HelpBox.stories.tsx
|
|
@@ -13,25 +11,10 @@ version: "1.0"
|
|
|
13
11
|
|
|
14
12
|
## Назначение
|
|
15
13
|
|
|
16
|
-
Иконка
|
|
17
|
-
Объединяет ButtonIcon-триггер, Tooltip и FocusTrap в одном компоненте.
|
|
14
|
+
Иконка «?» (`QuestioncircleFilledSrvIcon16`) с всплывающей подсказкой (`Tooltip`). Объединяет `ButtonIcon`-триггер, `Tooltip` и `FocusTrap` в одном компоненте.
|
|
18
15
|
|
|
19
16
|
Используй когда: нужна контекстная подсказка рядом с элементом интерфейса.
|
|
20
|
-
Не используй когда: нужен полноценный попап с формой или сложным контентом — используй Dropdown или Modal
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Файловая структура
|
|
25
|
-
|
|
26
|
-
```text
|
|
27
|
-
src/components/HelpBox/
|
|
28
|
-
├── HelpBox.tsx # Основной компонент
|
|
29
|
-
├── index.ts # Barrel export
|
|
30
|
-
├── styles/
|
|
31
|
-
│ └── HelpBox.module.less # Минимальные стили (position, vertical-align)
|
|
32
|
-
└── __tests__/
|
|
33
|
-
└── HelpBox.test.tsx # Unit-тесты
|
|
34
|
-
```
|
|
17
|
+
Не используй когда: нужен полноценный попап с формой или сложным контентом — используй `Dropdown` или `Modal`.
|
|
35
18
|
|
|
36
19
|
---
|
|
37
20
|
|
|
@@ -48,7 +31,7 @@ src/components/HelpBox/
|
|
|
48
31
|
|
|
49
32
|
| Prop | Тип | По умолчанию | Описание |
|
|
50
33
|
|---|---|---|---|
|
|
51
|
-
| `isOpen` | `boolean` |
|
|
34
|
+
| `isOpen` | `boolean` | — | Управляемое состояние открытия тултипа |
|
|
52
35
|
| `toggle` | `(open: boolean) => void` | — | Callback при открытии/закрытии |
|
|
53
36
|
| `onShow` | `(node: HTMLDivElement) => void` | — | Callback при появлении тултипа в DOM |
|
|
54
37
|
| `preferPlace` | `ETooltipPreferPlace` | — | Предпочтительное расположение: `ABOVE`, `BELOW`, `LEFT`, `RIGHT` |
|
|
@@ -61,46 +44,11 @@ src/components/HelpBox/
|
|
|
61
44
|
| `className` | `string` | — | CSS-класс, пробрасывается на кнопку-триггер |
|
|
62
45
|
| `...rest` | `React.HTMLAttributes<HTMLButtonElement>` | — | Все стандартные атрибуты `<button>`, включая `aria-label`, пробрасываются на кнопку-триггер |
|
|
63
46
|
|
|
64
|
-
###
|
|
47
|
+
### Ограничения использования
|
|
65
48
|
|
|
66
|
-
- **Uncontrolled
|
|
67
|
-
-
|
|
68
|
-
|
|
69
|
-
---
|
|
70
|
-
|
|
71
|
-
## Ключевые особенности реализации
|
|
72
|
-
|
|
73
|
-
### Композиция внутренних компонентов
|
|
74
|
-
|
|
75
|
-
HelpBox — обёртка над несколькими внутренними компонентами:
|
|
76
|
-
- `ButtonIcon` (shape=CIRCLE) — кнопка-триггер с иконкой `QuestioncircleFilledSrvIcon16`
|
|
77
|
-
- `Tooltip` (toggleType="hover", role="dialog") — всплывающая подсказка
|
|
78
|
-
- `FocusTrap` (только desktop, через `MobileView`) — ловушка фокуса при открытом тултипе
|
|
79
|
-
- `TooltipMobileHeader` — заголовок мобильной версии (рендерится только при наличии `mobileHeaderContent`)
|
|
80
|
-
|
|
81
|
-
### FocusTrap
|
|
82
|
-
|
|
83
|
-
Ловушка фокуса активируется только на desktop (через `MobileView` fallback). При открытии:
|
|
84
|
-
- `initialFocus` — элемент Tooltip (по ID)
|
|
85
|
-
- `clickOutsideDeactivates: true` — клик за пределами закрывает
|
|
86
|
-
- `preventScroll: true`
|
|
87
|
-
|
|
88
|
-
Потребитель может расширить настройки через `focusTrapProps.focusTrapOptions`.
|
|
89
|
-
|
|
90
|
-
### Ref forwarding
|
|
91
|
-
|
|
92
|
-
`forwardRef` пробрасывает ref на внутренний `ButtonIcon` (кнопку-триггер). Внутренний `buttonRef` используется для позиционирования Tooltip через `targetRef`.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Accessibility
|
|
97
|
-
|
|
98
|
-
- Кнопка-триггер — нативный `<button>` через `ButtonIcon`, shape `CIRCLE`.
|
|
99
|
-
- **`aria-label` триггера** — не захардкожен. Потребитель **обязан** передать `aria-label` через `...rest` (например, `aria-label="Подсказка"`). Библиотека мультиязычная, текст не хардкодится.
|
|
100
|
-
- **`aria-label` кнопки закрытия** — передаётся через `tooltipXButtonProps={{ "aria-label": "Закрыть" }}`. Потребитель **обязан** указать значение на своём языке.
|
|
101
|
-
- Tooltip открывается с `role="dialog"`, `tabIndex={-1}`.
|
|
102
|
-
- FocusTrap удерживает фокус внутри открытого тултипа на desktop.
|
|
103
|
-
- `tooltipAriaAttributes` позволяет добавить aria-атрибуты к контейнеру Tooltip.
|
|
49
|
+
- **Controlled / Uncontrolled**: если `isOpen` не передан — компонент сам управляет `openState`. При передаче `isOpen` обязательно передавать `toggle`, иначе компонент не сможет переключать состояние.
|
|
50
|
+
- `forwardRef` пробрасывает `ref` на внутренний `ButtonIcon` (кнопку-триггер). Внутренний `buttonRef` используется для позиционирования Tooltip через `targetRef`.
|
|
51
|
+
- HelpBox — обёртка над несколькими внутренними компонентами: `ButtonIcon` (`shape=CIRCLE`), `Tooltip` (`toggleType="hover"`, `role="dialog"`), `FocusTrap` (только desktop) и опциональный `TooltipMobileHeader` (рендерится только при наличии `mobileHeaderContent`).
|
|
104
52
|
|
|
105
53
|
---
|
|
106
54
|
|
|
@@ -120,30 +68,41 @@ HelpBox — обёртка над несколькими внутренними
|
|
|
120
68
|
|
|
121
69
|
---
|
|
122
70
|
|
|
71
|
+
## Accessibility
|
|
72
|
+
|
|
73
|
+
- Кнопка-триггер — нативный `<button>` через `ButtonIcon`, `shape=CIRCLE`.
|
|
74
|
+
- **`aria-label` триггера** — не захардкожен. Потребитель **обязан** передать `aria-label` через `...rest` (например, `aria-label="Подсказка"`). Библиотека мультиязычная, текст не хардкодится.
|
|
75
|
+
- **`aria-label` кнопки закрытия** — передаётся через `tooltipXButtonProps={{ "aria-label": "Закрыть" }}`. Потребитель **обязан** указать значение на своём языке.
|
|
76
|
+
- Tooltip открывается с `role="dialog"`, `tabIndex={-1}`.
|
|
77
|
+
- FocusTrap удерживает фокус внутри открытого тултипа на desktop. При активации: `initialFocus` — элемент Tooltip (по ID), `clickOutsideDeactivates: true` — клик за пределами закрывает, `preventScroll: true`. Потребитель может расширить настройки через `focusTrapProps.focusTrapOptions`.
|
|
78
|
+
- `tooltipAriaAttributes` позволяет добавить aria-атрибуты к контейнеру Tooltip.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
123
82
|
## Связанные компоненты
|
|
124
83
|
|
|
125
|
-
- `Tooltip` (`src/components/Tooltip/`) — всплывающая подсказка, основной визуальный
|
|
126
|
-
- `ButtonIcon` (`src/components/Button/ButtonIcon.tsx`) —
|
|
127
|
-
- `MobileView` (`src/components/MobileView/`) — переключение desktop/mobile
|
|
128
|
-
- `FocusTrap` (npm: `focus-trap-react`) — ловушка фокуса для desktop
|
|
84
|
+
- `Tooltip` (`src/components/Tooltip/`) — всплывающая подсказка, основной визуальный элемент.
|
|
85
|
+
- `ButtonIcon` (`src/components/Button/ButtonIcon.tsx`) — кнопка-триггер.
|
|
86
|
+
- `MobileView` (`src/components/MobileView/`) — переключение desktop/mobile поведения.
|
|
87
|
+
- `FocusTrap` (npm: `focus-trap-react`) — ловушка фокуса для desktop.
|
|
129
88
|
|
|
130
89
|
---
|
|
131
90
|
|
|
132
91
|
## Stories
|
|
133
92
|
|
|
134
|
-
`stories/HelpBox/HelpBox.stories.tsx`
|
|
93
|
+
Основные истории: `stories/HelpBox/HelpBox.stories.tsx`
|
|
135
94
|
Файлы примеров: `stories/HelpBox/examples/`
|
|
136
95
|
|
|
137
96
|
| Story | Example file | Что демонстрирует |
|
|
138
97
|
|---|---|---|
|
|
139
|
-
| `Playground` | — | Интерактивный контроль всех props
|
|
140
|
-
| `Default` | `
|
|
141
|
-
| `Sizes` | `
|
|
142
|
-
| `Placement` | `
|
|
143
|
-
| `WithMobileHeader` | `
|
|
144
|
-
| `Controlled` | `
|
|
145
|
-
| `ChangeIconProps` | `
|
|
146
|
-
| `VisualTests` | — | Скриншот-тест с открытым тултипом
|
|
98
|
+
| `Playground` | — | Интерактивный контроль всех props |
|
|
99
|
+
| `Default` | `Default.tsx` | Минимальное использование |
|
|
100
|
+
| `Sizes` | `Sizes.tsx` | Размеры тултипа `SM` / `LG` |
|
|
101
|
+
| `Placement` | `Placement.tsx` | Расположение: above, below, left, right |
|
|
102
|
+
| `WithMobileHeader` | `WithMobileHeader.tsx` | Мобильный заголовок |
|
|
103
|
+
| `Controlled` | `Controlled.tsx` | Управляемое состояние (`isOpen` + `toggle`) |
|
|
104
|
+
| `ChangeIconProps` | `ChangeIconProps.tsx` | Кастомизация иконки через `iconProps` |
|
|
105
|
+
| `VisualTests` | — | Скриншот-тест с открытым тултипом |
|
|
147
106
|
|
|
148
107
|
---
|
|
149
108
|
|
|
@@ -152,6 +111,8 @@ HelpBox — обёртка над несколькими внутренними
|
|
|
152
111
|
| Дата | Изменение |
|
|
153
112
|
|---|---|
|
|
154
113
|
| 2026-04-08 | Создан документ. Добавлен `forwardRef`. |
|
|
114
|
+
| 2026-04-27 | Приведён в соответствие с `docs/ai/template-ai.md`: убраны секции «Файловая структура» и «Ключевые особенности реализации», их содержимое перенесено в `Ограничения использования` и `Accessibility`, переставлены секции, добавлена колонка `Example file`. |
|
|
115
|
+
| 2026-07-08 | Актуализирована колонка `Example file`: имена файлов примеров приведены к фактическим (без постфикса `Example`). |
|
|
155
116
|
|
|
156
117
|
---
|
|
157
118
|
|
|
@@ -159,13 +120,13 @@ HelpBox — обёртка над несколькими внутренними
|
|
|
159
120
|
|
|
160
121
|
### Default
|
|
161
122
|
|
|
162
|
-
`stories/HelpBox/examples/
|
|
123
|
+
`stories/HelpBox/examples/Default.tsx`
|
|
163
124
|
|
|
164
125
|
```tsx
|
|
165
126
|
import React from "react";
|
|
166
127
|
import { HelpBox, ETooltipSize } from "@sberbusiness/triplex-next";
|
|
167
128
|
|
|
168
|
-
export const
|
|
129
|
+
export const Default = () => (
|
|
169
130
|
<div style={{ padding: 50 }}>
|
|
170
131
|
<HelpBox tooltipSize={ETooltipSize.SM} aria-label="Подсказка" tooltipXButtonProps={{ "aria-label": "Закрыть" }}>
|
|
171
132
|
Подсказка по элементу интерфейса
|
|
@@ -176,13 +137,13 @@ export const DefaultExample = () => (
|
|
|
176
137
|
|
|
177
138
|
### Sizes
|
|
178
139
|
|
|
179
|
-
`stories/HelpBox/examples/
|
|
140
|
+
`stories/HelpBox/examples/Sizes.tsx`
|
|
180
141
|
|
|
181
142
|
```tsx
|
|
182
143
|
import React from "react";
|
|
183
144
|
import { HelpBox, ETooltipSize, ETooltipPreferPlace } from "@sberbusiness/triplex-next";
|
|
184
145
|
|
|
185
|
-
export const
|
|
146
|
+
export const Sizes = () => (
|
|
186
147
|
<div style={{ padding: 50, display: "flex", gap: 100 }}>
|
|
187
148
|
<div>
|
|
188
149
|
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>SM</div>
|
|
@@ -212,13 +173,13 @@ export const SizesExample = () => (
|
|
|
212
173
|
|
|
213
174
|
### Placement
|
|
214
175
|
|
|
215
|
-
`stories/HelpBox/examples/
|
|
176
|
+
`stories/HelpBox/examples/Placement.tsx`
|
|
216
177
|
|
|
217
178
|
```tsx
|
|
218
179
|
import React from "react";
|
|
219
180
|
import { HelpBox, ETooltipSize, ETooltipPreferPlace } from "@sberbusiness/triplex-next";
|
|
220
181
|
|
|
221
|
-
export const
|
|
182
|
+
export const Placement = () => (
|
|
222
183
|
<div style={{ padding: 50, display: "grid", gridTemplateColumns: "repeat(2, minmax(120px, 1fr))", gap: 32 }}>
|
|
223
184
|
<div style={{ display: "flex", alignItems: "center", gap: 12 }}>
|
|
224
185
|
<span style={{ width: 150 }}>above</span>
|
|
@@ -270,13 +231,13 @@ export const PlacementExample = () => (
|
|
|
270
231
|
|
|
271
232
|
### WithMobileHeader
|
|
272
233
|
|
|
273
|
-
`stories/HelpBox/examples/
|
|
234
|
+
`stories/HelpBox/examples/WithMobileHeader.tsx`
|
|
274
235
|
|
|
275
236
|
```tsx
|
|
276
237
|
import React from "react";
|
|
277
238
|
import { HelpBox, ETooltipSize } from "@sberbusiness/triplex-next";
|
|
278
239
|
|
|
279
|
-
export const
|
|
240
|
+
export const WithMobileHeader = () => (
|
|
280
241
|
<div style={{ padding: 50 }}>
|
|
281
242
|
<HelpBox
|
|
282
243
|
tooltipSize={ETooltipSize.SM}
|
|
@@ -292,13 +253,13 @@ export const WithMobileHeaderExample = () => (
|
|
|
292
253
|
|
|
293
254
|
### Controlled
|
|
294
255
|
|
|
295
|
-
`stories/HelpBox/examples/
|
|
256
|
+
`stories/HelpBox/examples/Controlled.tsx`
|
|
296
257
|
|
|
297
258
|
```tsx
|
|
298
259
|
import React, { useState } from "react";
|
|
299
260
|
import { HelpBox, ETooltipSize, ETooltipPreferPlace } from "@sberbusiness/triplex-next";
|
|
300
261
|
|
|
301
|
-
export const
|
|
262
|
+
export const Controlled = () => {
|
|
302
263
|
const [open, setOpen] = useState(false);
|
|
303
264
|
|
|
304
265
|
const handleToggle = (nextOpen: boolean) => setOpen(nextOpen);
|
|
@@ -330,13 +291,13 @@ export const ControlledExample = () => {
|
|
|
330
291
|
|
|
331
292
|
### ChangeIconProps
|
|
332
293
|
|
|
333
|
-
`stories/HelpBox/examples/
|
|
294
|
+
`stories/HelpBox/examples/ChangeIconProps.tsx`
|
|
334
295
|
|
|
335
296
|
```tsx
|
|
336
297
|
import React from "react";
|
|
337
298
|
import { HelpBox, ETooltipSize } from "@sberbusiness/triplex-next";
|
|
338
299
|
|
|
339
|
-
export const
|
|
300
|
+
export const ChangeIconProps = () => (
|
|
340
301
|
<div style={{ padding: 50 }}>
|
|
341
302
|
<HelpBox
|
|
342
303
|
tooltipSize={ETooltipSize.SM}
|