@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
package/README.md
CHANGED
|
@@ -80,6 +80,9 @@ npm run inspect
|
|
|
80
80
|
# Обновить bundle/ из последнего релиза triplex-next
|
|
81
81
|
npm run fetch-bundle
|
|
82
82
|
|
|
83
|
+
# Обновить только AI-ready компоненты из bundle, остальные данные сохранить
|
|
84
|
+
npm run fetch-bundle -- --merge --file path/to/mcp-data.json
|
|
85
|
+
|
|
83
86
|
# Обновить bundle/icons.json из @sberbusiness/icons-next
|
|
84
87
|
npm run fetch-icons
|
|
85
88
|
|
|
@@ -111,6 +114,13 @@ bundle/
|
|
|
111
114
|
содержимое в поддиректории выше. Транзиентный `mcp-data.json` удаляется
|
|
112
115
|
после раскладки.
|
|
113
116
|
|
|
117
|
+
По умолчанию дерево перезаписывается целиком. Флаг `--merge` включает
|
|
118
|
+
инкрементальное обновление: компоненты, у которых в bundle есть данные
|
|
119
|
+
(`raw !== null`), перезаписываются, остальные сохраняют текущую документацию
|
|
120
|
+
и записи в `manifest.json`. Гайды и release notes из bundle перезаписываются,
|
|
121
|
+
отсутствующие в bundle — сохраняются. Режим полезен, пока AI-документация
|
|
122
|
+
в triplex-next выверяется покомпонентно.
|
|
123
|
+
|
|
114
124
|
В triplex-next bundle собирается скриптом `scripts/generateMcpData.ts`
|
|
115
125
|
(npm-команда `generateMcpData`) и автоматически прикладывается к релиз-ассетам
|
|
116
126
|
через `.github/workflows/release.yml`.
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: AlertContext
|
|
3
|
+
category: Alert
|
|
4
|
+
related: [AlertProcess]
|
|
5
|
+
tokens:
|
|
6
|
+
- --triplex-next-AlertContext-Info_Color
|
|
7
|
+
- --triplex-next-AlertContext-Warning_Color
|
|
8
|
+
- --triplex-next-AlertContext-Error_Color
|
|
9
|
+
- --triplex-next-AlertContext-System_Color
|
|
10
|
+
stories: stories/Alerts/AlertContext.stories.tsx
|
|
11
|
+
version: "1.0"
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# AlertContext
|
|
15
|
+
|
|
16
|
+
## Назначение
|
|
17
|
+
|
|
18
|
+
Инлайновое контекстное предупреждение: строка «иконка + короткий текст», которая
|
|
19
|
+
поясняет или уточняет соседний элемент интерфейса. Рендерится в `<span>` с
|
|
20
|
+
`role="alert"`, иконка выбирается автоматически по `type`, текст оборачивается в
|
|
21
|
+
`Text` с размером `ETextSize.B4`.
|
|
22
|
+
|
|
23
|
+
Используй когда: нужно дать пояснение, предупреждение или сообщение об ошибке
|
|
24
|
+
рядом с полем, кнопкой или блоком контента — без рамки, фона и кнопки закрытия.
|
|
25
|
+
|
|
26
|
+
Не используй когда: нужен полноценный блок-уведомление с фоном, скруглением,
|
|
27
|
+
ссылками, спойлером и кнопкой закрытия — это `AlertProcess`. Для всплывающих
|
|
28
|
+
уведомлений поверх интерфейса — `Notification`.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Варианты и props
|
|
33
|
+
|
|
34
|
+
### Обязательные props
|
|
35
|
+
|
|
36
|
+
| Prop | Тип | Описание |
|
|
37
|
+
| ------ | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
38
|
+
| `type` | `Exclude<EAlertType, EAlertType.FEATURE>` | Тип предупреждения: `INFO` / `WARNING` / `ERROR` / `SYSTEM`. Определяет и иконку по умолчанию, и цвет текста |
|
|
39
|
+
|
|
40
|
+
### Опциональные props
|
|
41
|
+
|
|
42
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
43
|
+
| ------------------------------ | ----------------- | ---------------- | -------------------------------------------------------------------------- |
|
|
44
|
+
| `renderIcon` | `React.ReactNode` | иконка по `type` | Полностью заменяет иконку по умолчанию |
|
|
45
|
+
| `children` | `React.ReactNode` | — | Текст предупреждения. Всегда оборачивается в `Text`, наружу не «протекает» |
|
|
46
|
+
| `...HTMLSpanElementAttributes` | — | — | Все стандартные атрибуты `<span>` |
|
|
47
|
+
|
|
48
|
+
### Ограничения по типам
|
|
49
|
+
|
|
50
|
+
- `EAlertType.FEATURE` **не поддерживается** и исключён на уровне типа
|
|
51
|
+
(`Exclude<EAlertType, EAlertType.FEATURE>`). Класса `.alertTypeFeature` в
|
|
52
|
+
`AlertContext.module.less` нет — общий `ALERT_TYPE_TO_CLASS_NAME_MAP` содержит
|
|
53
|
+
ветку `FEATURE` только ради `AlertProcess`. Если обойти типизацию (`as`) и
|
|
54
|
+
передать `FEATURE`, компонент отрендерится без иконки и без цветового класса.
|
|
55
|
+
- Иконки по умолчанию фиксированы: `InfoStrokeStsIcon16` (`paletteIndex={3}`),
|
|
56
|
+
`WarningStrokeStsIcon16` (`2`), `ErrorStrokeStsIcon16` (`1`),
|
|
57
|
+
`SystemStrokeStsIcon16` (`4`). Менять `paletteIndex` нельзя — они согласованы
|
|
58
|
+
с цветовыми токенами.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Дизайн-токены
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
--triplex-next-AlertContext-Info_Color // цвет текста для type=INFO
|
|
66
|
+
--triplex-next-AlertContext-Warning_Color // цвет текста для type=WARNING
|
|
67
|
+
--triplex-next-AlertContext-Error_Color // цвет текста для type=ERROR
|
|
68
|
+
--triplex-next-AlertContext-System_Color // цвет текста для type=SYSTEM
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Значения — в `src/components/DesignTokens/components/AlertContext.ts`. Обрати
|
|
72
|
+
внимание: `Info_Color`, `Warning_Color` и `System_Color` ссылаются на один и тот
|
|
73
|
+
же нейтральный цвет (`ColorDarkNeutralAlpha.0` / `ColorNeutralAlpha.0`),
|
|
74
|
+
выделен цветом только `Error_Color`. Типы различаются прежде всего иконкой, а не
|
|
75
|
+
цветом текста.
|
|
76
|
+
|
|
77
|
+
Размеры шрифта токенами не задаются — типографику целиком определяет `Text`
|
|
78
|
+
с `ETextSize.B4` (класс `.b4` в `Typography/styles/Text.module.less`).
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Инварианты
|
|
83
|
+
|
|
84
|
+
- **`forwardRef`** — обязателен, target — `HTMLSpanElement`. Не убирать.
|
|
85
|
+
- **Корневой элемент `<span>` с `role="alert"`** — не менять ни тег, ни роль.
|
|
86
|
+
Тег `<span>` выбран ради валидности вложения в инлайновый контекст, но
|
|
87
|
+
`display: flex` делает элемент **блочным** flex-контейнером: из текстового
|
|
88
|
+
потока он выпадает. Не рассчитывай на инлайновое обтекание.
|
|
89
|
+
- **`type` исключает `EAlertType.FEATURE`** — сужение типа публичное, расширять
|
|
90
|
+
без добавления стилей и иконки нельзя.
|
|
91
|
+
- **`renderIcon` переопределяет иконку через `||`, а не `??`** — намеренно:
|
|
92
|
+
falsy-значение (`false`, `null`) означает «показать иконку по умолчанию». Замена
|
|
93
|
+
на `??` изменит поведение для `renderIcon={false}`.
|
|
94
|
+
- **CSS-классы `alertContext`, `alertContextText`, `alertTypeInfo`,
|
|
95
|
+
`alertTypeWarning`, `alertTypeError`, `alertTypeSystem`** — проверяются в
|
|
96
|
+
unit-тестах, не переименовывать.
|
|
97
|
+
- **`Text` получает только `size` и `className`** — никакого `type`. Цвет —
|
|
98
|
+
зона ответственности `AlertContext`, см. «Подводные камни». Тест
|
|
99
|
+
`does not set the mapped Typography font type class on text` охраняет это
|
|
100
|
+
правило. В DOM класс `primary` при этом присутствует: `Text` подставляет
|
|
101
|
+
`EFontType.PRIMARY` по умолчанию — на цвет он не влияет, его перекрывает
|
|
102
|
+
локальное правило.
|
|
103
|
+
- **`ALERT_TYPE_TO_CLASS_NAME_MAP`** (`AlertTypeUtils.tsx`) — общий с
|
|
104
|
+
`AlertProcess` и экспортируется из barrel. Его форма (`Record<EAlertType,
|
|
105
|
+
(styles) => string>`) — часть публичного API, менять нельзя без breaking change.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Подводные камни
|
|
110
|
+
|
|
111
|
+
- **Цвет текста задаётся локальным правилом, а `type` у `Text` намеренно не
|
|
112
|
+
передаётся.** Цвет берётся из `.alertContext.alertTypeX .alertContextText`
|
|
113
|
+
(токены `AlertContext-*`). Раньше компонент дополнительно передавал в `Text`
|
|
114
|
+
вычисленный `EFontType`, но это было мёртвым кодом: локальное правило имеет
|
|
115
|
+
специфичность (0,3,0) и всегда перекрывает `.typography.info` (0,2,0) из
|
|
116
|
+
`Typography.module.less`. Хуже того, значения расходились — см. таблицу ниже.
|
|
117
|
+
Не возвращай `type` у `Text`: цвет от этого не изменится, но код начнёт
|
|
118
|
+
документировать неверное намерение. Обратное тоже неверно — не убирай
|
|
119
|
+
LESS-правила «раз цвет и так задаёт `Text`»: тогда текст станет `primary`.
|
|
120
|
+
|
|
121
|
+
| `type` | `AlertContext-*` (действует) | `Typography-*` (не действует) |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `INFO` | нейтральный `rgba(31,31,34,1)` / `rgba(255,255,255,1)` | синий `#0E57CC` / `#1297FE` |
|
|
124
|
+
| `WARNING` | нейтральный, те же значения | оранжевый `#EF4C01` / `#FF7A17` |
|
|
125
|
+
| `ERROR` | `#D10032` / `#F80C45` | `#D10032` / `#F80C45` — совпадает |
|
|
126
|
+
| `SYSTEM` | нейтральный, альфа `1` | `SECONDARY`: альфа `.65` / `.55` |
|
|
127
|
+
|
|
128
|
+
- **Из `.alertContext` удалены `font-size: 12px` / `line-height: 16px`**
|
|
129
|
+
(2026-07-27) как мёртвые правила: типографику текста задаёт `Text` через
|
|
130
|
+
класс `.b4` на самом текстовом элементе, а собственное объявление потомка
|
|
131
|
+
всегда бьёт наследуемое от родителя. На иконки влияния не было — они
|
|
132
|
+
рендерятся как `<svg width="16" height="16">` с px-атрибутами.
|
|
133
|
+
**Остаточный риск:** если потребитель передаёт в `renderIcon` не-svg элемент
|
|
134
|
+
с текстом, его типографика после удаления изменится — раньше он наследовал от
|
|
135
|
+
`.alertContext` 12px/16px, теперь наследует размер шрифта родителя страницы.
|
|
136
|
+
Штатный сценарий (`renderIcon` = иконка из `@sberbusiness/icons-next`) не
|
|
137
|
+
затронут.
|
|
138
|
+
- **`role="alert"` присутствует в DOM с момента монтирования.** Live-region,
|
|
139
|
+
добавленный в дерево вместе со своим содержимым, скринридеры часто не
|
|
140
|
+
анонсируют. Если нужно гарантированное озвучивание при динамическом появлении
|
|
141
|
+
сообщения — держи `AlertContext` смонтированным и меняй `children`, а не
|
|
142
|
+
монтируй компонент целиком.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Accessibility
|
|
147
|
+
|
|
148
|
+
- Корневой `<span>` имеет `role="alert"` — это `aria-live="assertive"` region:
|
|
149
|
+
изменение содержимого прерывает текущую речь скринридера.
|
|
150
|
+
- Иконка декоративная и не имеет текстовой альтернативы — весь смысл должен
|
|
151
|
+
быть в `children`. Не полагайся на цвет и иконку как на единственный носитель
|
|
152
|
+
информации о серьёзности сообщения.
|
|
153
|
+
- Компонент неинтерактивен: не получает фокус, не обрабатывает клавиатуру,
|
|
154
|
+
собственных `aria-*` атрибутов сверх `role` не выставляет. Любые `aria-label`
|
|
155
|
+
/ `aria-describedby` пробрасываются через `...rest`.
|
|
156
|
+
- При связывании с полем формы передавай `id` и ссылайся на него из поля через
|
|
157
|
+
`aria-describedby`.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Связанные компоненты
|
|
162
|
+
|
|
163
|
+
- `AlertProcess` — блочное уведомление того же семейства: фон, скругление,
|
|
164
|
+
кнопка закрытия, спойлер, ссылки. Поддерживает `EAlertType.FEATURE`.
|
|
165
|
+
- `EAlertType` — общий enum типов для всего семейства. `AlertContext`
|
|
166
|
+
использует его подмножество.
|
|
167
|
+
- `ALERT_TYPE_TO_CLASS_NAME_MAP` (`AlertTypeUtils.tsx`) — общий маппинг типа в
|
|
168
|
+
CSS-класс, разделяемый с `AlertProcess`. Собственного AI.md не имеет.
|
|
169
|
+
- `Text` — рендерит текст предупреждения (`ETextSize.B4`). Цвет им не
|
|
170
|
+
управляется: prop `type` намеренно не передаётся.
|
|
171
|
+
- `Notification` — всплывающее уведомление поверх интерфейса, а не инлайновое.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Stories
|
|
176
|
+
|
|
177
|
+
Основные истории: `stories/Alerts/AlertContext.stories.tsx`
|
|
178
|
+
Файлы примеров: `stories/Alerts/examples/AlertContext/`
|
|
179
|
+
|
|
180
|
+
| Story | Example file | Что демонстрирует |
|
|
181
|
+
| ---------------- | -------------------- | ---------------------------------------------------------------- |
|
|
182
|
+
| `Playground` | `Playground.tsx` | Интерактивный контроль `type` и `children` |
|
|
183
|
+
| `Default` | `Default.tsx` | Базовое предупреждение с типом `INFO` |
|
|
184
|
+
| `Types` | `Types.tsx` | Все поддерживаемые типы: `INFO` / `WARNING` / `ERROR` / `SYSTEM` |
|
|
185
|
+
| `WithCustomIcon` | `WithCustomIcon.tsx` | Замена иконки через `renderIcon` |
|
|
186
|
+
|
|
187
|
+
Скриншот-тесты: baseline лежат в `__screenshots__/` как
|
|
188
|
+
`alerts-alertcontext--{default,types,with-custom-icon}--{xs,xl}.png`.
|
|
189
|
+
`Playground` исключён из скриншот-тестов через `testRunner: { skip: true }`
|
|
190
|
+
(по `docs/ai/stories-guide.md` — всегда), его визуальная регрессия не покрыта.
|
|
191
|
+
Устаревшие `alerts-alertcontext--playground--{xs,xl}.png` удалены: скрипт
|
|
192
|
+
`scripts/checkOrphanScreenshots.ts` такие файлы не ловит — `parameters` нет в
|
|
193
|
+
`storybook-static/index.json`, поэтому skip-стори считаются ожидаемыми.
|
|
194
|
+
Отдельная `VisualTests` story не создавалась — у компонента нет состояний,
|
|
195
|
+
требующих взаимодействия (hover / focus / disabled / loading отсутствуют).
|
|
196
|
+
Непокрытый визуальный кейс — перенос текста на несколько строк.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## История изменений
|
|
201
|
+
|
|
202
|
+
| Дата | Изменение |
|
|
203
|
+
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
204
|
+
| 2026-07-27 | Создан документ. AI-рефакторинг: switch иконок заменён на `TYPE_TO_DEFAULT_ICON_MAP`, в `IAlertContextProps` добавлен явный `children`, из `.alertContext` удалены мёртвые `font-size` / `line-height`, из `Text` убран prop `type` вместе с маппингом `EFontType` (перекрывался специфичностью и расходился по значениям с токенами `AlertContext-*`). Unit-тесты расширены с 6 до 25 кейсов. Файлы примеров в `stories/Alerts/examples/AlertContext/` переименованы под modern pattern — без суффикса `Example`. Публичный API не менялся. |
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Примеры использования
|
|
209
|
+
|
|
210
|
+
### Default
|
|
211
|
+
|
|
212
|
+
`stories/Alerts/examples/AlertContext/Default.tsx`
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
import React from "react";
|
|
216
|
+
import { AlertContext, EAlertType } from "@sberbusiness/triplex-next";
|
|
217
|
+
|
|
218
|
+
export const Default = () => (
|
|
219
|
+
<div style={{ maxWidth: "750px" }}>
|
|
220
|
+
<AlertContext type={EAlertType.INFO}>
|
|
221
|
+
This message provides context or highlights important information to note.
|
|
222
|
+
</AlertContext>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Types
|
|
228
|
+
|
|
229
|
+
`stories/Alerts/examples/AlertContext/Types.tsx`
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import React from "react";
|
|
233
|
+
import { AlertContext, EAlertType } from "@sberbusiness/triplex-next";
|
|
234
|
+
|
|
235
|
+
const TYPES = Object.values(EAlertType).filter((type) => type !== EAlertType.FEATURE);
|
|
236
|
+
|
|
237
|
+
export const Types = () => (
|
|
238
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "16px", maxWidth: "750px" }}>
|
|
239
|
+
{TYPES.map((type) => (
|
|
240
|
+
<div key={type}>
|
|
241
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{type.toUpperCase()}</div>
|
|
242
|
+
<AlertContext type={type}>
|
|
243
|
+
This message provides context or highlights important information to note.
|
|
244
|
+
</AlertContext>
|
|
245
|
+
</div>
|
|
246
|
+
))}
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### WithCustomIcon
|
|
252
|
+
|
|
253
|
+
`stories/Alerts/examples/AlertContext/WithCustomIcon.tsx`
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import React from "react";
|
|
257
|
+
import { AlertContext, EAlertType } from "@sberbusiness/triplex-next";
|
|
258
|
+
import { WaitStrokeStsIcon16 } from "@sberbusiness/icons-next";
|
|
259
|
+
|
|
260
|
+
export const WithCustomIcon = () => (
|
|
261
|
+
<div style={{ maxWidth: "750px" }}>
|
|
262
|
+
<AlertContext type={EAlertType.INFO} renderIcon={<WaitStrokeStsIcon16 paletteIndex={4} />}>
|
|
263
|
+
This message provides context or highlights important information to note.
|
|
264
|
+
</AlertContext>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
```
|
|
268
|
+
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: BodyPage
|
|
3
|
+
category: Page
|
|
4
|
+
related: [Page, HeaderPage, FooterPage, Body, Island, LightBox]
|
|
5
|
+
tokens: []
|
|
6
|
+
stories: stories/Page/BodyPage/BodyPage.stories.tsx
|
|
7
|
+
version: "1.0"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# BodyPage
|
|
11
|
+
|
|
12
|
+
## Назначение
|
|
13
|
+
|
|
14
|
+
Тело страницы `Page`. Доступен как статическое свойство `Page.Body`. Контейнер для основного
|
|
15
|
+
контента страницы между `Page.Header` и `Page.Footer`.
|
|
16
|
+
|
|
17
|
+
Используй когда: нужно разместить основной контент внутри `Page` — как в карточке (Island), так и без неё.
|
|
18
|
+
Не используй когда: нужен заголовок или футер страницы — для этого есть `Page.Header` / `Page.Footer`.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Варианты и props
|
|
23
|
+
|
|
24
|
+
Публичный API — discriminated union по `type`: `IBodyPageTypeFirstProps | IBodyPageTypeSecondProps`.
|
|
25
|
+
Оба интерфейса расширяют `IBodyProps` (≈ `React.HTMLAttributes<HTMLDivElement>`).
|
|
26
|
+
|
|
27
|
+
### Обязательные props
|
|
28
|
+
|
|
29
|
+
| Prop | Тип | Описание |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| `type` | `EBodyPageType` | `FIRST` — контент оборачивается в `Island` (карточка с белым фоном и тенью). `SECOND` — контент без карточки. |
|
|
32
|
+
| `children` | `React.ReactNode` | Контент тела страницы. |
|
|
33
|
+
|
|
34
|
+
### Опциональные props
|
|
35
|
+
|
|
36
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| `verticalMargin` | `EBodyPageVerticalMargin` | `LARGE` | Вертикальные отступы: `LARGE` = 24px (16px на узких экранах), `SMALL` = 16px (8px на узких). В LightBox используется `SMALL`. |
|
|
39
|
+
| `size` | `EComponentSize` | — | Размер острова (Island). **Доступен только для `type=FIRST`**; для `type=SECOND` типизирован как `never`. |
|
|
40
|
+
|
|
41
|
+
### Ограничения по типам
|
|
42
|
+
|
|
43
|
+
- `size` доступен только при `type=FIRST` (в `SECOND` контент не оборачивается в Island, поэтому `size?: never`).
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Дизайн-токены
|
|
48
|
+
|
|
49
|
+
Собственных CSS-переменных нет. Внешний вид карточки наследуется от `Island` (`EIslandType.TYPE_1`).
|
|
50
|
+
Вертикальные отступы заданы фиксированными значениями в `styles/BodyPage.module.less`
|
|
51
|
+
(24/16px и адаптив 16/8px на `@screen-sm-max`).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Инварианты
|
|
56
|
+
|
|
57
|
+
- `forwardRef<HTMLDivElement>` — не убирать. Ref всегда указывает на корневой элемент
|
|
58
|
+
(Island для FIRST, Body для SECOND).
|
|
59
|
+
- `displayName = "BodyPage"` — не менять.
|
|
60
|
+
- Discriminated union по `type` и значения `EBodyPageType` / `EBodyPageVerticalMargin` — часть
|
|
61
|
+
публичного API, менять нельзя.
|
|
62
|
+
- Экспорты `BodyPage`, `IBodyPageTypeFirstProps`, `IBodyPageTypeSecondProps` идут в barrel
|
|
63
|
+
`src/components/Page/index.ts` — сохранять.
|
|
64
|
+
- `verticalMargin` по умолчанию `LARGE` — менять дефолт нельзя без обсуждения.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Accessibility
|
|
69
|
+
|
|
70
|
+
Особого a11y-поведения нет — это структурный контейнер. Семантику и aria-атрибуты задаёт
|
|
71
|
+
потребитель через проброшенные HTML-атрибуты (`...rest` уходит в `Body`).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Связанные компоненты
|
|
76
|
+
|
|
77
|
+
- `Page` — родитель; `BodyPage` доступен как `Page.Body`.
|
|
78
|
+
- `HeaderPage` (`Page.Header`), `FooterPage` (`Page.Footer`) — соседи внутри `Page`.
|
|
79
|
+
- `Body` — внутренний контейнер контента (рендерится в обоих типах).
|
|
80
|
+
- `Island` — карточка-обёртка для `type=FIRST`.
|
|
81
|
+
- `LightBox` — типичное место использования с `verticalMargin=SMALL`.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Stories
|
|
86
|
+
|
|
87
|
+
Основные истории: `stories/Page/BodyPage/BodyPage.stories.tsx`
|
|
88
|
+
Файлы примеров: `stories/Page/BodyPage/examples/`
|
|
89
|
+
|
|
90
|
+
| Story | Example file | Что демонстрирует |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| `Playground` | `Playground.tsx` | Интерактивный контроль `type` и `verticalMargin` |
|
|
93
|
+
| `Default` | `Default.tsx` | Минимальный пример (FIRST, контент в карточке) |
|
|
94
|
+
| `Types` | `Types.tsx` | Сравнение типов FIRST и SECOND |
|
|
95
|
+
| `VerticalMargins` | `VerticalMargins.tsx` | Отступы LARGE (24px) и SMALL (16px) |
|
|
96
|
+
| `VisualTests` | `VisualTests.tsx` | Матрица type × verticalMargin для скриншот-регрессии |
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
## История изменений
|
|
101
|
+
|
|
102
|
+
| Дата | Изменение |
|
|
103
|
+
|---|---|
|
|
104
|
+
| 2026-06-18 | Создан документ. AI-рефакторинг (clsx order, JSDoc), unit-тесты, миграция stories на modern pattern. |
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Примеры использования
|
|
109
|
+
|
|
110
|
+
### Default
|
|
111
|
+
|
|
112
|
+
`stories/Page/BodyPage/examples/Default.tsx`
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
import React from "react";
|
|
116
|
+
import { Page, EBodyPageType, Text, ETextSize, EFontType } from "@sberbusiness/triplex-next";
|
|
117
|
+
|
|
118
|
+
export const Default = () => (
|
|
119
|
+
<Page.Body type={EBodyPageType.FIRST}>
|
|
120
|
+
<Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
|
|
121
|
+
BodyPage типа FIRST оборачивает контент в Island (карточку) с белым фоном и тенью.
|
|
122
|
+
</Text>
|
|
123
|
+
</Page.Body>
|
|
124
|
+
);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Types
|
|
128
|
+
|
|
129
|
+
`stories/Page/BodyPage/examples/Types.tsx`
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
import React from "react";
|
|
133
|
+
import { Page, EBodyPageType, Text, ETextSize, EFontType } from "@sberbusiness/triplex-next";
|
|
134
|
+
|
|
135
|
+
export const Types = () => (
|
|
136
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
137
|
+
<div>
|
|
138
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>FIRST</div>
|
|
139
|
+
<Page.Body type={EBodyPageType.FIRST}>
|
|
140
|
+
<Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
|
|
141
|
+
Тип FIRST оборачивает контент в Island (карточку) с белым фоном и тенью.
|
|
142
|
+
</Text>
|
|
143
|
+
</Page.Body>
|
|
144
|
+
</div>
|
|
145
|
+
<div>
|
|
146
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>SECOND</div>
|
|
147
|
+
<Page.Body type={EBodyPageType.SECOND}>
|
|
148
|
+
<Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
|
|
149
|
+
Тип SECOND отображает контент без карточки.
|
|
150
|
+
</Text>
|
|
151
|
+
</Page.Body>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### VerticalMargins
|
|
158
|
+
|
|
159
|
+
`stories/Page/BodyPage/examples/VerticalMargins.tsx`
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import React from "react";
|
|
163
|
+
import { Page, EBodyPageType, EBodyPageVerticalMargin, Text, ETextSize, EFontType } from "@sberbusiness/triplex-next";
|
|
164
|
+
|
|
165
|
+
export const VerticalMargins = () => (
|
|
166
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
167
|
+
<div>
|
|
168
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>LARGE (24px)</div>
|
|
169
|
+
<Page.Body type={EBodyPageType.FIRST} verticalMargin={EBodyPageVerticalMargin.LARGE}>
|
|
170
|
+
<Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
|
|
171
|
+
Отступы сверху и снизу 24px (значение по умолчанию).
|
|
172
|
+
</Text>
|
|
173
|
+
</Page.Body>
|
|
174
|
+
</div>
|
|
175
|
+
<div>
|
|
176
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: 700 }}>SMALL (16px)</div>
|
|
177
|
+
<Page.Body type={EBodyPageType.FIRST} verticalMargin={EBodyPageVerticalMargin.SMALL}>
|
|
178
|
+
<Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
|
|
179
|
+
Уменьшенные отступы сверху и снизу 16px. Используется в LightBox.
|
|
180
|
+
</Text>
|
|
181
|
+
</Page.Body>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|