@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,317 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Alert
|
|
3
|
+
category: Alerts
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [Notification, Typography, ButtonIcon, Spoiler]
|
|
7
|
+
tokens:
|
|
8
|
+
- --triplex-next-AlertContext-Error_Color
|
|
9
|
+
- --triplex-next-AlertContext-Info_Color
|
|
10
|
+
- --triplex-next-AlertContext-Warning_Color
|
|
11
|
+
- --triplex-next-AlertContext-System_Color
|
|
12
|
+
- --triplex-next-AlertProcess-Error_Background
|
|
13
|
+
- --triplex-next-AlertProcess-Info_Background
|
|
14
|
+
- --triplex-next-AlertProcess-Warning_Background
|
|
15
|
+
- --triplex-next-AlertProcess-System_Background
|
|
16
|
+
- --triplex-next-AlertProcess-Feature_Background
|
|
17
|
+
stories:
|
|
18
|
+
- stories/Alerts/AlertContext.stories.tsx
|
|
19
|
+
- stories/Alerts/AlertProcess.stories.tsx
|
|
20
|
+
version: "1.0"
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Alert
|
|
24
|
+
|
|
25
|
+
## Назначение
|
|
26
|
+
|
|
27
|
+
Компоненты для отображения статусных/предупреждающих сообщений. Папка `Alert` содержит
|
|
28
|
+
две независимые реализации под разные сценарии:
|
|
29
|
+
|
|
30
|
+
- **`AlertContext`** — короткое inline-сообщение в виде строки с иконкой (`<span>`).
|
|
31
|
+
Применяется рядом с полями форм, таблицами, виджетами для уточнения контекста.
|
|
32
|
+
- **`AlertProcess`** — блочное предупреждение с фоном, заголовком, кнопкой закрытия
|
|
33
|
+
и опциональным спойлером для скрытия расширенного контента. Применяется как
|
|
34
|
+
самостоятельный информационный блок на странице.
|
|
35
|
+
|
|
36
|
+
Оба компонента разделяют один набор семантических типов (`EAlertType`).
|
|
37
|
+
|
|
38
|
+
Используй `AlertContext` когда: нужна короткая одна-две строки подсказки без фона
|
|
39
|
+
(пример: сообщение об ошибке валидации рядом с полем).
|
|
40
|
+
Используй `AlertProcess` когда: нужен заметный блок с фоном, многострочный контент,
|
|
41
|
+
возможность закрытия или спойлер (пример: системное уведомление в начале страницы).
|
|
42
|
+
Не используй когда: нужен toast/тост — используй `Notification`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Файловая структура
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
src/components/Alert/
|
|
50
|
+
├── EAlertType.ts # Enum общих типов (INFO, WARNING, ERROR, SYSTEM, FEATURE)
|
|
51
|
+
├── AlertTypeUtils.tsx # ALERT_TYPE_TO_CLASS_NAME_MAP — маппинг type → styles.alertType{Xxx}
|
|
52
|
+
├── index.ts # Barrel: AlertContext, AlertProcess + Spoiler, EAlertType, EAlertProcessBorderRadius
|
|
53
|
+
├── AlertContext/
|
|
54
|
+
│ ├── AlertContext.tsx # <span role="alert"> с иконкой и Text
|
|
55
|
+
│ ├── styles/AlertContext.module.less
|
|
56
|
+
│ └── __tests__/AlertContext.test.tsx
|
|
57
|
+
└── AlertProcess/
|
|
58
|
+
├── AlertProcess.tsx # <div> с фоном, иконкой, закрытием, Object.assign({Spoiler})
|
|
59
|
+
├── AlertProcessContext.ts # Context для коммуникации AlertProcess ↔ AlertProcess.Spoiler
|
|
60
|
+
├── enums.ts # EAlertProcessBorderRadius (MD, LG)
|
|
61
|
+
├── components/AlertProcessSpoiler.tsx # AlertProcess.Spoiler — раскрывающийся блок
|
|
62
|
+
├── styles/AlertProcess.module.less
|
|
63
|
+
└── __tests__/AlertProcess.test.tsx
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Особенности:
|
|
67
|
+
- Два независимых компонента в одной папке — не объединять, у них разная структура,
|
|
68
|
+
семантика и визуал.
|
|
69
|
+
- Общий enum `EAlertType` и утилита `ALERT_TYPE_TO_CLASS_NAME_MAP` намеренно вынесены
|
|
70
|
+
на уровень выше — это единственный переиспользуемый код между `AlertContext` и
|
|
71
|
+
`AlertProcess`.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Варианты и props
|
|
76
|
+
|
|
77
|
+
### Общий enum `EAlertType`
|
|
78
|
+
|
|
79
|
+
| Значение | Цвет иконки (paletteIndex) | Поддерживает AlertContext | Поддерживает AlertProcess |
|
|
80
|
+
|---|---|---|---|
|
|
81
|
+
| `INFO` | `3` (синий) | Да | Да |
|
|
82
|
+
| `WARNING` | `2` (жёлтый) | Да | Да |
|
|
83
|
+
| `ERROR` | `1` (красный) | Да | Да |
|
|
84
|
+
| `SYSTEM` | `4` (фиолетовый) | Да | Да |
|
|
85
|
+
| `FEATURE` | `0` (neutral) | **Нет** — запрещён через `Exclude<EAlertType, EAlertType.FEATURE>` | Да (default icon = `DefaulticonStrokePrdIcon20`) |
|
|
86
|
+
|
|
87
|
+
### `AlertContext` — `IAlertContextProps extends React.HTMLAttributes<HTMLSpanElement>`
|
|
88
|
+
|
|
89
|
+
| Prop | Тип | Обязателен | Описание |
|
|
90
|
+
|---|---|---|---|
|
|
91
|
+
| `type` | `Exclude<EAlertType, EAlertType.FEATURE>` | Да | Семантический тип. FEATURE запрещён на уровне типов. |
|
|
92
|
+
| `renderIcon` | `React.ReactNode` | Нет | Кастомная иконка. Если не передана — рендерится дефолтная 16px иконка, соответствующая `type`. |
|
|
93
|
+
| `children` | `React.ReactNode` | Нет | Текст сообщения — заворачивается в `<Text size={B4} type={...}>`. |
|
|
94
|
+
| `...HTMLSpanAttributes` | — | — | Все стандартные атрибуты `<span>`, включая `className`. |
|
|
95
|
+
|
|
96
|
+
### `AlertProcess` — `IAlertProcessProps extends React.HTMLAttributes<HTMLDivElement>`
|
|
97
|
+
|
|
98
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
99
|
+
|---|---|---|---|
|
|
100
|
+
| `type` | `EAlertType` | — (обязателен) | Любой из пяти типов, включая `FEATURE`. |
|
|
101
|
+
| `closable` | `boolean` | `false` | Если `true` — добавляется `ButtonIcon` с крестиком в правом верхнем углу. |
|
|
102
|
+
| `onClose` | `() => void` | — | Коллбек при нажатии на крестик. AlertProcess сам скрывает себя (`closed` state). |
|
|
103
|
+
| `renderIcon` | `React.ReactNode` | — | Кастомная иконка слева. По умолчанию — дефолтная 20px иконка по `type`. |
|
|
104
|
+
| `borderRadius` | `EAlertProcessBorderRadius` | `MD` (12px) | `MD` = 12px, `LG` = 24px. |
|
|
105
|
+
| `children` | `React.ReactNode` | — | **Без Typography не задаёт стили текста** — потребитель сам заворачивает текст в `Typography`-компоненты. Может содержать `AlertProcess.Spoiler`. |
|
|
106
|
+
| `...HTMLDivAttributes` | — | — | Все стандартные атрибуты `<div>`. |
|
|
107
|
+
|
|
108
|
+
### `AlertProcess.Spoiler` — `IAlertProcessSpoilerProps extends React.HTMLAttributes<HTMLDivElement>`
|
|
109
|
+
|
|
110
|
+
Доступен через `Object.assign` как property компонента: `<AlertProcess.Spoiler>`.
|
|
111
|
+
|
|
112
|
+
| Prop | Тип | Описание |
|
|
113
|
+
|---|---|---|
|
|
114
|
+
| `open` | `boolean` | Контролируемое состояние раскрытия. Неконтролируемого режима нет. |
|
|
115
|
+
| `onOpen` | `(open: boolean) => void` | Коллбек при клике на треугольник. Потребитель обязан обновить `open`. |
|
|
116
|
+
| `children` | `React.ReactNode` | Скрываемый контент. |
|
|
117
|
+
|
|
118
|
+
`EAlertProcessBorderRadius` — enum: `MD = "md"`, `LG = "lg"`.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Ключевые особенности реализации
|
|
123
|
+
|
|
124
|
+
### `ALERT_TYPE_TO_CLASS_NAME_MAP` принимает `styles` аргументом
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
[EAlertType.INFO]: (styles) => styles.alertTypeInfo
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Маппинг — не прямой `type → "alertTypeInfo"`, а **функция `(styles) => string`**. Это
|
|
131
|
+
потому что CSS-модули отдают хэшированные имена, и каждая локация (`AlertContext`,
|
|
132
|
+
`AlertProcess`) импортирует свои стили. Передача `styles` в маппинг позволяет
|
|
133
|
+
переиспользовать его без дублирования кода под разные CSS-модули.
|
|
134
|
+
|
|
135
|
+
При добавлении нового `EAlertType` — добавляй ключ в `ALERT_TYPE_TO_CLASS_NAME_MAP`
|
|
136
|
+
**и** соответствующий класс `.alertType{Xxx}` в оба LESS-файла
|
|
137
|
+
(`AlertContext.module.less`, `AlertProcess.module.less`).
|
|
138
|
+
|
|
139
|
+
### `AlertContext.tsx`: маппинг type → `EFontType` для Text
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
alertTypeToFontTypeMap = {
|
|
143
|
+
INFO: EFontType.INFO,
|
|
144
|
+
WARNING: EFontType.WARNING,
|
|
145
|
+
ERROR: EFontType.ERROR,
|
|
146
|
+
SYSTEM: EFontType.SECONDARY, // ← SYSTEM использует SECONDARY, не SYSTEM
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
`SYSTEM` маппится в `SECONDARY` намеренно — цвет текста для системных сообщений
|
|
151
|
+
совпадает со вторичным текстом. Не менять без дизайнерского согласования.
|
|
152
|
+
|
|
153
|
+
### `AlertProcess`: closed-state держится внутри компонента
|
|
154
|
+
|
|
155
|
+
При клике на крестик AlertProcess устанавливает `closed=true` и возвращает `null`.
|
|
156
|
+
Повторно показать тот же инстанс нельзя — потребитель должен либо перерендерить
|
|
157
|
+
его с новым key, либо управлять видимостью снаружи (не через `closable`, а своим
|
|
158
|
+
if/else). `onClose` здесь — сигнал "пользователь закрыл", а не контролируемое
|
|
159
|
+
состояние.
|
|
160
|
+
|
|
161
|
+
### `AlertProcessContext` и `Spoiler` ↔ `AlertProcess` коммуникация
|
|
162
|
+
|
|
163
|
+
`AlertProcess.Spoiler` в `useEffect` устанавливает `hasSpoiler=true` в контексте
|
|
164
|
+
при монтировании и сбрасывает при размонтировании. `AlertProcess` читает `hasSpoiler`
|
|
165
|
+
и добавляет класс `.withSpoiler` (min-height: 40px), чтобы оставить место под
|
|
166
|
+
кнопку раскрытия.
|
|
167
|
+
|
|
168
|
+
Без `AlertProcess.Spoiler` внутри `AlertProcess` контекст не имеет эффекта —
|
|
169
|
+
дефолтные значения (`hasSpoiler: false`, `setHasSpoiler: noop`) безопасны.
|
|
170
|
+
|
|
171
|
+
### `Object.assign(forwardRef, { Spoiler })` для compound-компонента
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
export const AlertProcess = Object.assign(
|
|
175
|
+
React.forwardRef(...),
|
|
176
|
+
{ Spoiler: AlertProcessSpoiler },
|
|
177
|
+
);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Делает `AlertProcess.Spoiler` доступным как property. Альтернативный паттерн
|
|
181
|
+
(`AlertProcess.Spoiler = AlertProcessSpoiler` без Object.assign) не работает
|
|
182
|
+
с forwardRef в TypeScript — теряется типизация Spoiler. Не упрощать.
|
|
183
|
+
|
|
184
|
+
`displayName` и `Spoiler` устанавливаются **повторно** после Object.assign
|
|
185
|
+
(`AlertProcess.displayName = ...`, `AlertProcess.Spoiler = ...`) — это тоже
|
|
186
|
+
особенность из-за ограничений TS, не убирать.
|
|
187
|
+
|
|
188
|
+
### `AlertProcessSpoiler`: анимация через max-height в LESS
|
|
189
|
+
|
|
190
|
+
Максимальная высота = 1000px (`max-height: 1000px`) — жёсткий лимит. Контент
|
|
191
|
+
выше 1000px будет обрезан. При необходимости — увеличить константу в LESS.
|
|
192
|
+
|
|
193
|
+
### `data-tx={process.env.npm_package_version}`
|
|
194
|
+
|
|
195
|
+
Оба компонента ставят `data-tx` с версией пакета — используется для аналитики
|
|
196
|
+
и дебага "из какой версии библиотеки отрендерилось". Не удалять.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
## Инварианты
|
|
201
|
+
|
|
202
|
+
- **`AlertContext` — `<span role="alert">`**, не `<div>`. Инлайн-семантика важна:
|
|
203
|
+
компонент задуман как inline-блок рядом с полями форм.
|
|
204
|
+
- **`AlertContext` type НЕ принимает `FEATURE`** — тип `Exclude<EAlertType, EAlertType.FEATURE>`.
|
|
205
|
+
Если нужен FEATURE-контекст — создавай отдельный компонент, не расширяй AlertContext.
|
|
206
|
+
- **`AlertProcess` — `<div>`**, не `<section>` или `<aside>`. Семантическую роль
|
|
207
|
+
потребитель может задать через `role` в props.
|
|
208
|
+
- **`forwardRef`** — обязателен на `AlertContext` и `AlertProcess`. Не убирать.
|
|
209
|
+
- **`AlertProcessSpoiler` — обычный `React.FC`** без forwardRef. Исключение из
|
|
210
|
+
общего правила: компонент внутренний к `AlertProcess`, ref на его root не имеет
|
|
211
|
+
публичной ценности. Можно привести к forwardRef в рамках AI refactoring, но это
|
|
212
|
+
breaking — изменит сигнатуру типа `AlertProcess.Spoiler`.
|
|
213
|
+
- **`EAlertType` значения** (`"info"`, `"warning"`, `"error"`, `"system"`, `"feature"`) —
|
|
214
|
+
публичное API, не переименовывать.
|
|
215
|
+
- **`EAlertProcessBorderRadius`** (`"md"`, `"lg"`) — публичное API, не переименовывать.
|
|
216
|
+
- **Toggle-логика `Spoiler`** — полностью controlled (`open` + `onOpen`). Не добавлять
|
|
217
|
+
uncontrolled fallback без согласования API.
|
|
218
|
+
- **`paletteIndex` у иконок** — часть контракта с `@sberbusiness/icons-next`. Не
|
|
219
|
+
менять без согласования с дизайн-токенами цветовых палитр.
|
|
220
|
+
- **`data-tx`** — использовать `process.env.npm_package_version` (Vite подставляет
|
|
221
|
+
во время сборки). Не хардкодить.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Accessibility
|
|
226
|
+
|
|
227
|
+
### AlertContext
|
|
228
|
+
- **`role="alert"`** — объявление "alert" для screen reader. Screen reader прерывает
|
|
229
|
+
чтение и зачитывает новое содержимое при появлении элемента. Не убирать role.
|
|
230
|
+
- **Полностью inline** — текст доступен как текст, иконка декоративна. Если нужно
|
|
231
|
+
явно скрыть иконку от screen reader — потребитель передаёт `renderIcon` с
|
|
232
|
+
`aria-hidden="true"`.
|
|
233
|
+
|
|
234
|
+
### AlertProcess
|
|
235
|
+
- **Нет `role`** по умолчанию — компонент трактуется как обычный блок контента.
|
|
236
|
+
Если сообщение критическое, потребитель обязан передать `role="alert"` или
|
|
237
|
+
`role="status"` через `...rest`.
|
|
238
|
+
- **Кнопка закрытия (`ButtonIcon`)** не имеет встроенного `aria-label` — это
|
|
239
|
+
баг/пробел: потребитель должен знать, что ButtonIcon требует `aria-label` от него.
|
|
240
|
+
В текущей реализации `AlertProcess` НЕ пробрасывает возможность задать
|
|
241
|
+
`aria-label` на кнопку закрытия. При AI refactoring — добавить prop `closeAriaLabel`.
|
|
242
|
+
- **Spoiler toggle** — `ButtonIcon` с иконкой каретки, тоже без `aria-expanded`
|
|
243
|
+
и `aria-label`. Тот же баг a11y, тот же план.
|
|
244
|
+
- **Клавиатура**: `ButtonIcon` — нативный `<button>`, работает Tab/Enter/Space.
|
|
245
|
+
Никаких фокус-ловушек или кастомной навигации компонент не добавляет.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Дизайн-токены
|
|
250
|
+
|
|
251
|
+
**AlertContext** — только цвета текста:
|
|
252
|
+
```
|
|
253
|
+
--triplex-next-AlertContext-{Error|Info|Warning|System}_Color
|
|
254
|
+
```
|
|
255
|
+
У SYSTEM отдельного токена нет — используется цвет SECONDARY-типа из Typography.
|
|
256
|
+
|
|
257
|
+
**AlertProcess** — только фон блока:
|
|
258
|
+
```
|
|
259
|
+
--triplex-next-AlertProcess-{Error|Info|Warning|System|Feature}_Background
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Цвет текста внутри `AlertProcess` задаёт потребитель через `Typography`-компоненты,
|
|
263
|
+
компонент-обёртка не хардкодит.
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Связанные компоненты
|
|
268
|
+
|
|
269
|
+
- `Typography` (`Text`, `Title`) — `AlertContext` использует `Text` внутри;
|
|
270
|
+
`AlertProcess` ожидает Typography-компоненты в `children` от потребителя.
|
|
271
|
+
- `ButtonIcon` (`src/components/Button/ButtonIcon.tsx`) — используется для кнопок
|
|
272
|
+
закрытия и раскрытия спойлера.
|
|
273
|
+
- `@sberbusiness/icons-next` — источник дефолтных иконок
|
|
274
|
+
(`InfoStrokeStsIcon16/20`, `WarningStrokeStsIcon16/20`, `ErrorStrokeStsIcon16/20`,
|
|
275
|
+
`SystemStrokeStsIcon16/20`, `DefaulticonStrokePrdIcon20`, `CrossStrokeSrvIcon16`,
|
|
276
|
+
`CaretdownStrokeSrvIcon16`).
|
|
277
|
+
- `Notification` (`src/components/Notification`) — похожий по назначению, но
|
|
278
|
+
toast-формат (поверх контента, авто-закрытие).
|
|
279
|
+
- `Spoiler` (`src/components/Spoiler`) — отдельный компонент для сворачиваемого
|
|
280
|
+
контента. `AlertProcess.Spoiler` не использует его, реализация своя (проще).
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## Stories
|
|
285
|
+
|
|
286
|
+
`AlertContext`: `stories/Alerts/AlertContext.stories.tsx`
|
|
287
|
+
Файлы примеров: `stories/Alerts/examples/AlertContext/`
|
|
288
|
+
|
|
289
|
+
| Story | Example file | Что демонстрирует |
|
|
290
|
+
|---|---|---|
|
|
291
|
+
| `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `type` и `children` |
|
|
292
|
+
| `Default` | `DefaultExample.tsx` | Базовое использование с INFO |
|
|
293
|
+
| `Types` | `TypesExample.tsx` | Все 4 типа (без FEATURE) |
|
|
294
|
+
| `WithCustomIcon` | `WithCustomIconExample.tsx` | Переопределение иконки через `renderIcon` |
|
|
295
|
+
|
|
296
|
+
`AlertProcess`: `stories/Alerts/AlertProcess.stories.tsx`
|
|
297
|
+
Файлы примеров: `stories/Alerts/examples/AlertProcess/`
|
|
298
|
+
|
|
299
|
+
| Story | Example file | Что демонстрирует |
|
|
300
|
+
|---|---|---|
|
|
301
|
+
| `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `type`, `closable`, `borderRadius`, `children` |
|
|
302
|
+
| `Default` | `DefaultExample.tsx` | Базовое использование |
|
|
303
|
+
| `Types` | `TypesExample.tsx` | Все 5 типов (включая FEATURE) |
|
|
304
|
+
| `BorderRadius` | `BorderRadiusExample.tsx` | MD (12px) vs LG (24px) |
|
|
305
|
+
| `WithCustomIcon` | `WithCustomIconExample.tsx` | Кастомная иконка |
|
|
306
|
+
| `Closable` | `ClosableExample.tsx` | Кнопка закрытия |
|
|
307
|
+
| `WithButtonLink` | `WithButtonLinkExample.tsx` | Кнопка-ссылка в контенте |
|
|
308
|
+
| `WithLink` | `WithLinkExample.tsx` | Обычная ссылка в контенте |
|
|
309
|
+
| `WithSpoiler` | `WithSpoilerExample.tsx` | Использование `AlertProcess.Spoiler` |
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## История изменений
|
|
314
|
+
|
|
315
|
+
| Дата | Изменение |
|
|
316
|
+
|---|---|
|
|
317
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Amount
|
|
3
|
+
category: Display
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [AmountField, Typography]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: stories/Amount/Amount.stories.tsx
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Amount
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Display-компонент для отображения денежной суммы. Форматирует число с разделителями
|
|
17
|
+
групп (неразрывный пробел) и фиксированной дробной частью, опционально добавляет
|
|
18
|
+
сокращение валюты справа и подсказку через `title`. Поддерживает адаптивное
|
|
19
|
+
уменьшение шрифта при длинных значениях.
|
|
20
|
+
|
|
21
|
+
Компонент **только визуализирует**, не принимает ввод — для поля ввода денежной
|
|
22
|
+
суммы используй `AmountField`.
|
|
23
|
+
|
|
24
|
+
Используй когда: нужно вывести сумму в тексте, таблице, детали карточки. Когда
|
|
25
|
+
важна единая визуальная форма отображения чисел по всей библиотеке.
|
|
26
|
+
Не используй когда: сумму нужно вводить (возьми `AmountField`); нужна произвольная
|
|
27
|
+
числовая метка без валюты и форматирования (используй обычный `Text`).
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Файловая структура
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
src/components/Amount/
|
|
35
|
+
├── Amount.tsx # React.FC, НЕ forwardRef
|
|
36
|
+
├── index.ts # Barrel export
|
|
37
|
+
├── styles/Amount.module.less # Только .adaptive класс
|
|
38
|
+
└── __tests__/Amount.test.tsx
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Зависимости:
|
|
42
|
+
- `@sberbusiness/triplex-next/utils/amountUtils` → `formatAmount` (использует `big.js`).
|
|
43
|
+
- `@sberbusiness/triplex-next/consts/AmountConst` → константы разделителей
|
|
44
|
+
(`DecimalComma`, `DecimalPoint`, `GroupSeparator`).
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Варианты и props
|
|
49
|
+
|
|
50
|
+
### `IAmountProps extends React.HTMLAttributes<HTMLSpanElement>`
|
|
51
|
+
|
|
52
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| `value` | `string` | — (обязателен) | Числовое значение как строка. Может содержать `.` или `,`, пробелы, знак `+`/`-`. Внутри форматируется через `big.js` → устойчиво к floating-point. |
|
|
55
|
+
| `fractionLength` | `0 \| 1 \| 2 \| 3 \| 4` | `2` (из `AmountConst.FractionLength`) | Количество знаков после запятой. Тип **литерал-union** — нельзя передать произвольный `number`. Для `0` потребитель обязан передать **именно `0`**, не `null`/`undefined` (undefined даст дефолт 2). |
|
|
56
|
+
| `currency` | `string` | — | Если указан — справа от суммы добавляется `\u00A0{currency}` (неразрывный пробел + строка). Не задано → валюта не отображается. |
|
|
57
|
+
| `currencyTitle` | `string` | — | Подсказка (title-атрибут) для валюты — обычно полное название ("Российские рубли" для "RUB"). Применяется к `<span>`, обёрнутому вокруг currency. |
|
|
58
|
+
| `adaptive` | `boolean` | `false` | Если `true` и длина форматированной строки ≥ 14 — добавляется класс `.adaptive` (font-size: 10px, line-height: 12px через `!important`). |
|
|
59
|
+
| `dataTestId` | `string` | — | **Кастомный prop**, не пробрасывается на root `<span>`. Используется только для `data-test-id` на внутренние `<span>` (суффиксы `__amount`, `__currencyName`). |
|
|
60
|
+
| `className` | `string` | — | Объединяется с `.adaptive` через `clsx`. |
|
|
61
|
+
| `...HTMLSpanAttributes` | — | — | Всё остальное спредится на root `<span>`. |
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Ключевые особенности реализации
|
|
66
|
+
|
|
67
|
+
### Компонент — `React.FC`, НЕ `forwardRef`
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
export const Amount: React.FC<IAmountProps> = ({ ... }) => { ... }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Это **исключение из правила библиотеки про обязательный forwardRef**. Причина
|
|
74
|
+
исторически неизвестна; при AI refactoring компонент должен быть переведён на
|
|
75
|
+
`React.forwardRef<HTMLSpanElement, IAmountProps>`. Это non-breaking изменение.
|
|
76
|
+
До рефакторинга — не добавлять ref-логику, она не пройдёт TypeScript.
|
|
77
|
+
|
|
78
|
+
### `dataTestId` — НЕ `data-testid`
|
|
79
|
+
|
|
80
|
+
Имя prop — camelCase `dataTestId`. Пропускается через проп-деструктуризацию и
|
|
81
|
+
применяется только к внутренним спанам:
|
|
82
|
+
- `{dataTestId}__amount` — на спан с самим числом.
|
|
83
|
+
- `{dataTestId}__currencyName` — на спан с валютой.
|
|
84
|
+
|
|
85
|
+
На root `<span>` `dataTestId` не попадает автоматически — потребитель, если нужно,
|
|
86
|
+
передаёт `data-test-id` через `...restProps`. Это намеренная двухуровневая
|
|
87
|
+
структура для тестов.
|
|
88
|
+
|
|
89
|
+
### Замена дефис-минуса на настоящий знак минус
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
if (formattedAmount[0] == "-") {
|
|
93
|
+
formattedAmount = formattedAmount.replace("\u002D", "\u2212");
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`\u002D` — ASCII hyphen-minus, `\u2212` — Unicode MINUS SIGN. Screen reader
|
|
98
|
+
корректно произносит `\u2212` как "минус", а `\u002D` обычно читается как "дефис"
|
|
99
|
+
или пропускается. **Не убирать** — это осознанная a11y-особенность.
|
|
100
|
+
|
|
101
|
+
Замена применяется ТОЛЬКО в первой позиции — если минус в середине (например,
|
|
102
|
+
разделитель диапазона "100–200"), он не будет заменён.
|
|
103
|
+
|
|
104
|
+
### Неразрывный пробел перед валютой
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
renderCurrencyName = () => [
|
|
108
|
+
"\u00A0", // NBSP
|
|
109
|
+
<span ...>{currency}</span>,
|
|
110
|
+
]
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Между числом и валютой вставляется NBSP (`\u00A0`), не обычный пробел. Это
|
|
114
|
+
предотвращает перенос валюты на следующую строку при переполнении.
|
|
115
|
+
|
|
116
|
+
### Адаптивный шрифт через `!important`
|
|
117
|
+
|
|
118
|
+
`.adaptive { font-size: 10px !important; line-height: 12px !important; }` —
|
|
119
|
+
`!important` нужен, чтобы перебить родительский Typography-стиль. Если потребитель
|
|
120
|
+
хочет переопределить размер — `className` с более специфичным селектором тоже
|
|
121
|
+
должен использовать `!important`. Это компромисс ради надёжного поведения
|
|
122
|
+
в контексте таблиц/карточек.
|
|
123
|
+
|
|
124
|
+
Порог `adaptiveAmountLength = 14` — длина именно **форматированной** строки (после
|
|
125
|
+
вставки разделителей групп). Не равна количеству значащих цифр.
|
|
126
|
+
|
|
127
|
+
### `formatAmount` — большая часть логики вне компонента
|
|
128
|
+
|
|
129
|
+
`Amount.tsx` — тонкая обёртка. Вся сложность форматирования в `utils/amountUtils.ts`:
|
|
130
|
+
- Использует `big.js` для чисел (устойчиво к floating-point).
|
|
131
|
+
- `Big.RM = 0` — режим без округления (truncate).
|
|
132
|
+
- Принимает запятую и точку как десятичный разделитель.
|
|
133
|
+
- Поддерживает знак "+" (сохраняется в выводе).
|
|
134
|
+
- Поддерживает `separateGroups` и `fillFraction` — но **Amount не прокидывает эти
|
|
135
|
+
флаги**. Для customизации форматирования нужно расширить Amount или использовать
|
|
136
|
+
`formatAmount` напрямую.
|
|
137
|
+
|
|
138
|
+
### `data-tx={process.env.npm_package_version}`
|
|
139
|
+
|
|
140
|
+
На root `<span>` выставляется `data-tx` с версией пакета (Vite подставляет при
|
|
141
|
+
сборке). Не удалять.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## Инварианты
|
|
146
|
+
|
|
147
|
+
- **`IAmountProps extends React.HTMLAttributes<HTMLSpanElement>`** — не менять на
|
|
148
|
+
`HTMLDivElement`. Компонент inline по дизайну.
|
|
149
|
+
- **`value` только `string`** — не `number`, не `Big`. Компонент не принимает
|
|
150
|
+
`number` напрямую (в отличие от `formatAmount`, который принимает `string | Big`).
|
|
151
|
+
Потребитель должен сам привести число к строке.
|
|
152
|
+
- **`fractionLength` литеральный union `0 \| 1 \| 2 \| 3 \| 4`** — не расширять
|
|
153
|
+
до `number`, это ограничение защищает от визуально уродливых значений (20 знаков).
|
|
154
|
+
- **Замена `\u002D` → `\u2212` в минусе** — не удалять. A11y.
|
|
155
|
+
- **NBSP (`\u00A0`) перед валютой** — не заменять на обычный пробел.
|
|
156
|
+
- **`dataTestId` как camelCase prop** — не переименовывать в `data-testid` без
|
|
157
|
+
breaking-change согласования.
|
|
158
|
+
- **`.adaptive` с `!important`** — не убирать `!important` без параллельной
|
|
159
|
+
правки потребителей (которые полагаются на его работу в таблицах).
|
|
160
|
+
- **`adaptiveAmountLength = 14`** — константа внутри файла, не выносить в props
|
|
161
|
+
без дизайнерского согласования.
|
|
162
|
+
- **`formatAmount` вызов не мемоизируется** — если это станет bottleneck (большие
|
|
163
|
+
таблицы), оборачивай Amount в `React.memo` снаружи. Не добавлять `useMemo`
|
|
164
|
+
внутрь без профиля.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Accessibility
|
|
169
|
+
|
|
170
|
+
- **Замена дефиса на настоящий минус (`\u2212`)** — screen reader корректно
|
|
171
|
+
озвучивает знак "минус". Это ключевая a11y-особенность компонента.
|
|
172
|
+
- **`currency` как отдельный `<span>`** внутри — позволяет потребителю, при
|
|
173
|
+
необходимости, добавить `aria-label` через children override.
|
|
174
|
+
- **`title={currencyTitle}`** — при наведении курсора показывает полное название
|
|
175
|
+
валюты (например, "Российские рубли" для "RUB"). Screen reader читает title
|
|
176
|
+
как дополнительное описание.
|
|
177
|
+
- **Нет `aria-label` по умолчанию** — если нужно озвучить значение целиком с валютой
|
|
178
|
+
("восемь миллионов девятьсот шестьдесят семь тысяч четыреста пятьдесят два рубля
|
|
179
|
+
тридцать одна копейка"), потребитель должен сформировать его сам и передать
|
|
180
|
+
через `aria-label` в `...restProps`. Автоматического склонения названия валюты
|
|
181
|
+
компонент не делает.
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## Дизайн-токены
|
|
186
|
+
|
|
187
|
+
Нет — компонент не хардкодит цветов и использует наследуемый от родителя шрифт.
|
|
188
|
+
Единственное исключение — класс `.adaptive` с фиксированными `10px/12px`
|
|
189
|
+
(не через токены). Это кандидат на рефакторинг с введением токенов.
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Связанные компоненты
|
|
194
|
+
|
|
195
|
+
- `AmountField` (`src/components/AmountField`) — input-аналог для ввода суммы.
|
|
196
|
+
Использует тот же `formatAmount` и ту же знак-замену.
|
|
197
|
+
- `Typography` — Amount наследует шрифт от родителя; обычно оборачивается в
|
|
198
|
+
`Text` / `Title` нужного размера.
|
|
199
|
+
- `formatAmount` / `amountComparator` (`src/utils/amountUtils.ts`) — утилиты,
|
|
200
|
+
которые Amount использует внутри, но также могут быть использованы напрямую
|
|
201
|
+
потребителем для консистентного форматирования в местах, где Amount-компонент
|
|
202
|
+
не подходит.
|
|
203
|
+
- `AmountConst` (`src/consts/AmountConst`) — источник констант:
|
|
204
|
+
`FractionLength=2`, `DecimalComma=","`, `DecimalPoint="."`, `GroupSeparator="\u00A0"`.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Stories
|
|
209
|
+
|
|
210
|
+
`stories/Amount/Amount.stories.tsx`
|
|
211
|
+
Файлы примеров: `stories/Amount/examples/`
|
|
212
|
+
|
|
213
|
+
| Story | Example file | Что демонстрирует |
|
|
214
|
+
|---|---|---|
|
|
215
|
+
| `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль всех props |
|
|
216
|
+
| `Default` | `DefaultExample.tsx` | Базовое использование с RUB |
|
|
217
|
+
| `Example` | `ShowcaseExample.tsx` | Расширенный пример (разные значения, знаки) |
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## История изменений
|
|
222
|
+
|
|
223
|
+
| Дата | Изменение |
|
|
224
|
+
|---|---|
|
|
225
|
+
| 2026-04-18 | Создан документ |
|