@sberbusiness/triplex-next-mcp-server 1.41.0-beta → 1.42.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.
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  component: Body
3
3
  category: Layout
4
- figma-node: ""
5
- figma-file: ""
6
- related: [Page, Header, Footer]
4
+ related: [BodyPage]
7
5
  tokens: []
8
- stories: ""
6
+ stories: stories/Body/Body.stories.tsx
9
7
  version: "1.0"
10
8
  ---
11
9
 
@@ -13,155 +11,149 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Минимальный layout-контейнер для содержимого страницы. Создаёт двухуровневую
17
- структуру `<div>` (root + inner) с `display: flex` и `flex-grow: 1` на inner,
18
- что позволяет контенту растягиваться на всю доступную высоту.
14
+ Контейнер основного контента. Корневой элемент — flex-контейнер, внутренняя обёртка
15
+ (`flex-grow: 1; width: 100%`) растягивает контент на всю доступную ширину. Собственных
16
+ отступов, фона и рамок не задаёт.
19
17
 
20
- В текущей архитектуре `Body` — примитив, используемый внутри `BodyPage`
21
- (экспортируется как `Page.Body` в stories). Как самостоятельный публичный
22
- компонент применяется редко — чаще через `Page.Body` с дополнительными
23
- props (`type`, `verticalMargin`).
24
-
25
- Используй когда: собираешь кастомный layout страницы и хочешь переиспользовать
26
- flex-обёртку без привязки к Page.
27
- Не используй когда: строишь страницу по стандартному паттерну — бери `Page.Body`,
28
- там уже есть Island, verticalMargin и поддержка типов.
29
-
30
- ---
31
-
32
- ## Файловая структура
33
-
34
- ```text
35
- src/components/Body/
36
- ├── Body.tsx # React.forwardRef, thin wrapper
37
- ├── index.ts # Barrel
38
- ├── styles/Body.module.less # .body (flex) + .bodyInner (flex-grow: 1)
39
- └── __tests__/Body.test.tsx
40
- ```
41
-
42
- Особенности:
43
- - Нет LESS-токенов — компонент чисто структурный.
44
- - **Нет собственных stories** — документируется косвенно через `Page.Body`
45
- (stories/Page/BodyPage.stories.tsx).
46
- - **Импорт через публичный путь, а не через `../Body`**: в `BodyPage.tsx` путь
47
- `@sberbusiness/triplex-next/components/Body/Body` — это сохранено намеренно,
48
- paths-alias для работы в монорепозитории потребителей.
18
+ Используй когда: нужен нейтральный блок-контейнер контента, растягивающийся по ширине
19
+ родителя, — в первую очередь как внутренняя часть тела страницы.
20
+ Не используй когда: нужно тело страницы `Page` с карточкой (`Island`) и вертикальными
21
+ отступами — для этого есть `BodyPage` (`Page.Body`), который сам оборачивает `Body`.
49
22
 
50
23
  ---
51
24
 
52
25
  ## Варианты и props
53
26
 
54
- ### `IBodyProps extends React.HTMLAttributes<HTMLDivElement>`
55
-
56
- Интерфейс пустой — используется наследование от HTMLAttributes как есть.
57
-
58
- | Prop | Тип | Описание |
59
- |---|---|---|
60
- | `children` | `React.ReactNode` | Контент, рендерится внутри inner-div. |
61
- | `className` | `string` | Объединяется с `.body` через `clsx`. |
62
- | `...HTMLDivAttributes` | — | Всё стандартное для `<div>`. |
27
+ Своих props у компонента нет. `IBodyProps` расширяет `React.HTMLAttributes<HTMLDivElement>`:
28
+ все стандартные атрибуты `div` (включая `className`, `style`, `id`, `aria-*`, обработчики
29
+ событий) уходят через `...rest` на корневой элемент.
63
30
 
64
- ---
31
+ ### Опциональные props
65
32
 
66
- ## Ключевые особенности реализации
33
+ | Prop | Тип | По умолчанию | Описание |
34
+ | ---------- | ----------------- | ------------ | ---------------------------------------------------------------------------------- |
35
+ | `children` | `React.ReactNode` | — | Контент тела. Рендерится во внутренней обёртке, а не напрямую в корневом элементе. |
67
36
 
68
- ### Двухуровневая обёртка
37
+ Поскольку настраиваемых props нет, у компонента нет story `Playground`.
69
38
 
70
- ```tsx
71
- <div className={clsx(styles.body, className)} {...rest} data-tx={...} ref={ref}>
72
- <div className={styles.bodyInner}>{children}</div>
73
- </div>
74
- ```
39
+ ---
75
40
 
76
- Root — `display: flex; position: relative`. Inner — `flex-grow: 1; width: 100%;
77
- position: relative`. Двойной уровень нужен, чтобы:
78
- - Root мог получать `className` и event handler'ы от потребителя без поломки
79
- flex-layout.
80
- - Inner гарантированно занимал всю ширину/высоту, что критично для корректного
81
- позиционирования абсолютных потомков (position: relative на обоих уровнях).
41
+ ## Дизайн-токены
82
42
 
83
- ### ref идёт на root
43
+ Собственных CSS-переменных нет. В `styles/Body.module.less` заданы только layout-свойства
44
+ (`position`, `display: flex`, `flex-grow`, `width`) — ни цветов, ни отступов.
84
45
 
85
- `forwardRef` прокидывает ref на **внешний div**, не на inner. Это сохраняет
86
- стабильный контракт (ref → тот же DOM-элемент, что получает className и spread
87
- props).
46
+ ---
88
47
 
89
- ### `data-tx` только на root
48
+ ## Инварианты
90
49
 
91
- Версия пакета ставится только на внешний div — второй раз на inner не нужен.
50
+ - `forwardRef<HTMLDivElement>` — не убирать. Ref указывает на **корневой** элемент
51
+ (тот же, что получает `className`, `...rest` и `data-tx`), а не на внутреннюю обёртку.
52
+ - Двухуровневая разметка (корневой `div` > внутренний `div`) — часть наблюдаемого контракта:
53
+ `children` всегда попадают во внутреннюю обёртку. Уровень вложенности виден потребителям
54
+ в DOM, поэтому его изменение может сломать их CSS-селекторы и DOM-запросы и требует записи
55
+ в release notes.
56
+ - `className` мерджится только в корневой элемент; внутренняя обёртка кастомных классов не получает.
57
+ - Компонент не задаёт собственных отступов — вертикальные отступы тела страницы добавляет
58
+ `BodyPage`. Добавление padding сюда изменит вёрстку всех потребителей.
59
+ - `displayName = "Body"` — не менять.
60
+ - Экспорты `Body` и `IBodyProps` идут в barrel `src/components/Body/index.ts` и далее в корневой
61
+ `src/components/index.ts` — сохранять.
92
62
 
93
- ### Пустой интерфейс `IBodyProps`
63
+ ---
94
64
 
95
- ```tsx
96
- export interface IBodyProps extends React.HTMLAttributes<HTMLDivElement> {}
97
- ```
65
+ ## Accessibility
98
66
 
99
- ESLint может предлагать заменить на type-alias `type IBodyProps = React.HTMLAttributes<HTMLDivElement>`,
100
- но `interface` сохранён для возможности расширения в будущем (например, если
101
- потребуется добавить `verticalMargin` на уровень Body, а не BodyPage). Не
102
- переписывать на type.
67
+ Собственного a11y-поведения нет — это структурный контейнер без роли и без интерактивности.
68
+ Семантику (`role`, `aria-*`, заголовки) задаёт потребитель через проброшенные HTML-атрибуты.
103
69
 
104
70
  ---
105
71
 
106
- ## Инварианты
72
+ ## Связанные компоненты
107
73
 
108
- - **`forwardRef`** — обязателен. Ref идёт на root div.
109
- - **`data-tx={process.env.npm_package_version}`** — не удалять (версия для
110
- отладки).
111
- - **Двухуровневая структура (`.body` → `.bodyInner`)** — не схлопывать в один
112
- div. От этого зависит lafyut-контракт потребителей, особенно `BodyPage`
113
- (он оборачивает Body в Island для типа FIRST).
114
- - **`position: relative` на обоих уровнях** — не убирать. Потребители могут
115
- полагаться на то, что абсолютно спозиционированные элементы привязаны к
116
- этим контейнерам.
117
- - **`flex-grow: 1` на inner** — не убирать. Обеспечивает поведение "body
118
- занимает всё доступное место по высоте".
119
- - **`IBodyProps` как interface (не type)** — сохранить для будущего расширения.
120
- - **Нет своих дизайн-токенов** — не добавлять без согласования (компонент
121
- намеренно стилистически нейтрален, цвет/шрифт/отступы задаёт потребитель
122
- или родитель).
74
+ - `BodyPage` — тело страницы (`Page.Body`); рендерит `Body` внутри себя, добавляя карточку
75
+ `Island` (для `type=FIRST`) и вертикальные отступы. Его props расширяют `IBodyProps`.
76
+ Типичная точка путаницы: в продуктовом коде страницы почти всегда нужен `Page.Body`, а не голый `Body`.
77
+ - `Page` — страница целиком; `Body` попадает в неё опосредованно, через `Page.Body`.
123
78
 
124
79
  ---
125
80
 
126
- ## Accessibility
81
+ ## Stories
82
+
83
+ Основные истории: `stories/Body/Body.stories.tsx`
84
+ Файлы примеров: `stories/Body/examples/`
127
85
 
128
- - **Нет собственной ARIA-роли** — `<div>` семантически нейтрален. Если нужна
129
- semantic main-область — потребитель передаёт `role="main"` через `...rest`
130
- или использует `<main>` как обёртку снаружи.
131
- - **Не перехватывает фокус, не манипулирует tabindex** — полностью прозрачен
132
- для навигации.
86
+ | Story | Example file | Что демонстрирует |
87
+ | ------------- | ----------------- | ------------------------------------------------------------------------- |
88
+ | `Default` | `Default.tsx` | Минимальный пример с текстовым контентом |
89
+ | `Example` | `Example.tsx` | Production-like композиция: `Body` как контейнер контента внутри `Island` |
90
+ | `VisualTests` | `VisualTests.tsx` | Несколько детей, длинный неразрывный контент, `Body` рядом с сиблингом |
133
91
 
134
92
  ---
135
93
 
136
- ## Дизайн-токены
94
+ ## История изменений
137
95
 
138
- Нет — компонент структурный, без визуального оформления.
96
+ | Дата | Изменение |
97
+ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
98
+ | 2026-08-13 | Создан документ. AI-рефакторинг (уточнён JSDoc компонента, `children` задокументирован явно), расширены unit-тесты, добавлены stories в modern pattern. |
139
99
 
140
100
  ---
141
101
 
142
- ## Связанные компоненты
102
+ ## Примеры использования
143
103
 
144
- - `Page` (`src/components/Page`) — страничный layout. Содержит Header / Body /
145
- Footer как compound-пропсы.
146
- - `BodyPage` / `Page.Body` (`src/components/Page/components/BodyPage.tsx`) —
147
- расширенный Body с поддержкой `type` (FIRST/SECOND), `verticalMargin`,
148
- опциональной обёрткой в Island. В большинстве сценариев потребитель использует
149
- Page.Body, а не Body напрямую.
150
- - `Header` / `Page.Header`, `Footer` / `Page.Footer` — соседние компоненты страницы.
151
- - `Island` (`src/components/Island`) — используется внутри `Page.Body` типа FIRST,
152
- даёт body карточное оформление.
104
+ ### Default
153
105
 
154
- ---
106
+ `stories/Body/examples/Default.tsx`
155
107
 
156
- ## Stories
108
+ ```tsx
109
+ import React from "react";
110
+ import { Body, Text, ETextSize, EFontType } from "@sberbusiness/triplex-next";
111
+
112
+ export const Default = () => (
113
+ <Body>
114
+ <Text tag="div" size={ETextSize.B2} type={EFontType.PRIMARY}>
115
+ Body — контейнер основного контента. Собственных отступов не задаёт.
116
+ </Text>
117
+ </Body>
118
+ );
119
+ ```
157
120
 
158
- Отдельных stories нет. Поведение Body показано через `Page.Body` в
159
- `stories/Page/BodyPage.stories.tsx` с вариациями `type` и `verticalMargin`.
121
+ ### Example
160
122
 
161
- ---
123
+ `stories/Body/examples/Example.tsx`
162
124
 
163
- ## История изменений
125
+ ```tsx
126
+ import React from "react";
127
+ import { Body, Island, Text, ETextSize, EFontType, Caption, ECaptionSize } from "@sberbusiness/triplex-next";
128
+
129
+ export const Example = () => (
130
+ <div style={{ maxWidth: "480px" }}>
131
+ <Island>
132
+ <Body>
133
+ <div style={{ display: "flex", flexDirection: "column", gap: "12px" }}>
134
+ <Text tag="div" size={ETextSize.B1} type={EFontType.PRIMARY}>
135
+ Реквизиты счёта
136
+ </Text>
137
+ <div style={{ display: "flex", justifyContent: "space-between", gap: "16px" }}>
138
+ <Caption size={ECaptionSize.C1} type={EFontType.SECONDARY}>
139
+ Номер счёта
140
+ </Caption>
141
+ <Text tag="span" size={ETextSize.B2} type={EFontType.PRIMARY}>
142
+ 40702810400000012345
143
+ </Text>
144
+ </div>
145
+ <div style={{ display: "flex", justifyContent: "space-between", gap: "16px" }}>
146
+ <Caption size={ECaptionSize.C1} type={EFontType.SECONDARY}>
147
+ БИК
148
+ </Caption>
149
+ <Text tag="span" size={ETextSize.B2} type={EFontType.PRIMARY}>
150
+ 044525225
151
+ </Text>
152
+ </div>
153
+ </div>
154
+ </Body>
155
+ </Island>
156
+ </div>
157
+ );
158
+ ```
164
159
 
165
- | Дата | Изменение |
166
- |---|---|
167
- | 2026-04-18 | Создан документ |