@sberbusiness/triplex-next-mcp-server 1.41.0-beta → 1.43.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 (41) hide show
  1. package/bundle/components/AlertProcess.md +460 -0
  2. package/bundle/components/Amount.md +145 -169
  3. package/bundle/components/Badge.md +155 -219
  4. package/bundle/components/Body.md +108 -116
  5. package/bundle/components/Button.md +1 -0
  6. package/bundle/components/CarouselExtended.md +355 -194
  7. package/bundle/components/Checkbox.md +7 -1
  8. package/bundle/components/CheckboxTreeExtended.md +149 -248
  9. package/bundle/components/CheckboxXGroup.md +2 -0
  10. package/bundle/components/CheckboxYGroup.md +7 -2
  11. package/bundle/components/ChipGroup.md +195 -126
  12. package/bundle/components/ComposedKeyDownListener.md +323 -0
  13. package/bundle/components/FooterPage.md +2 -1
  14. package/bundle/components/HeaderPage.md +2 -1
  15. package/bundle/components/Island.md +100 -12
  16. package/bundle/components/KeyDownListener.md +11 -72
  17. package/bundle/components/LightBox.md +6 -0
  18. package/bundle/components/LoaderSmall.md +230 -0
  19. package/bundle/components/MaskedField.md +481 -0
  20. package/bundle/components/MediaWidth.md +252 -108
  21. package/bundle/components/MobileView.md +192 -68
  22. package/bundle/components/ModalWindow.md +3 -1
  23. package/bundle/components/Notification.md +21 -3
  24. package/bundle/components/Page.md +3 -1
  25. package/bundle/components/Pagination.md +20 -0
  26. package/bundle/components/SelectExtendedField.md +691 -236
  27. package/bundle/components/SliderExtended.md +358 -222
  28. package/bundle/components/TabsExtended.md +380 -194
  29. package/bundle/components/UnorderedList.md +254 -0
  30. package/bundle/components/UnorderedListExtended.md +255 -0
  31. package/bundle/components/WindowResizeListener.md +249 -0
  32. package/bundle/guides/commits.md +66 -3
  33. package/bundle/guides/context.md +26 -0
  34. package/bundle/guides/stories.md +3 -1
  35. package/bundle/guides/template.md +1 -1
  36. package/bundle/manifest.json +64 -21
  37. package/bundle/release-notes/1.41.1.mdx +18 -0
  38. package/bundle/release-notes/1.42.0.mdx +81 -0
  39. package/bundle/release-notes/1.43.0.mdx +94 -0
  40. package/bundle/release-notes/1.44.0.mdx +7 -0
  41. package/package.json +1 -1
@@ -1,11 +1,9 @@
1
1
  ---
2
2
  component: MediaWidth
3
- category: Utilities
4
- figma-node: ""
5
- figma-file: ""
6
- related: [MobileView, IslandWidget]
3
+ category: MediaWidth
4
+ related: [MediaMinWidth, MediaMaxWidth, MediaBetweenWidth, useMatchMedia, MobileView, WindowResizeListener]
7
5
  tokens: []
8
- stories: ""
6
+ stories: stories/MediaWidth/MediaWidth.stories.tsx
9
7
  version: "1.0"
10
8
  ---
11
9
 
@@ -13,157 +11,303 @@ version: "1.0"
13
11
 
14
12
  ## Назначение
15
13
 
16
- Набор компонентов + хук для условного рендеринга по ширине окна:
17
- - **`useMatchMedia(query, initial)`** — хук, обёртка над `window.matchMedia` с live-обновлением через `change`-listener.
18
- - **`MediaMinWidth` / `MediaMaxWidth` / `MediaBetweenWidth`** — рендерят `children` / `fallback` по результату media-query.
19
- - **`MediaWidth`** — универсальная обёртка; по наличию `minWidth`/`maxWidth` выбирает нужный из трёх.
20
-
21
- Используй когда: нужно рендерить разный UI на разных брейкпоинтах.
22
- Для бинарного "mobile vs desktop" — `MobileView`. Для стилей — CSS `@media`
23
- напрямую (без JS-условия).
24
-
25
- ---
26
-
27
- ## Файловая структура
28
-
29
- ```text
30
- src/components/MediaWidth/
31
- ├── MediaWidth.tsx # Компонент-диспетчер
32
- ├── MediaMinWidth.tsx # min-width only
33
- ├── MediaMaxWidth.tsx # max-width only
34
- ├── MediaBetweenWidth.tsx # between min and max
35
- ├── useMatchMedia.ts # Хук
36
- ├── index.ts # Barrel (все 4 компонента + хук)
37
- └── __tests__/
38
- ```
14
+ Сервисный headless-компонент адаптивности и точка входа в семейство `MediaWidth`.
15
+ Рендерит `children`, когда ширина окна браузера попадает в диапазон, заданный
16
+ `minWidth` и/или `maxWidth`, и `fallback` — во всех остальных случаях.
17
+ Собственной разметки не добавляет: в DOM попадает ровно тот элемент, который
18
+ выбран по медиа-запросу.
19
+
20
+ Сам подписку на медиа-запрос не выполняет — по набору переданных props делегирует
21
+ рендер в `MediaBetweenWidth`, `MediaMinWidth` или `MediaMaxWidth`, а те уже
22
+ используют `useMatchMedia`.
23
+
24
+ Используй когда: на определённой ширине окна нужно отрендерить **другое дерево**
25
+ компонентов, а не просто другие стили — мобильный вариант дропдауна вместо
26
+ десктопного, список вместо таблицы, компактная панель вместо развёрнутой.
27
+
28
+ Не используй когда:
29
+ - Разница между ширинами чисто визуальная (отступы, шрифт, раскладка) — это
30
+ дешевле и надёжнее решается медиа-запросом в `*.module.less`, без
31
+ перемонтирования поддерева.
32
+ - Граница — мобильная (`<768px`): для этого есть `MobileView`, частный случай с
33
+ `maxWidth={EScreenWidth.SM_MAX}`.
34
+ - Нужно булево значение для props или условной разметки вокруг, а не выбор между
35
+ двумя готовыми элементами — используй хук `useMatchMedia` (или `useMobileView`
36
+ для мобильной границы).
39
37
 
40
38
  ---
41
39
 
42
40
  ## Варианты и props
43
41
 
44
- ### MediaWidth — `IMediaProps`
42
+ ### Обязательные props
45
43
 
46
- | Prop | Тип | Обязателен | Описание |
47
- |---|---|---|---|
48
- | `children` | `ReactElement \| null` | Да | Элемент рендерится при совпадении с media-query. |
49
- | `fallback` | `ReactElement \| null` | Да | Рендерится, если не совпало. |
50
- | `minWidth` | `EScreenWidth` | Нет | Нижняя граница. |
51
- | `maxWidth` | `EScreenWidth` | Нет | Верхняя граница. |
44
+ | Prop | Тип | Описание |
45
+ |---|---|---|
46
+ | `children` | `React.ReactElement \| null` | Элемент для ширины внутри диапазона. `null` — внутри диапазона не рендерится ничего |
47
+ | `fallback` | `React.ReactElement \| null` | Элемент для ширины вне диапазона. Обязателен: prop без значения по умолчанию, для «ничего» передаётся явный `null` |
52
48
 
53
- Логика выбора:
54
- - `minWidth && maxWidth` → `MediaBetweenWidth`
55
- - `minWidth` → `MediaMinWidth`
56
- - `maxWidth` → `MediaMaxWidth`
57
- - Ни один — возвращает `fallback`.
49
+ ### Опциональные props
58
50
 
59
- ### MediaMinWidth / MediaMaxWidth / MediaBetweenWidth
51
+ | Prop | Тип | По умолчанию | Описание |
52
+ |---|---|---|---|
53
+ | `minWidth` | `EScreenWidth` | — | Нижняя граница диапазона, включительно |
54
+ | `maxWidth` | `EScreenWidth` | — | Верхняя граница диапазона, включительно |
55
+
56
+ ### Как комбинация props выбирает реализацию
57
+
58
+ | Переданы | Делегирует в | Медиа-запрос |
59
+ |---|---|---|
60
+ | `minWidth` и `maxWidth` | `MediaBetweenWidth` | `(max-width: {maxWidth}) and (min-width: {minWidth})` |
61
+ | только `minWidth` | `MediaMinWidth` | `(min-width: {minWidth})` |
62
+ | только `maxWidth` | `MediaMaxWidth` | `(max-width: {maxWidth})` |
63
+ | ничего | — | запрос не строится, `window.matchMedia` не вызывается |
64
+
65
+ ### Особенности поведения
66
+
67
+ - **Без `minWidth` и `maxWidth` всегда рендерится `fallback`, а `children` — никогда.**
68
+ Это штатное поведение, а не деградация: ветка «нет ограничений» трактуется как
69
+ «условие не выполнено». Story `Fallback` фиксирует его специально. Если ширины
70
+ приходят из props потребителя и могут быть `undefined` — учитывай, что
71
+ «ограничений нет» здесь означает «показать `fallback`».
72
+ - **Границы включительные.** Значения `EScreenWidth` подобраны парами
73
+ (`XS_MAX = 575px` / `SM_MIN = 576px`, `SM_MAX = 767px` / `MD_MIN = 768px` и
74
+ т.д.), поэтому в `minWidth` передаётся `*_MIN`, в `maxWidth` — `*_MAX`. Так
75
+ соседние диапазоны стыкуются без перекрытия и без «дыр» в один пиксель.
76
+ - **Согласованность `minWidth` и `maxWidth` не проверяется.** Если `minWidth`
77
+ больше `maxWidth`, запрос просто никогда не сматчится и всегда будет рендериться
78
+ `fallback` — ни предупреждения, ни ошибки не будет.
79
+ - **Ветки взаимоисключающие.** При пересечении границы одна ветка размонтируется,
80
+ вторая монтируется: локальный state, фокус, значения неконтролируемых полей и
81
+ текущие анимации внутри поддерева теряются. Состояние, которое должно
82
+ переживать смену ширины, храни выше `MediaWidth` (или передавай его как props
83
+ в обе ветки).
84
+ - Значение медиа-запроса читается синхронно на первом рендере (`useMatchMedia`
85
+ вызывает `window.matchMedia` в инициализаторе `useState`), поэтому «мигания»
86
+ неправильной ветки на первом кадре нет.
87
+ - Пересчёт при ресайзе идёт по событию `change` у `MediaQueryList`, а не по
88
+ `resize` окна — слушатель снимается при размонтировании и переподписывается при
89
+ смене строки запроса.
90
+ - **Компонент не SSR-safe:** `window.matchMedia` вызывается на первом рендере.
91
+ Это поведение унаследовано от `useMatchMedia` и общее для всего семейства.
60
92
 
61
- Аналогичные props (`children`, `fallback`, соответствующие `min`/`max`).
93
+ ---
62
94
 
63
- ### useMatchMedia — `(query: string, initial: boolean) => boolean`
95
+ ## Дизайн-токены
64
96
 
65
- | Параметр | Описание |
66
- |---|---|
67
- | `query` | Полный media-query (например, `"(max-width: 767px)"`). |
68
- | `initial` | Начальное значение до первого рендера — критично для SSR/первого кадра. |
97
+ Собственных стилей и CSS-переменных нет — компонент не рендерит разметку.
98
+ Границы диапазонов задаются enum `EScreenWidth` (`src/helpers/breakpoints.ts`),
99
+ согласованным с LESS-переменными брейкпоинтов.
69
100
 
70
- Возвращает `true`, если query совпадает. Подписывается на `change`, возвращает актуальное значение.
101
+ ---
71
102
 
72
- ### EScreenWidth (из `@sberbusiness/triplex-next/helpers/breakpoints`)
103
+ ## Инварианты
73
104
 
74
- Breakpoint-значения: `XS_MAX`, `SM_MIN`, `SM_MAX`, `MD_MIN`, `MD_MAX`, `LG_MIN`, `LG_MAX`, `XL_MIN`, и т.д. (строковые — в px). Используются как значения `minWidth`/`maxWidth`.
105
+ - **Без `forwardRef` — осознанное исключение** из общего правила библиотеки:
106
+ компонент не рендерит собственный host-элемент, форвардить `ref` некуда.
107
+ Не добавлять и не убирать без отдельного решения — это публичный контракт.
108
+ - **Интерфейс props называется `IMediaProps`, а не `IMediaWidthProps`.**
109
+ Рассинхрон с именем компонента исторический, интерфейс экспортируется из
110
+ barrel — переименование будет breaking change. Не «чинить» походя: только
111
+ отдельным решением с записью в release notes.
112
+ - **Имена и типы props `children`, `minWidth`, `maxWidth`, `fallback`** —
113
+ публичное API, не менять. `fallback` остаётся обязательным: сделать его
114
+ опциональным можно только осознанно, это меняет контракт у потребителей.
115
+ - **Значения `EScreenWidth`** — публичное API и общая сетка дизайн-системы. Не
116
+ хардкодить пиксели в props и не заводить локальные брейкпоинты.
117
+ - **Делегирование в `MediaBetweenWidth` / `MediaMinWidth` / `MediaMaxWidth`** —
118
+ не инлайнить `useMatchMedia` в `MediaWidth.tsx`. Строки медиа-запросов живут
119
+ в трёх реализациях, и это единственное место, где они собираются.
120
+ - **Порядок веток в `if`/`else` значим:** проверка «оба props» идёт первой,
121
+ иначе комбинация `minWidth + maxWidth` схлопнулась бы до одной границы.
122
+ - **Barrel `src/components/MediaWidth/index.ts`** экспортирует все четыре
123
+ компонента и `useMatchMedia` — состав экспортов не сокращать.
124
+ - Реализация остаётся React 17-совместимой (без `useId`,
125
+ `useSyncExternalStore` и прочих React 18-only API): код синхронизируется
126
+ в `release-0`.
127
+ - **Fallback на устаревшие `addListener` / `removeListener`** в `useMatchMedia` —
128
+ это поддержка старых браузеров, где `MediaQueryList` не наследует `EventTarget`
129
+ и не имеет `addEventListener` (Safari < 14). К React 17 и синхронизации
130
+ в `release-0` он отношения не имеет: удалять его вместе с React 17-совместимостью
131
+ нельзя — это наблюдаемая регрессия у потребителей.
75
132
 
76
133
  ---
77
134
 
78
- ## Ключевые особенности реализации
135
+ ## Accessibility
79
136
 
80
- ### `children` / `fallback` обязательны — нет "пустого рендера"
137
+ - Собственной ARIA-семантики нет — компонент прозрачен для accessibility-дерева.
138
+ - Невыбранная ветка **не рендерится в DOM**, а не скрывается визуально: скринридер
139
+ и последовательность табуляции видят только актуальный вариант. Дублирования
140
+ контента для ассистивных технологий не возникает, но и «широкая» разметка на
141
+ узком экране недоступна.
142
+ - Смена ветки при ресайзе удаляет из DOM сфокусированный элемент — фокус
143
+ переходит на `<body>`. Если это критично (открытый оверлей, форма), верни
144
+ фокус явно на стороне потребителя.
145
+ - Медиа-запрос завязан на ширину окна, а не на тип ввода: на десктопе с узким
146
+ окном тоже рендерится «мобильная» ветка. Не завязывай на `MediaWidth` наличие
147
+ touch-специфичных обработчиков как единственного способа взаимодействия.
81
148
 
82
- ```ts
83
- children: React.ReactElement | null;
84
- fallback: React.ReactElement | null;
85
- ```
149
+ ---
86
150
 
87
- - Оба slot'а должны быть заданы (даже если один — `null`). Не `children?: ReactNode`.
88
- - **Render-props стиль "if/else"**, не "return null if mismatch".
151
+ ## Связанные компоненты
89
152
 
90
- ### `window.innerWidth` на первом рендере — НЕ SSR-safe
153
+ Все три реализации живут в той же папке, экспортируются из того же barrel и
154
+ собственного AI.md не имеют — их контракт описан здесь.
155
+
156
+ > **Объём AI-рефакторинга.** В рамках TRI-58 отрефакторен только `MediaWidth.tsx`:
157
+ > соседние реализации и `useMatchMedia` были вне scope задачи. В их JSDoc
158
+ > остаются недочёты (опечатка «ширина экран» в `MediaMaxWidth` / `MediaMinWidth` /
159
+ > `MediaBetweenWidth`, `@param initial` без соответствующего параметра
160
+ > в `useMatchMedia`) — семейство ещё не вычищено целиком, это отдельная задача.
161
+ > Туда же — тест на fallback `addListener` / `removeListener`: инвариант ниже
162
+ > запрещает его удалять, но ни один тест эту ветку не исполняет (во всех моках
163
+ > `MediaQueryList` есть `addEventListener`).
164
+
165
+ - `MediaBetweenWidth` (`src/components/MediaWidth/MediaBetweenWidth.tsx`) —
166
+ диапазон между двумя границами. Props: `minWidth` и `maxWidth` **обязательные**,
167
+ плюс `children` и `fallback`. Интерфейс `IMediaBetweenWidthProps`.
168
+ - `MediaMinWidth` (`src/components/MediaWidth/MediaMinWidth.tsx`) — только нижняя
169
+ граница, `minWidth` обязателен. Интерфейс `IMediaMinWidthProps`.
170
+ - `MediaMaxWidth` (`src/components/MediaWidth/MediaMaxWidth.tsx`) — только верхняя
171
+ граница, `maxWidth` обязателен. Интерфейс `IMediaMaxWidthProps`.
172
+ - `useMatchMedia` (`src/components/MediaWidth/useMatchMedia.ts`) — хук подписки на
173
+ произвольный медиа-запрос, основа всего семейства. Принимает строку запроса,
174
+ возвращает `boolean`. Годится и для не-ширинных запросов: `CarouselButton`
175
+ использует его с `(pointer: coarse)`.
176
+ - `MobileView` (`src/components/MobileView/`) — частный случай `MediaWidth` с
177
+ `maxWidth={EScreenWidth.SM_MAX}`, со своим AI.md. Для мобильной границы
178
+ используется он, а не `MediaWidth` напрямую.
179
+ - `WindowResizeListener` (`src/components/WindowResizeListener/`) — альтернатива
180
+ для императивного случая: даёт колбэк на поток событий `resize`, а не рендерит
181
+ ветку по медиа-запросу. Правило выбора: нужно **что-то показать** на
182
+ определённой ширине — `MediaWidth`; нужно **что-то посчитать/сделать** на
183
+ ресайз — `WindowResizeListener`.
184
+
185
+ Разница между `MediaWidth` и тремя реализациями: у `MediaWidth` обе границы
186
+ опциональны и выбор реализации делается за потребителя; у реализаций
187
+ соответствующие границы обязательны. Прямое использование реализации оправдано,
188
+ когда набор границ известен статически и «пустая» комбинация невозможна по
189
+ построению.
190
+
191
+ ### Потребители внутри библиотеки
192
+
193
+ Компонентом `MediaWidth`: `MobileView` (и, транзитивно, все его потребители).
194
+ Хуком `useMatchMedia`: `CarouselButton`, `useMobileView`.
195
+
196
+ В unit-тестах потребителей ветка задаётся подменой `window.matchMedia` (как в
197
+ `MediaWidth.test.tsx` и `Dropdown.test.tsx`) либо мокированием модуля
198
+ `useMatchMedia` (как в `IslandWidget.test.tsx`).
91
199
 
92
- ```ts
93
- useMatchMedia(`(min-width: ${minWidth})`, window.innerWidth >= parseInt(minWidth));
94
- ```
200
+ ---
95
201
 
96
- - `window.innerWidth` в initial-аргументе выполняется **при рендере**, не в `useEffect` — упадёт на SSR.
97
- - Потребители в SSR должны оборачивать в ClientOnly или подавать `false`/`true` безопасный default через свой wrapper.
202
+ ## Stories
98
203
 
99
- ### `useMatchMedia` — `addEventListener("change")`, не deprecated `addListener`
204
+ Основные истории: `stories/MediaWidth/MediaWidth.stories.tsx`
205
+ Файлы примеров: `stories/MediaWidth/examples/`
100
206
 
101
- ```ts
102
- mediaQueryList.addEventListener("change", handleChangeMatches);
103
- ```
207
+ | Story | Example file | Что демонстрирует |
208
+ |---|---|---|
209
+ | `Playground` | — | Интерактивный подбор `minWidth` / `maxWidth`, включая значение `undefined` |
210
+ | `Default` | `DefaultExample.tsx` | Обе границы: контент виден в диапазоне 768px–1199px |
211
+ | `MinWidth` | `MinWidthExample.tsx` | Только нижняя граница: контент от 768px и шире |
212
+ | `MaxWidth` | `MaxWidthExample.tsx` | Только верхняя граница: контент до 1199px включительно |
213
+ | `Fallback` | `FallbackExample.tsx` | Без границ: всегда рендерится `fallback` |
214
+ | `Example: MobileView` | `MobileViewExample.tsx` | Связь общего случая с частным — `MobileView` вместо ручной мобильной границы |
104
215
 
105
- - Современный API. Safari 13.1+, Chrome 76+ — ок.
106
- - **Legacy `addListener` не используется** — если нужна поддержка старых Safari, нужен polyfill.
216
+ Скриншот-тестами покрыта только story `Example: MobileView` (baseline
217
+ `mediawidth--mobile-view-story--xs.png` и `--xl.png`): на viewport `xs` (575px)
218
+ рендерится мобильная ветка, на `xl` (1200px) — `fallback`. Остальные stories
219
+ помечены `testRunner: { skip: true }` — их результат целиком определяется
220
+ шириной viewport и уже проверяется этой парой скриншотов.
107
221
 
108
- ### `useEffect` зависит только от `query`
222
+ ---
223
+
224
+ ## История изменений
109
225
 
110
- Колбэк `handleChangeMatches` всегда зовёт `setMatches(event.matches)` — `initial` игнорируется после первого рендера.
226
+ | Дата | Изменение |
227
+ |---|---|
228
+ | 2026-08-18 | TRI-104: в `related` и «Связанные компоненты» добавлен `WindowResizeListener` — обратная сторона симметричной связи-альтернативы. Код и публичный API не затронуты. |
229
+ | 2026-08-11 | Создан документ. AI-рефакторинг (TRI-58): `displayName` у `MediaWidth`, исправлены опечатки и дополнен JSDoc props и компонента, unit-тесты расширены с 7 до 19 кейсов (проверяются строки медиа-запросов, выбор реализации, `null`-ветки, переподписка и отписка). Публичный API не изменён (props, `IMediaProps`, barrel-экспорты; `forwardRef` по-прежнему осознанно отсутствует). |
111
230
 
112
- ### `MediaBetweenWidth` query — AND двух conditions
231
+ ---
113
232
 
114
- ```ts
115
- `(max-width: ${maxWidth}) and (min-width: ${minWidth})`
116
- ```
233
+ ## Примеры использования
117
234
 
118
- Оба условия должны выполняться. `between` — это **пересечение**.
235
+ ### Default
119
236
 
120
- ### `MediaWidth` — не "матчит всё" по умолчанию
237
+ `stories/MediaWidth/examples/DefaultExample.tsx`
121
238
 
122
- Если ни `minWidth`, ни `maxWidth` не переданы — возвращает `fallback`. Это неочевидно: потребители могут ожидать, что пустая media-query рендерит `children`. Потому всегда **передавай хотя бы одну границу**.
239
+ ```tsx
240
+ import React from "react";
241
+ import { MediaWidth, EScreenWidth } from "@sberbusiness/triplex-next";
123
242
 
124
- ---
243
+ export const DefaultExample = () => (
244
+ <MediaWidth
245
+ minWidth={EScreenWidth.MD_MIN}
246
+ maxWidth={EScreenWidth.LG_MAX}
247
+ fallback={<div>Fallback: ширина экрана за пределами диапазона 768px–1199px</div>}
248
+ >
249
+ <div>Контент виден только на экранах шириной от 768px до 1199px включительно</div>
250
+ </MediaWidth>
251
+ );
252
+ ```
125
253
 
126
- ## Инварианты
254
+ ### MinWidth
127
255
 
128
- - **`children` и `fallback` — обязательные `ReactElement | null`**, не `ReactNode`. Не менять на optional.
129
- - **`EScreenWidth` как тип `minWidth`/`maxWidth`** — потребители завязаны на брейкпоинты библиотеки; произвольные строки не принимаются.
130
- - **`useMatchMedia(initial)` аргумент обязателен** — отсутствие initial ломает SSR-совместимость (которая и так условная).
131
- - **`window.innerWidth` в initial** — legacy-approach. Не вставлять в SSR-контекст без защиты.
132
- - **`addEventListener("change")`** — современный API; не переключать на deprecated `addListener`.
133
- - **`MediaWidth` без границ → `fallback`** — документированное поведение, не менять.
256
+ `stories/MediaWidth/examples/MinWidthExample.tsx`
134
257
 
135
- ---
258
+ ```tsx
259
+ import React from "react";
260
+ import { MediaWidth, EScreenWidth } from "@sberbusiness/triplex-next";
136
261
 
137
- ## Accessibility
262
+ export const MinWidthExample = () => (
263
+ <MediaWidth minWidth={EScreenWidth.MD_MIN} fallback={<div>Fallback: ширина экрана менее 768px</div>}>
264
+ <div>Контент виден на экранах шириной 768px и более</div>
265
+ </MediaWidth>
266
+ );
267
+ ```
138
268
 
139
- - JS-условный рендеринг → **содержимое DOM меняется на брейкпоинте**. При переключении фокуса/viewport/скринридера это может вызвать нежелательный повторный анонс.
140
- - Предпочитай CSS `@media` + `display: none` там, где возможно: DOM стабилен, скринридеры видят весь контент (если это желаемое поведение) или выбираешь, какой показать через `aria-hidden`.
141
- - Используй `MediaWidth`/`MobileView` только тогда, когда действительно нужно **разное дерево React'а** (разные компоненты, не CSS-вариации).
269
+ ### MaxWidth
142
270
 
143
- ---
271
+ `stories/MediaWidth/examples/MaxWidthExample.tsx`
144
272
 
145
- ## Дизайн-токены
273
+ ```tsx
274
+ import React from "react";
275
+ import { MediaWidth, EScreenWidth } from "@sberbusiness/triplex-next";
146
276
 
147
- Нет. Брейкпоинты — `EScreenWidth` (строковые px).
277
+ export const MaxWidthExample = () => (
278
+ <MediaWidth maxWidth={EScreenWidth.LG_MAX} fallback={<div>Fallback: ширина экрана более 1199px</div>}>
279
+ <div>Контент виден на экранах шириной до 1199px включительно</div>
280
+ </MediaWidth>
281
+ );
282
+ ```
148
283
 
149
- ---
284
+ ### Fallback
150
285
 
151
- ## Связанные компоненты
286
+ `stories/MediaWidth/examples/FallbackExample.tsx`
152
287
 
153
- - `MobileView` — частный случай (mobile vs desktop), use-case определён.
154
- - `IslandWidget` — использует `useMatchMedia` для адаптивного сворачивания.
155
- - `helpers/breakpoints.EScreenWidth` — источник брейкпоинтов.
288
+ ```tsx
289
+ import React from "react";
290
+ import { MediaWidth } from "@sberbusiness/triplex-next";
156
291
 
157
- ---
292
+ export const FallbackExample = () => (
293
+ <MediaWidth fallback={<div>Fallback отображается всегда, если не заданы minWidth и maxWidth</div>}>
294
+ {null}
295
+ </MediaWidth>
296
+ );
297
+ ```
158
298
 
159
- ## Stories
299
+ ### Example: MobileView
160
300
 
161
- Нет. Компонент утилитарный; покрытие в тестах и через потребителей.
301
+ `stories/MediaWidth/examples/MobileViewExample.tsx`
162
302
 
163
- ---
303
+ ```tsx
304
+ import React from "react";
305
+ import { MobileView } from "@sberbusiness/triplex-next";
164
306
 
165
- ## История изменений
307
+ export const MobileViewExample = () => (
308
+ <MobileView fallback={<div>Десктоп: ширина экрана 768px и более</div>}>
309
+ <div>Мобильный: ширина экрана менее 768px</div>
310
+ </MobileView>
311
+ );
312
+ ```
166
313
 
167
- | Дата | Изменение |
168
- |---|---|
169
- | 2026-04-18 | Создан документ |