@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,11 +1,9 @@
1
1
  ---
2
2
  component: Portal
3
- category: Utilities
4
- figma-node: ""
5
- figma-file: ""
6
- related: [ModalWindow, LightBox, Dropdown, Tooltip]
3
+ category: Portal
4
+ related: [Dropdown, Tooltip]
7
5
  tokens: []
8
- stories: ""
6
+ stories: stories/Portal/Portal.stories.tsx
9
7
  version: "1.0"
10
8
  ---
11
9
 
@@ -13,107 +11,173 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Тонкая обёртка над `ReactDOM.createPortal`. Рендерит `children` во
17
- внешний DOM-узел (`container`), оставаясь в текущем React-дереве
18
- (контекст, обработчики, focus-trap работают как обычно).
14
+ Сервисный компонент — тонкая обёртка над `ReactDOM.createPortal`. Рендерит
15
+ `children` в указанный внешний DOM-узел (`container`), а не в месте объявления,
16
+ сохраняя React-контекст и всплытие событий по React-дереву.
19
17
 
20
- Используй когда: нужен node вне родительского дерева (обход
21
- `overflow: hidden`, `z-index`-стэк, поверх модалок). В большинстве
22
- случаев напрямую — внутри `ModalWindow`/`Dropdown`/`Tooltip`/`LightBox`.
18
+ Используй когда: содержимое нужно вынести из DOM-иерархии родителя — выйти за
19
+ пределы контейнера с `overflow: hidden`, поверх `z-index`-контекста, в
20
+ `document.body` или произвольный узел (всплывающие слои, тултипы, дропдауны).
23
21
 
24
- ---
25
-
26
- ## Файловая структура
27
-
28
- ```text
29
- src/components/Portal/
30
- ├── Portal.tsx # FC, 1 строка — createPortal
31
- └── index.ts # Barrel
32
- ```
33
-
34
- Нет стилей, тестов, stories.
22
+ Не используй когда:
23
+ - Нужен готовый всплывающий слой с позиционированием и поведением — используй
24
+ `Dropdown`, `Tooltip`, `ModalWindow`: они уже рендерятся через Portal или
25
+ собственные механизмы.
26
+ - Контейнер ещё не существует на момент рендера — сначала дождись монтирования
27
+ узла (создай его через ref-callback/`useState`), затем рендери Portal.
35
28
 
36
29
  ---
37
30
 
38
31
  ## Варианты и props
39
32
 
40
- ### `IPortalProps`
33
+ ### Обязательные props
41
34
 
42
- | Prop | Тип | Обязателен | Описание |
43
- |---|---|---|---|
44
- | `children` | `ReactNode` | Да | Рендерится в `container`. |
45
- | `container` | `Element \| DocumentFragment` | Да | Целевой DOM-узел. |
35
+ | Prop | Тип | Описание |
36
+ |---|---|---|
37
+ | `children` | `React.ReactNode` | Содержимое, рендерящееся в `container` |
38
+ | `container` | `Element \| DocumentFragment` | Существующий DOM-узел, в который рендерится содержимое |
46
39
 
47
- Никаких опциональных props или fallback'ов.
40
+ Опциональных props нет. Компонент не рендерит собственный host-элемент и не
41
+ принимает `className`/rest-атрибуты — стилизуется сам `container` или
42
+ содержимое.
48
43
 
49
- ---
44
+ ### Особенности поведения
50
45
 
51
- ## Ключевые особенности реализации
46
+ - При смене `container` на rerender содержимое переносится в новый узел,
47
+ старый очищается.
48
+ - При unmount содержимое удаляется из `container`; сам узел-контейнер
49
+ компонент не создаёт и не удаляет — его жизненный цикл на потребителе.
50
+ - События из содержимого всплывают по React-дереву (к родителю Portal), а не
51
+ по DOM-дереву контейнера — стандартная семантика `createPortal`.
52
52
 
53
- ### `ReactDOM.createPortal`
53
+ ---
54
54
 
55
- ```tsx
56
- export const Portal = ({ children, container }) => ReactDOM.createPortal(children, container);
57
- ```
55
+ ## Дизайн-токены
58
56
 
59
- - React сам управляет mount/unmount через виртуальное дерево.
60
- - **Контекст-провайдеры**, **events bubbling** работают, как если бы дерево было локальным (events bubble через React-tree, не DOM-tree).
57
+ Собственных стилей и CSS-переменных нет — компонент не рендерит разметку.
61
58
 
62
- ### `container` — обязателен
59
+ ---
63
60
 
64
- - В отличие от ряда библиотек, `Portal` **не создаёт** контейнер сам и **не подбирает** `document.body` по умолчанию.
65
- - Потребитель сам решает, куда монтировать (типичный паттерн: создать `<div>` в `document.body` и передать сюда).
61
+ ## Инварианты
66
62
 
67
- ### **Не SSR-safe**
63
+ - **Без `forwardRef` — осознанное исключение** из общего правила библиотеки:
64
+ Portal не рендерит собственный host-элемент, ref форвардить некуда. Не
65
+ добавлять `forwardRef` без изменения контракта.
66
+ - **Имена props `children` и `container`** и тип `container: Element |
67
+ DocumentFragment` — публичное API с версии 1.21.0, не менять.
68
+ - **Интерфейс `IPortalProps`** экспортируется из barrel — не переименовывать.
69
+ - Реализация остаётся тонкой обёрткой над `ReactDOM.createPortal` (React
70
+ 17-совместимый API) — не добавлять состояние, эффекты и React 18-only API:
71
+ код синхронизируется в release-0.
68
72
 
69
- - `createPortal` на сервере выбрасывает ошибку. При SSR — потребитель должен оборачивать в `if (typeof window !== "undefined")` или использовать `useEffect`.
70
- - В этом проекте — обычно через `useEffect` создают и монтируют контейнер (см. `ModalWindow`, `LightBox`).
73
+ ---
71
74
 
72
- ### **Никаких lifecycle-хуков**
75
+ ## Accessibility
73
76
 
74
- - Portal не отслеживает изменение `container`. При смене `container` — React удалит старый child из старого container и смонтирует в новый (стандартное поведение createPortal).
77
+ - Собственной ARIA-семантики нет — компонент прозрачен для accessibility-дерева.
78
+ - Портал не управляет фокусом: focus trap, возврат фокуса, `aria-modal` и
79
+ прочие контракты всплывающих слоёв — ответственность потребителя
80
+ (`ModalWindow`, `Dropdown` реализуют их самостоятельно).
81
+ - Учитывай порядок чтения screen reader'ом: содержимое читается в месте
82
+ `container` в DOM, а не в месте объявления.
75
83
 
76
84
  ---
77
85
 
78
- ## Инварианты
86
+ ## Связанные компоненты
79
87
 
80
- - **`container` — обязателен**, не optional.
81
- - **`children` — `ReactNode`**, не `ReactElement` (можно массив, fragment, primitive).
82
- - **`FC`, не `forwardRef`** — ref на children идёт нативно через React-tree, на сам Portal-component — нет.
83
- - **Не SSR-safe** — потребитель ответственен за условный рендер.
84
- - **Контейнер не создаётся автоматически** — приходит снаружи.
85
- - **Никаких side effects** — нет `useEffect`, нет mount-классов, нет cleanup.
88
+ - `Dropdown` (`src/components/Dropdown/`) — рендерит выпадающий слой через
89
+ Portal в `document.body`.
90
+ - `Tooltip` (`src/components/Tooltip/`) — desktop- и mobile-реализации
91
+ рендерят тултип через Portal: mobile — всегда в `document.body`, desktop — в
92
+ `renderContainer ?? document.body`.
86
93
 
87
94
  ---
88
95
 
89
- ## Accessibility
96
+ ## Stories
97
+
98
+ Основные истории: `stories/Portal/Portal.stories.tsx`
99
+ Файлы примеров: `stories/Portal/examples/`
90
100
 
91
- - Portal не влияет на семантику. **Focus management, ARIA-связи** — задача потребителя.
92
- - Tab-последовательность определяется DOM-порядком: portal'ed узел — там, куда смонтирован, не там, где находится в JSX. Это часто нарушает focus order — нужен focus-trap внутри.
101
+ | Story | Example file | Что демонстрирует |
102
+ |---|---|---|
103
+ | `Playground` | `Playground.tsx` | Интерактивный контроль `children`; `container` задаётся обёрткой (узел с пунктирной рамкой) |
104
+ | `Default` | `Default.tsx` | Содержимое рендерится в указанный DOM-узел, а не в месте объявления |
105
+ | `Example` | `Example.tsx` | Типовой сценарий: вынос содержимого из контейнера с `overflow: hidden` |
93
106
 
94
107
  ---
95
108
 
96
- ## Дизайн-токены
109
+ ## История изменений
97
110
 
98
- Нет.
111
+ | Дата | Изменение |
112
+ |---|---|
113
+ | 2026-07-29 | Создан документ. AI-рефакторинг (TRI-67): JSDoc на props `IPortalProps`, unit-тесты (5 кейсов: рендер в container/DocumentFragment, rerender, смена container, unmount), stories по modern pattern. Публичный API не менялся; `forwardRef` осознанно отсутствует. |
99
114
 
100
115
  ---
101
116
 
102
- ## Связанные компоненты
117
+ ## Примеры использования
103
118
 
104
- - `ModalWindow` / `LightBox` / `Dropdown` / `Tooltip` — все используют Portal.
105
- - `react-dom` `createPortal` — нативный API.
119
+ ### Default
106
120
 
107
- ---
121
+ `stories/Portal/examples/Default.tsx`
108
122
 
109
- ## Stories
123
+ ```tsx
124
+ import React, { useState } from "react";
125
+ import { Portal } from "@sberbusiness/triplex-next";
126
+
127
+ export const Default = () => {
128
+ const [container, setContainer] = useState<HTMLDivElement | null>(null);
129
+
130
+ return (
131
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px", maxWidth: "400px" }}>
132
+ <div>Компонент Portal объявлен здесь, но его содержимое рендерится в контейнер с пунктирной рамкой.</div>
133
+ <div
134
+ ref={setContainer}
135
+ style={{ border: "1px dashed rgb(125, 131, 138)", borderRadius: "4px", padding: "16px" }}
136
+ />
137
+ {container && <Portal container={container}>Содержимое, отрендеренное через Portal.</Portal>}
138
+ </div>
139
+ );
140
+ };
141
+ ```
110
142
 
111
- Нет.
143
+ ### Example
112
144
 
113
- ---
145
+ `stories/Portal/examples/Example.tsx`
114
146
 
115
- ## История изменений
147
+ ```tsx
148
+ import React, { useState } from "react";
149
+ import { Portal } from "@sberbusiness/triplex-next";
150
+
151
+ export const Example = () => {
152
+ const [container, setContainer] = useState<HTMLDivElement | null>(null);
153
+
154
+ return (
155
+ <div style={{ display: "flex", flexDirection: "column", gap: "16px", maxWidth: "400px" }}>
156
+ <div
157
+ style={{
158
+ border: "1px solid rgb(125, 131, 138)",
159
+ borderRadius: "4px",
160
+ padding: "16px",
161
+ height: "48px",
162
+ overflow: "hidden",
163
+ }}
164
+ >
165
+ <div>Контейнер с overflow: hidden и фиксированной высотой.</div>
166
+ {container && (
167
+ <Portal container={container}>
168
+ <div>
169
+ Это содержимое объявлено внутри контейнера с overflow: hidden, но через Portal отрендерено
170
+ во внешний узел с пунктирной рамкой, поэтому не обрезается и видно полностью.
171
+ </div>
172
+ </Portal>
173
+ )}
174
+ </div>
175
+ <div
176
+ ref={setContainer}
177
+ style={{ border: "1px dashed rgb(125, 131, 138)", borderRadius: "4px", padding: "16px" }}
178
+ />
179
+ </div>
180
+ );
181
+ };
182
+ ```
116
183
 
117
- | Дата | Изменение |
118
- |---|---|
119
- | 2026-04-18 | Создан документ |
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  component: Row
3
3
  category: Layout
4
- figma-node: ""
5
- figma-file: ""
6
- related: [Col, Container]
4
+ related: [Col, Gap]
7
5
  tokens: []
8
6
  stories: stories/Row/Row.stories.tsx
9
7
  version: "1.0"
@@ -13,108 +11,87 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Строка grid-системы — `<div>` с горизонтальным flex-wrap layout'ом и
17
- **отрицательными margin'ами по бокам** для компенсации gutter'ов
18
- дочерних `Col`. Рекомендованный child — `Col`.
14
+ Строка сетки: flex-контейнер с нижним отступом, предназначенный для использования с колонками `Col` в children. Передаёт размер горизонтального отступа между колонками (`gridHorizontalGap`) в дочерние `Col` через внутренний `RowContext`.
19
15
 
20
- Используй когда: компонуешь форму/контент в колоночной сетке проекта.
21
- Для нестандартного layout'а — flex/grid-CSS напрямую.
16
+ Используй когда: нужно разместить контент в колоночной сетке — несколько `Col` в одной строке с управляемым горизонтальным отступом между ними и вертикальным отступом между строками.
22
17
 
23
- ---
24
-
25
- ## Файловая структура
26
-
27
- ```text
28
- src/components/Row/
29
- ├── Row.tsx # FC; <div> + flex layout
30
- ├── styles/Row.module.less # margin -horizontal-gap, padding-bottom
31
- ├── index.ts # Barrel
32
- └── __tests__/
33
- ```
18
+ Не используй когда:
19
+ - Нужен только вертикальный отступ между блоками без колонок — используй `Gap`.
20
+ - Children — не колонки `Col`: компонент рассчитан на связку `Row` → `Col`, отрицательные боковые margin компенсируются padding колонок.
34
21
 
35
22
  ---
36
23
 
37
24
  ## Варианты и props
38
25
 
39
- ### `IRowProps extends React.HTMLAttributes<HTMLDivElement>`
40
-
41
- | Prop | Тип | Default | Описание |
42
- |---|---|---|---|
43
- | `paddingBottom` | `boolean` | `true` | Нижний отступ строки. `false` — отключить. |
44
- | `...HTMLAttributes` | — | — | На корневой `<div>`. |
45
-
46
- - `paddingBottom: false` → класс `noPaddingBottom`.
47
- - **Последняя `Row` в родителе** автоматически получает `padding-bottom: 0` через CSS-селектор `:last-child`.
48
-
49
- ---
26
+ ### Обязательные props
50
27
 
51
- ## Ключевые особенности реализации
28
+ Обязательных props нет.
52
29
 
53
- ### Compensating margins
30
+ ### Опциональные props
54
31
 
55
- ```less
56
- .row {
57
- display: flex;
58
- flex-wrap: wrap;
59
- margin-left: -@grid-horizontal-gap;
60
- margin-right: -@grid-horizontal-gap;
61
- padding-bottom: @row-bottom-padding;
62
- }
63
- ```
32
+ | Prop | Тип | По умолчанию | Описание |
33
+ |---|---|---|---|
34
+ | `paddingBottom` | `boolean` | `true` | Нижний отступ строки (16px). При `false` — отступ убирается. У последней строки (`:last-child`) отступ убирается стилями независимо от значения prop. |
35
+ | `gridHorizontalGap` | `EComponentSize.SM \| EComponentSize.MD` | `EComponentSize.SM` | Размер отступа между колонками: SM — 8px, MD — 12px. Передаётся в дочерние `Col` через `RowContext`. |
64
36
 
65
- - Отрицательные margin компенсируют padding'и `Col`'ов — содержимое крайних колонок выровнено по краю Row.
66
- - Стандартный bootstrap-style grid pattern.
37
+ Компонент расширяет `React.HTMLAttributes<HTMLDivElement>` — принимает все стандартные атрибуты `<div>` (`className`, `style`, `aria-*`, `data-*` и т.д.).
67
38
 
68
- ### `padding-bottom` через CSS, а не inline
39
+ ### Ограничения
69
40
 
70
- - LESS-переменная `@row-bottom-padding` определяет величину.
71
- - `:last-child` — обнуление: серия Row друг под другом не накапливает отступ снизу.
41
+ - `gridHorizontalGap` намеренно сужен до `SM | MD` — остальные значения `EComponentSize` не входят в контракт сетки.
42
+ - Механика gap: `Row` задаёт отрицательные `margin-left`/`margin-right`, а `Col` — соответствующий горизонтальный padding (значение получает из `RowContext`). Управлять gap нужно только через prop на `Row`, а не стилями `Col`.
72
43
 
73
- ### `flex-wrap: wrap`
44
+ ---
74
45
 
75
- - Колонки с суммарной шириной > 100% переносятся на новую строку (внутри одной Row).
46
+ ## Дизайн-токены
76
47
 
77
- ### **Только базовый `<div>`**
48
+ Компонент не использует CSS-переменных `--triplex-next-*`. Размеры берутся из LESS-переменных сетки в `src/styles/components/grid.less`:
78
49
 
79
- - Нет `forwardRef`, нет slots, нет компонентного API. Простой layout helper.
50
+ ```less
51
+ @row-bottom-padding: 16px
52
+ @grid-horizontal-gap-SM: 8px
53
+ @grid-horizontal-gap-MD: 12px
54
+ ```
80
55
 
81
56
  ---
82
57
 
83
58
  ## Инварианты
84
59
 
85
- - **`<div>` с `display: flex; flex-wrap: wrap`** — изменение типа layout — breaking.
86
- - **`paddingBottom: true` default** — большинство строк с отступом.
87
- - **`:last-child` снимает padding-bottom** — публичное CSS-поведение.
88
- - **Отрицательные margin'ы** = ожидание дочерних `Col`'ов с padding'ами равными `@grid-horizontal-gap`.
89
- - **`FC, не forwardRef`**.
90
- - **Контракт child** — `Col` (на уровне типов не enforced).
60
+ - **`forwardRef`** — обязателен, не убирать. `ref` пробрасывается на корневой `<div>`.
61
+ - **Имена публичного API**: компонент `Row`, интерфейс `IRowProps`, props `paddingBottom`, `gridHorizontalGap` и их дефолты — менять нельзя (breaking change).
62
+ - **Barrel `src/components/Row/index.ts` экспортирует только `./Row`** — `RowContext` остаётся внутренним модулем, в barrel не добавлять.
63
+ - **`RowContext` — внутренний контракт с `Col`**: `Col` читает `gridHorizontalGap` из контекста (`src/components/Col/Col.tsx`). Изменение формы `IRowContext` или дефолтного значения контекста требует синхронного обновления `Col`.
64
+ - **Значение контекста мемоизировано** (`React.useMemo` по `gridHorizontalGap`) — не убирать, иначе все `Col`-потребители будут перерендериваться на каждом рендере `Row`.
65
+ - **Корневой DOM-элемент — `<div>`** без ARIA-роли.
66
+ - **CSS-классы `SM`, `MD`, `noPaddingBottom`** в `Row.module.less` используются в unit-тестах; класс `row` — корневой, тестами не проверяется, но фиксируется visual baseline. `SM`/`MD` — исторически не camelCase, переименование требует синхронного обновления тестов и проверки visual baseline.
67
+ - **`displayName = "Row"`** — проверяется тестом.
91
68
 
92
69
  ---
93
70
 
94
71
  ## Accessibility
95
72
 
96
- - Нейтральный `<div>` — без семантики. Если строка несёт смысл (form-row), потребитель добавляет `role` сам.
97
-
98
- ---
99
-
100
- ## Дизайн-токены
101
-
102
- LESS-переменные (через `@import '../../../styles/style'`):
103
- - `@grid-horizontal-gap` — горизонтальный gap.
104
- - `@row-bottom-padding` — нижний отступ.
73
+ Компонент не интерактивный: рендерит обычный `<div>` без роли, keyboard navigation и focus management не применимы. Потребитель может передать `role` и `aria-*` атрибуты через spread.
105
74
 
106
75
  ---
107
76
 
108
77
  ## Связанные компоненты
109
78
 
110
- - `Col` — колонка, основной child.
111
- - Прочая grid-система (`Container`) — если есть в проекте.
79
+ - `Col` (`src/components/Col/`) — колонка сетки, единственный ожидаемый тип children. Потребляет `gridHorizontalGap` из `RowContext`.
80
+ - `Gap` (`src/components/Gap/`) — вертикальный отступ-разделитель вне колоночной сетки.
112
81
 
113
82
  ---
114
83
 
115
84
  ## Stories
116
85
 
117
- `stories/Row/Row.stories.tsx`
86
+ Основные истории: `stories/Row/Row.stories.tsx`
87
+ Файлы примеров: `stories/Row/examples/`
88
+
89
+ | Story | Example file | Что демонстрирует |
90
+ |---|---|---|
91
+ | `Playground` | `Playground.tsx` | Интерактивный контроль `paddingBottom` и `gridHorizontalGap` |
92
+ | `Default` | `Default.tsx` | Две строки по две колонки, отступ между строками по умолчанию |
93
+ | `GridHorizontalGaps` | `GridHorizontalGaps.tsx` | Отступы между колонками SM (8px) и MD (12px) |
94
+ | `WithoutPaddingBottom` | `WithoutPaddingBottom.tsx` | Строки 1 и 3 с `paddingBottom={false}` в контрасте со строкой 2 с отступом по умолчанию |
118
95
 
119
96
  ---
120
97
 
@@ -122,4 +99,129 @@ LESS-переменные (через `@import '../../../styles/style'`):
122
99
 
123
100
  | Дата | Изменение |
124
101
  |---|---|
125
- | 2026-04-18 | Создан документ |
102
+ | 2026-07-28 | Создан документ. AI-рефакторинг (TRI-71): добавлен `forwardRef`, значение `RowContext` мемоизировано, JSDoc на props и контекст, расширены unit-тесты (ref, проброс gap через контекст); stories переведены на modern pattern (`stories/Row/`), включены визуальные тесты. |
103
+
104
+ ---
105
+
106
+ ## Примеры использования
107
+
108
+ ### Default
109
+
110
+ `stories/Row/examples/Default.tsx`
111
+
112
+ ```tsx
113
+ import React from "react";
114
+ import { Col, Row } from "@sberbusiness/triplex-next";
115
+
116
+ export const Default = () => (
117
+ <div style={{ maxWidth: "320px" }}>
118
+ <Row>
119
+ <Col size={6}>
120
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
121
+ Row 1, Col 1
122
+ </div>
123
+ </Col>
124
+ <Col size={6}>
125
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
126
+ Row 1, Col 2
127
+ </div>
128
+ </Col>
129
+ </Row>
130
+ <Row>
131
+ <Col size={6}>
132
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
133
+ Row 2, Col 1
134
+ </div>
135
+ </Col>
136
+ <Col size={6}>
137
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
138
+ Row 2, Col 2
139
+ </div>
140
+ </Col>
141
+ </Row>
142
+ </div>
143
+ );
144
+ ```
145
+
146
+ ### GridHorizontalGaps
147
+
148
+ `stories/Row/examples/GridHorizontalGaps.tsx`
149
+
150
+ ```tsx
151
+ import React from "react";
152
+ import { Col, EComponentSize, Row } from "@sberbusiness/triplex-next";
153
+
154
+ export const GridHorizontalGaps = () => (
155
+ <div style={{ maxWidth: "320px" }}>
156
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>SM</div>
157
+ <Row gridHorizontalGap={EComponentSize.SM}>
158
+ <Col size={6}>
159
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>Col 1</div>
160
+ </Col>
161
+ <Col size={6}>
162
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>Col 2</div>
163
+ </Col>
164
+ </Row>
165
+ <div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>MD</div>
166
+ <Row gridHorizontalGap={EComponentSize.MD}>
167
+ <Col size={6}>
168
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>Col 1</div>
169
+ </Col>
170
+ <Col size={6}>
171
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>Col 2</div>
172
+ </Col>
173
+ </Row>
174
+ </div>
175
+ );
176
+ ```
177
+
178
+ ### WithoutPaddingBottom
179
+
180
+ `stories/Row/examples/WithoutPaddingBottom.tsx`
181
+
182
+ ```tsx
183
+ import React from "react";
184
+ import { Col, Row } from "@sberbusiness/triplex-next";
185
+
186
+ export const WithoutPaddingBottom = () => (
187
+ <div style={{ maxWidth: "320px" }}>
188
+ <Row paddingBottom={false}>
189
+ <Col size={6}>
190
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
191
+ Row 1, Col 1
192
+ </div>
193
+ </Col>
194
+ <Col size={6}>
195
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
196
+ Row 1, Col 2
197
+ </div>
198
+ </Col>
199
+ </Row>
200
+ <Row>
201
+ <Col size={6}>
202
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
203
+ Row 2, Col 1
204
+ </div>
205
+ </Col>
206
+ <Col size={6}>
207
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
208
+ Row 2, Col 2
209
+ </div>
210
+ </Col>
211
+ </Row>
212
+ <Row paddingBottom={false}>
213
+ <Col size={6}>
214
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
215
+ Row 3, Col 1
216
+ </div>
217
+ </Col>
218
+ <Col size={6}>
219
+ <div style={{ padding: "16px", textAlign: "center", backgroundColor: "rgb(255, 217, 160)" }}>
220
+ Row 3, Col 2
221
+ </div>
222
+ </Col>
223
+ </Row>
224
+ </div>
225
+ );
226
+ ```
227
+