@sberbusiness/triplex-next-mcp-server 0.24.0-beta1
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 +124 -0
- package/bundle/.gitkeep +0 -0
- package/bundle/components/AbstractTree.md +198 -0
- package/bundle/components/AccordionBase.md +227 -0
- package/bundle/components/Alert.md +317 -0
- package/bundle/components/Amount.md +225 -0
- package/bundle/components/AmountField.md +289 -0
- package/bundle/components/Avatar.md +209 -0
- package/bundle/components/Badge.md +277 -0
- package/bundle/components/Body.md +167 -0
- package/bundle/components/Button.md +230 -0
- package/bundle/components/ButtonDropdown.md +159 -0
- package/bundle/components/ButtonIcon.md +122 -0
- package/bundle/components/Calendar.md +445 -0
- package/bundle/components/Card.md +374 -0
- package/bundle/components/CarouselExtended.md +250 -0
- package/bundle/components/Checkbox.md +126 -0
- package/bundle/components/CheckboxTree.md +280 -0
- package/bundle/components/CheckboxTreeExtended.md +321 -0
- package/bundle/components/CheckboxXGroup.md +68 -0
- package/bundle/components/CheckboxYGroup.md +67 -0
- package/bundle/components/Chip.md +404 -0
- package/bundle/components/ChipGroup.md +179 -0
- package/bundle/components/Col.md +221 -0
- package/bundle/components/CollapsableTree.md +255 -0
- package/bundle/components/Confirm.md +343 -0
- package/bundle/components/DateField.md +371 -0
- package/bundle/components/DatePickerExtended.md +342 -0
- package/bundle/components/DateRange.md +275 -0
- package/bundle/components/DesignTokens.md +385 -0
- package/bundle/components/Divider.md +196 -0
- package/bundle/components/DocumentNumberEdit.md +280 -0
- package/bundle/components/Dropdown.md +433 -0
- package/bundle/components/Ellipsis.md +208 -0
- package/bundle/components/EmptyView.md +99 -0
- package/bundle/components/ExpandAnimation.md +281 -0
- package/bundle/components/Footer.md +339 -0
- package/bundle/components/FormField.md +326 -0
- package/bundle/components/FormGroup.md +99 -0
- package/bundle/components/Gap.md +113 -0
- package/bundle/components/Header.md +280 -0
- package/bundle/components/HelpBox.md +154 -0
- package/bundle/components/IconWrapper.md +145 -0
- package/bundle/components/Island.md +197 -0
- package/bundle/components/IslandAccordion.md +230 -0
- package/bundle/components/IslandWidget.md +233 -0
- package/bundle/components/KeyDownListener.md +157 -0
- package/bundle/components/LightBox.md +322 -0
- package/bundle/components/Link.md +161 -0
- package/bundle/components/List.md +247 -0
- package/bundle/components/ListMaster.md +204 -0
- package/bundle/components/Loader.md +161 -0
- package/bundle/components/LoaderScreen.md +134 -0
- package/bundle/components/Marker.md +127 -0
- package/bundle/components/MarkerStatus.md +148 -0
- package/bundle/components/MediaWidth.md +169 -0
- package/bundle/components/MobileView.md +120 -0
- package/bundle/components/ModalWindow.md +308 -0
- package/bundle/components/MonthYearField.md +168 -0
- package/bundle/components/MultiselectField.md +213 -0
- package/bundle/components/Notification.md +233 -0
- package/bundle/components/NumberField.md +178 -0
- package/bundle/components/OrderedList.md +169 -0
- package/bundle/components/Overlay.md +237 -0
- package/bundle/components/Page.md +246 -0
- package/bundle/components/Pagination.md +298 -0
- package/bundle/components/Portal.md +119 -0
- package/bundle/components/Radio.md +174 -0
- package/bundle/components/Row.md +125 -0
- package/bundle/components/SMSField.md +160 -0
- package/bundle/components/SegmentedControl.md +235 -0
- package/bundle/components/SelectExtendedField.md +322 -0
- package/bundle/components/SelectField.md +213 -0
- package/bundle/components/Skeleton.md +129 -0
- package/bundle/components/Slider.md +157 -0
- package/bundle/components/SliderExtended.md +210 -0
- package/bundle/components/SliderRange.md +160 -0
- package/bundle/components/SmallInput.md +101 -0
- package/bundle/components/Spoiler.md +121 -0
- package/bundle/components/StatusTracker.md +151 -0
- package/bundle/components/Step.md +121 -0
- package/bundle/components/Stepper.md +163 -0
- package/bundle/components/Suggest.md +160 -0
- package/bundle/components/SuggestField.md +157 -0
- package/bundle/components/SwipeableArea.md +144 -0
- package/bundle/components/Table.md +199 -0
- package/bundle/components/Tabs.md +152 -0
- package/bundle/components/TabsExtended.md +273 -0
- package/bundle/components/TabsLine.md +189 -0
- package/bundle/components/Tag.md +135 -0
- package/bundle/components/TagColor.md +121 -0
- package/bundle/components/TagGroup.md +100 -0
- package/bundle/components/TextField.md +152 -0
- package/bundle/components/TextareaField.md +124 -0
- package/bundle/components/ThemeProvider.md +181 -0
- package/bundle/components/Tooltip.md +254 -0
- package/bundle/components/TopOverlay.md +145 -0
- package/bundle/components/TreeView.md +224 -0
- package/bundle/components/Triggers.md +121 -0
- package/bundle/guides/codestyle.md +205 -0
- package/bundle/guides/commits.md +166 -0
- package/bundle/guides/context.md +277 -0
- package/bundle/guides/stories.md +618 -0
- package/bundle/guides/template.md +154 -0
- package/bundle/guides/tests.md +301 -0
- package/bundle/icons.json +4156 -0
- package/bundle/manifest.json +796 -0
- package/bundle/release-notes/1.1.0.mdx +26 -0
- package/bundle/release-notes/1.1.1.mdx +14 -0
- package/bundle/release-notes/1.10.0.mdx +43 -0
- package/bundle/release-notes/1.11.0.mdx +19 -0
- package/bundle/release-notes/1.12.0.mdx +21 -0
- package/bundle/release-notes/1.13.0.mdx +43 -0
- package/bundle/release-notes/1.14.0.mdx +29 -0
- package/bundle/release-notes/1.15.0.mdx +56 -0
- package/bundle/release-notes/1.16.0.mdx +55 -0
- package/bundle/release-notes/1.17.0.mdx +15 -0
- package/bundle/release-notes/1.18.0.mdx +24 -0
- package/bundle/release-notes/1.19.0.mdx +48 -0
- package/bundle/release-notes/1.19.1.mdx +9 -0
- package/bundle/release-notes/1.2.0.mdx +80 -0
- package/bundle/release-notes/1.20.0.mdx +48 -0
- package/bundle/release-notes/1.21.0.mdx +66 -0
- package/bundle/release-notes/1.22.0.mdx +75 -0
- package/bundle/release-notes/1.23.0.mdx +50 -0
- package/bundle/release-notes/1.24.0.mdx +59 -0
- package/bundle/release-notes/1.25.0.mdx +52 -0
- package/bundle/release-notes/1.26.0.mdx +11 -0
- package/bundle/release-notes/1.3.0.mdx +21 -0
- package/bundle/release-notes/1.4.0.mdx +37 -0
- package/bundle/release-notes/1.5.0.mdx +24 -0
- package/bundle/release-notes/1.6.0.mdx +37 -0
- package/bundle/release-notes/1.6.1.mdx +11 -0
- package/bundle/release-notes/1.7.0.mdx +29 -0
- package/bundle/release-notes/1.8.0.mdx +38 -0
- package/bundle/release-notes/1.9.0.mdx +28 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +324 -0
- package/dist/index.js.map +1 -0
- package/package.json +51 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: LoaderScreen
|
|
3
|
+
category: Feedback
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [Loader, Skeleton, LightBox, List]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: stories/Loaders/LoaderScreen
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# LoaderScreen
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Контейнер-оверлей, рендерящий `LoaderSmall` или `LoaderMiddle` с полупрозрачным
|
|
17
|
+
бэкдропом — поверх блока/экрана, пока идёт загрузка. Centered по `flexbox`
|
|
18
|
+
внутри относительно расположенного родителя (наружный элемент должен иметь
|
|
19
|
+
`position: relative` или быть самим "экраном").
|
|
20
|
+
|
|
21
|
+
Используй когда: нужно закрыть контент оверлеем на время загрузки
|
|
22
|
+
(в Island'е, Modal'е, Content-wrapper'е). Для inline-спиннера в кнопке —
|
|
23
|
+
`LoaderSmall` напрямую. Для skeleton-загрузки известной структуры — `Skeleton`.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Файловая структура
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
src/components/LoaderScreen/
|
|
31
|
+
├── LoaderScreen.tsx # FC, <div> + lоадер
|
|
32
|
+
├── index.ts # Barrel
|
|
33
|
+
├── styles/LoaderScreen.module.less
|
|
34
|
+
└── __tests__/LoaderScreen.test.tsx
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Варианты и props
|
|
40
|
+
|
|
41
|
+
### `ILoaderScreenProps extends HTMLAttributes<HTMLDivElement>`
|
|
42
|
+
|
|
43
|
+
| Prop | Тип | Default | Описание |
|
|
44
|
+
|---|---|---|---|
|
|
45
|
+
| `type` | `"small" \| "middle"` | — (обязателен) | Тип лоадера внутри. `small` — LoaderSmall, `middle` — LoaderMiddle. |
|
|
46
|
+
| `theme` | `ELoaderSmallTheme` | `BRAND` | Только для `type="small"`. Игнорируется для `middle`. |
|
|
47
|
+
| `size` | `EComponentSize` | `MD` | Только для `type="small"`. Игнорируется для `middle`. |
|
|
48
|
+
| `className`, `...HTMLDivAttributes` | — | — | Стандартные. |
|
|
49
|
+
|
|
50
|
+
**`type` — строковый литерал**, не enum. Публичный API. Не смешивать с `ELoaderSmallTheme`.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Ключевые особенности реализации
|
|
55
|
+
|
|
56
|
+
### Два backdrop-класса по типу
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
{
|
|
60
|
+
[styles.loaderSmallBackdrop]: type === "small",
|
|
61
|
+
[styles.loaderMiddleBackdrop]: type === "middle",
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- **`loaderSmallBackdrop`** и **`loaderMiddleBackdrop`** задают разную прозрачность/цвет бэкдропа. Middle обычно более явный (полноценный overlay), Small — лёгкий полупрозрачный.
|
|
66
|
+
|
|
67
|
+
### Middle обёрнут в дополнительный `<div>`
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
<div className={styles.loaderMiddleBackground}>
|
|
71
|
+
<LoaderMiddle />
|
|
72
|
+
</div>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Внутренний `background`-wrapper — для "карточки" вокруг точек LoaderMiddle.
|
|
76
|
+
LoaderSmall — просто инлайн-элемент по центру.
|
|
77
|
+
|
|
78
|
+
### Игнорирование `theme`/`size` для `type="middle"`
|
|
79
|
+
|
|
80
|
+
`LoaderMiddle` API-less, так что `theme` и `size` принимаются, но не
|
|
81
|
+
используются при `type === "middle"`. Не выкидывать их — потребители
|
|
82
|
+
могут переключать `type` динамически без очистки props.
|
|
83
|
+
|
|
84
|
+
### Не forwardRef
|
|
85
|
+
|
|
86
|
+
Компонент — `React.FC`, не `forwardRef`. Это отступление от общего правила
|
|
87
|
+
библиотеки (`forwardRef обязателен`). Известный legacy-момент; для нового
|
|
88
|
+
API-использования нужен ref — оборачивай снаружи.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Инварианты
|
|
93
|
+
|
|
94
|
+
- **`type: "small" | "middle"`** — строковый литерал. Не заменять на enum без breaking-change.
|
|
95
|
+
- **`theme` / `size` применяются только при `type="small"`** — не разворачивать на `middle` без изменения Loader.
|
|
96
|
+
- **`FC`, без forwardRef** — технический долг. Исправлять — breaking (меняется тип).
|
|
97
|
+
- **Centered через flex внутри оверлея** — родитель должен иметь `position: relative` (или LoaderScreen должен использоваться на фоне самостоятельного блока).
|
|
98
|
+
- **Бэкдроп встроен в LoaderScreen** — отдельно менять прозрачность нельзя, только переопределением CSS-переменной/через `className`.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Accessibility
|
|
103
|
+
|
|
104
|
+
- `role="status"` и `aria-label="loading"` приходят от вложенных `LoaderSmall`/`LoaderMiddle` — LoaderScreen сам ARIA-атрибутов не добавляет.
|
|
105
|
+
- `<div>`-оверлей **не блокирует клики** по контенту под ним — потребитель должен либо расположить LoaderScreen над блоком с `pointer-events`, либо использовать его в модалках/LightBox, где фокус и клики уже контролируются.
|
|
106
|
+
- Для правильной семантики при глобальной загрузке — ставь `aria-busy="true"` на родительский контейнер.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Дизайн-токены
|
|
111
|
+
|
|
112
|
+
Нет публичных переменных — цвета бэкдропа в `styles/LoaderScreen.module.less`.
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Связанные компоненты
|
|
117
|
+
|
|
118
|
+
- `Loader` (`LoaderSmall`, `LoaderMiddle`) — вложенные компоненты.
|
|
119
|
+
- `ELoaderSmallTheme`, `EComponentSize` — enum'ы пропсов.
|
|
120
|
+
- `List`, `LightBox`, `ModalWindow` — типовые потребители (оверлей над контентом).
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Stories
|
|
125
|
+
|
|
126
|
+
`stories/Loaders/LoaderScreen/` — stories для обоих типов.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## История изменений
|
|
131
|
+
|
|
132
|
+
| Дата | Изменение |
|
|
133
|
+
|---|---|
|
|
134
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Marker
|
|
3
|
+
category: Feedback
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [MarkerStatus, Badge, TagColor]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: ""
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Marker
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Тонкая обёртка над `Badge.Dot` — цветной кружок-статус (success/error/
|
|
17
|
+
warning/waiting). Содержательно это **именованный preset цвета** для точки,
|
|
18
|
+
чтобы не передавать `palette`-атрибут каждый раз.
|
|
19
|
+
|
|
20
|
+
Используй когда: нужен компактный индикатор статуса (в строке таблицы,
|
|
21
|
+
заголовке, рядом с меткой) и выбор из фиксированной 4-статусной палитры
|
|
22
|
+
семантики. Для статуса с подписью — `MarkerStatus`. Для кастомного цвета —
|
|
23
|
+
`Badge.Dot` напрямую.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Файловая структура
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
src/components/Marker/
|
|
31
|
+
├── Marker.tsx # FC, обёртка над Badge.Dot
|
|
32
|
+
├── enums.ts # EMarkerStatus (SUCCESS/ERROR/WARNING/WAITING)
|
|
33
|
+
├── utils.ts # statusToClassNameMap — публичная, используется MarkerStatus
|
|
34
|
+
├── styles/Marker.module.less # Цвета статусов
|
|
35
|
+
└── index.ts # Barrel
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Варианты и props
|
|
41
|
+
|
|
42
|
+
### `IMarkerProps extends IBadgeDotProps`
|
|
43
|
+
|
|
44
|
+
| Prop | Тип | Обязателен | Описание |
|
|
45
|
+
|---|---|---|---|
|
|
46
|
+
| `status` | `EMarkerStatus` | Да | Семантический статус (цвет). |
|
|
47
|
+
| `...IBadgeDotProps` | — | — | Все props `Badge.Dot` (size, className, прочие). |
|
|
48
|
+
|
|
49
|
+
### EMarkerStatus
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
enum EMarkerStatus {
|
|
53
|
+
SUCCESS = "success",
|
|
54
|
+
ERROR = "error",
|
|
55
|
+
WARNING = "warning",
|
|
56
|
+
WAITING = "waiting",
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Четыре фиксированных статуса. Расширение — breaking change.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Ключевые особенности реализации
|
|
65
|
+
|
|
66
|
+
### Реализация — одна строка
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<Badge.Dot className={clsx(styles.marker, statusToClassNameMap[status], className)} {...rest} />
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
- Поверх `Badge.Dot` накладывается класс `.marker` + один из `.success/.error/.warning/.waiting` из `Marker.module.less`, которые переопределяют цвета у точки.
|
|
73
|
+
- Все остальные props `Badge.Dot` (включая `size`, `style`) прокидываются как есть.
|
|
74
|
+
|
|
75
|
+
### `statusToClassNameMap` — экспортируемая утилита
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
export const statusToClassNameMap = { [EMarkerStatus.SUCCESS]: styles.success, ... };
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- **Экспортируется для переиспользования в `MarkerStatus`** (который применяет те же классы к своему контейнеру для окраски текста/описания).
|
|
82
|
+
- Если добавляешь статус — обязательно обнови `utils.ts` и LESS-стили, и проверь, что `MarkerStatus` тоже подтягивает новый класс.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Инварианты
|
|
87
|
+
|
|
88
|
+
- **`EMarkerStatus`** (4 значения) — публичный API. Расширение — breaking.
|
|
89
|
+
- **`Marker = Badge.Dot + className`** — тонкая обёртка; избегать добавления своих props, которые размажут семантику со `Badge`.
|
|
90
|
+
- **`statusToClassNameMap`** экспортируется из `utils.ts` — `MarkerStatus` зависит от неё. Не менять shape.
|
|
91
|
+
- **`size` приходит от `Badge.Dot`** (через `IBadgeDotProps`), а не кастомизируется Marker'ом.
|
|
92
|
+
- **FC, не forwardRef** — ref прокидывается `Badge.Dot` внутри? Проверь перед изменением.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Accessibility
|
|
97
|
+
|
|
98
|
+
- `Badge.Dot` по умолчанию — декоративный элемент без ARIA. Для анонсирования статуса скринридером потребитель должен добавить `aria-label` через `...rest` или сопроводить текстом рядом.
|
|
99
|
+
- `MarkerStatus` уже выводит текстовый статус — там a11y закрыт.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Дизайн-токены
|
|
104
|
+
|
|
105
|
+
Цвета статусов заданы в `styles/Marker.module.less` (не через CSS-переменные). Для новой темы статусов — переопределяй в LESS.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Связанные компоненты
|
|
110
|
+
|
|
111
|
+
- `Badge` / `Badge.Dot` — основа.
|
|
112
|
+
- `MarkerStatus` — Marker + текст + описание, использует тот же `statusToClassNameMap`.
|
|
113
|
+
- `TagColor` — альтернатива для статуса с подписью внутри "пилюли".
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Stories
|
|
118
|
+
|
|
119
|
+
Нет отдельных — только через `MarkerStatus.stories.tsx` (там показаны все 4 статуса).
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## История изменений
|
|
124
|
+
|
|
125
|
+
| Дата | Изменение |
|
|
126
|
+
|---|---|
|
|
127
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: MarkerStatus
|
|
3
|
+
category: Feedback
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [Marker, Badge, Typography]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: stories/MarkerStatus/MarkerStatus.stories.tsx
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MarkerStatus
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Статус-блок: цветная точка (`Marker`) + заголовок (`children`) + опциональное
|
|
17
|
+
описание. Окрашивает **текст заголовка/описания** цветом статуса через
|
|
18
|
+
общий `statusToClassNameMap` (из `Marker/utils`). Два размера — MD / LG.
|
|
19
|
+
|
|
20
|
+
Используй когда: нужна компактная семантическая индикация состояния с
|
|
21
|
+
подписью (успех операции, ошибка, pending). Для просто точки без текста —
|
|
22
|
+
`Marker`. Для статуса-пилюли с фоном — `TagColor`.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Файловая структура
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
src/components/MarkerStatus/
|
|
30
|
+
├── MarkerStatus.tsx # FC, div + Marker + Text/Caption
|
|
31
|
+
├── index.ts # Barrel
|
|
32
|
+
├── styles/MarkerStatus.module.less # Цвета текста по статусу, размерные варианты
|
|
33
|
+
└── __tests__/MarkerStatus.test.tsx
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Варианты и props
|
|
39
|
+
|
|
40
|
+
### `IMarkerStatusProps extends HTMLAttributes<HTMLDivElement>`
|
|
41
|
+
|
|
42
|
+
| Prop | Тип | Default | Описание |
|
|
43
|
+
|---|---|---|---|
|
|
44
|
+
| `status` | `EMarkerStatus` (`SUCCESS`/`ERROR`/`WARNING`/`WAITING`) | — | Обязателен. Цвет точки и текста. |
|
|
45
|
+
| `children` | `ReactNode` | — | Заголовок (основной текст статуса). Рендерится в `Text size=B4` (MD) / `B3` (LG). |
|
|
46
|
+
| `description` | `ReactNode` | — | Доп. описание под заголовком. MD — `Caption C1 SECONDARY`; LG — `Text B4 SECONDARY`. |
|
|
47
|
+
| `size` | `EComponentSize.MD \| EComponentSize.LG` | `MD` | **Ограниченный enum-subset** — нет `SM`. |
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Ключевые особенности реализации
|
|
52
|
+
|
|
53
|
+
### Размер = `EComponentSize.MD | EComponentSize.LG`
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
size?: EComponentSize.MD | EComponentSize.LG;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- **SM запрещён на уровне типа**. Если передать `SM` — TS ошибка. Для runtime-значения — визуал не определён.
|
|
60
|
+
- Если появится требование SM — добавить маппинги `sizeToClassNameMap`, `markerStatusSizeToTextSizeMap` и LESS-стиль.
|
|
61
|
+
|
|
62
|
+
### `size` пробрасывается в `Marker` (Badge.Dot)
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<Marker status={status} size={size} />
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Marker получает `size` через `...IBadgeDotProps` — `Badge.Dot` сам определяет, как размер влияет на диаметр точки.
|
|
69
|
+
|
|
70
|
+
### Маппинг размера → typography-размер
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
const markerStatusSizeToTextSizeMap = {
|
|
74
|
+
[EComponentSize.MD]: ETextSize.B4,
|
|
75
|
+
[EComponentSize.LG]: ETextSize.B3,
|
|
76
|
+
};
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- MD → B4, LG → B3. Публичный контракт (визуальная спецификация).
|
|
80
|
+
|
|
81
|
+
### `description` — разный компонент по размеру
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
size === EComponentSize.MD
|
|
85
|
+
? <Caption size={C1} type={SECONDARY}>{description}</Caption>
|
|
86
|
+
: <Text size={B4} type={SECONDARY}>{description}</Text>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
- **MD → Caption (C1)**, **LG → Text (B4 SECONDARY)**. Меньшая строка (Caption) в меньшем размере.
|
|
90
|
+
- `type=SECONDARY` — приглушённый цвет.
|
|
91
|
+
|
|
92
|
+
### Цвет текста — через `statusToClassNameMap` из Marker/utils
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<div className={clsx(styles.markerStatus, sizeToClassNameMap[size], statusToClassNameMap[status], className)}>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
- **Переиспользование** CSS-Modules класса из `Marker/styles` — заложена **кросс-файловая зависимость**: `Marker/utils.ts` импортирует `Marker.module.less`. Если стили MarkerStatus переопределяют цвет текста, то они опираются на то, что корневой класс `.success/.error/...` уже задан.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Инварианты
|
|
103
|
+
|
|
104
|
+
- **`status` обязателен** — без него семантика теряется.
|
|
105
|
+
- **`size: MD | LG`** — тип-ограниченный subset `EComponentSize`. Расширение — breaking для потребителей, проверяющих тип.
|
|
106
|
+
- **Маппинг размера → typography** (B4/B3 для заголовка; C1/B4 для описания) — зафиксирован в коде, публичная визуальная спецификация.
|
|
107
|
+
- **Использует `Marker/utils.statusToClassNameMap`** — изменение shape в Marker сломает MarkerStatus.
|
|
108
|
+
- **FC, не forwardRef** — ref вовне не прокидывается. Legacy.
|
|
109
|
+
- **`data-tx={npm_package_version}`** — маркер версии. Сохранять.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Accessibility
|
|
114
|
+
|
|
115
|
+
- `<div>` — без ARIA-роли. Статус должен читаться скринридером через **текст в children**. Не полагайся только на цвет.
|
|
116
|
+
- Если children тоже визуально отражает статус (например, "Ошибка"), и нужна дополнительная семантика — добавь `role="status"` через `...rest` или оборачивай MarkerStatus в live region.
|
|
117
|
+
- Цвет текста — только как визуальный акцент. WCAG-контраст контролируется токенами `SECONDARY`/статус-цветами; при кастомных темах — проверить.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Дизайн-токены
|
|
122
|
+
|
|
123
|
+
Нет публичных переменных компонента; цвета текста статусов заданы в
|
|
124
|
+
`styles/MarkerStatus.module.less`. Цвет точки — через `Marker`.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Связанные компоненты
|
|
129
|
+
|
|
130
|
+
- `Marker` — цветная точка; то же `EMarkerStatus` и `statusToClassNameMap`.
|
|
131
|
+
- `Badge.Dot` — база для Marker.
|
|
132
|
+
- `Typography` (`Text`, `Caption`) — для заголовка и описания.
|
|
133
|
+
- `TagColor` — альтернатива с фоном-пилюлей.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Stories
|
|
138
|
+
|
|
139
|
+
`stories/MarkerStatus/MarkerStatus.stories.tsx`
|
|
140
|
+
Примеры: `stories/MarkerStatus/examples/`
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## История изменений
|
|
145
|
+
|
|
146
|
+
| Дата | Изменение |
|
|
147
|
+
|---|---|
|
|
148
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: MediaWidth
|
|
3
|
+
category: Utilities
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [MobileView, IslandWidget]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: ""
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# MediaWidth
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
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
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Варианты и props
|
|
43
|
+
|
|
44
|
+
### MediaWidth — `IMediaProps`
|
|
45
|
+
|
|
46
|
+
| Prop | Тип | Обязателен | Описание |
|
|
47
|
+
|---|---|---|---|
|
|
48
|
+
| `children` | `ReactElement \| null` | Да | Элемент рендерится при совпадении с media-query. |
|
|
49
|
+
| `fallback` | `ReactElement \| null` | Да | Рендерится, если не совпало. |
|
|
50
|
+
| `minWidth` | `EScreenWidth` | Нет | Нижняя граница. |
|
|
51
|
+
| `maxWidth` | `EScreenWidth` | Нет | Верхняя граница. |
|
|
52
|
+
|
|
53
|
+
Логика выбора:
|
|
54
|
+
- `minWidth && maxWidth` → `MediaBetweenWidth`
|
|
55
|
+
- `minWidth` → `MediaMinWidth`
|
|
56
|
+
- `maxWidth` → `MediaMaxWidth`
|
|
57
|
+
- Ни один — возвращает `fallback`.
|
|
58
|
+
|
|
59
|
+
### MediaMinWidth / MediaMaxWidth / MediaBetweenWidth
|
|
60
|
+
|
|
61
|
+
Аналогичные props (`children`, `fallback`, соответствующие `min`/`max`).
|
|
62
|
+
|
|
63
|
+
### useMatchMedia — `(query: string, initial: boolean) => boolean`
|
|
64
|
+
|
|
65
|
+
| Параметр | Описание |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `query` | Полный media-query (например, `"(max-width: 767px)"`). |
|
|
68
|
+
| `initial` | Начальное значение до первого рендера — критично для SSR/первого кадра. |
|
|
69
|
+
|
|
70
|
+
Возвращает `true`, если query совпадает. Подписывается на `change`, возвращает актуальное значение.
|
|
71
|
+
|
|
72
|
+
### EScreenWidth (из `@sberbusiness/triplex-next/helpers/breakpoints`)
|
|
73
|
+
|
|
74
|
+
Breakpoint-значения: `XS_MAX`, `SM_MIN`, `SM_MAX`, `MD_MIN`, `MD_MAX`, `LG_MIN`, `LG_MAX`, `XL_MIN`, и т.д. (строковые — в px). Используются как значения `minWidth`/`maxWidth`.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Ключевые особенности реализации
|
|
79
|
+
|
|
80
|
+
### `children` / `fallback` обязательны — нет "пустого рендера"
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
children: React.ReactElement | null;
|
|
84
|
+
fallback: React.ReactElement | null;
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
- Оба slot'а должны быть заданы (даже если один — `null`). Не `children?: ReactNode`.
|
|
88
|
+
- **Render-props стиль "if/else"**, не "return null if mismatch".
|
|
89
|
+
|
|
90
|
+
### `window.innerWidth` на первом рендере — НЕ SSR-safe
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
useMatchMedia(`(min-width: ${minWidth})`, window.innerWidth >= parseInt(minWidth));
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- `window.innerWidth` в initial-аргументе выполняется **при рендере**, не в `useEffect` — упадёт на SSR.
|
|
97
|
+
- Потребители в SSR должны оборачивать в ClientOnly или подавать `false`/`true` безопасный default через свой wrapper.
|
|
98
|
+
|
|
99
|
+
### `useMatchMedia` — `addEventListener("change")`, не deprecated `addListener`
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
mediaQueryList.addEventListener("change", handleChangeMatches);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- Современный API. Safari 13.1+, Chrome 76+ — ок.
|
|
106
|
+
- **Legacy `addListener` не используется** — если нужна поддержка старых Safari, нужен polyfill.
|
|
107
|
+
|
|
108
|
+
### `useEffect` зависит только от `query`
|
|
109
|
+
|
|
110
|
+
Колбэк `handleChangeMatches` всегда зовёт `setMatches(event.matches)` — `initial` игнорируется после первого рендера.
|
|
111
|
+
|
|
112
|
+
### `MediaBetweenWidth` query — AND двух conditions
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
`(max-width: ${maxWidth}) and (min-width: ${minWidth})`
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Оба условия должны выполняться. `between` — это **пересечение**.
|
|
119
|
+
|
|
120
|
+
### `MediaWidth` — не "матчит всё" по умолчанию
|
|
121
|
+
|
|
122
|
+
Если ни `minWidth`, ни `maxWidth` не переданы — возвращает `fallback`. Это неочевидно: потребители могут ожидать, что пустая media-query рендерит `children`. Потому всегда **передавай хотя бы одну границу**.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Инварианты
|
|
127
|
+
|
|
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`** — документированное поведение, не менять.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Accessibility
|
|
138
|
+
|
|
139
|
+
- JS-условный рендеринг → **содержимое DOM меняется на брейкпоинте**. При переключении фокуса/viewport/скринридера это может вызвать нежелательный повторный анонс.
|
|
140
|
+
- Предпочитай CSS `@media` + `display: none` там, где возможно: DOM стабилен, скринридеры видят весь контент (если это желаемое поведение) или выбираешь, какой показать через `aria-hidden`.
|
|
141
|
+
- Используй `MediaWidth`/`MobileView` только тогда, когда действительно нужно **разное дерево React'а** (разные компоненты, не CSS-вариации).
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Дизайн-токены
|
|
146
|
+
|
|
147
|
+
Нет. Брейкпоинты — `EScreenWidth` (строковые px).
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Связанные компоненты
|
|
152
|
+
|
|
153
|
+
- `MobileView` — частный случай (mobile vs desktop), use-case определён.
|
|
154
|
+
- `IslandWidget` — использует `useMatchMedia` для адаптивного сворачивания.
|
|
155
|
+
- `helpers/breakpoints.EScreenWidth` — источник брейкпоинтов.
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Stories
|
|
160
|
+
|
|
161
|
+
Нет. Компонент утилитарный; покрытие в тестах и через потребителей.
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## История изменений
|
|
166
|
+
|
|
167
|
+
| Дата | Изменение |
|
|
168
|
+
|---|---|
|
|
169
|
+
| 2026-04-18 | Создан документ |
|