@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,277 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Badge
|
|
3
|
+
category: Badges
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [Avatar, Chip, Tag, MarkerStatus]
|
|
7
|
+
tokens:
|
|
8
|
+
- --triplex-next-Badge-Background
|
|
9
|
+
stories: stories/Badge/Badge.stories.tsx
|
|
10
|
+
version: "1.0"
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Badge
|
|
14
|
+
|
|
15
|
+
## Назначение
|
|
16
|
+
|
|
17
|
+
Индикатор статуса или уведомления в виде горизонтальной "таблетки" с опциональным
|
|
18
|
+
префиксом, контентом и постфиксом. Имеет три размера (SM / MD / LG), которые
|
|
19
|
+
соответствуют общей шкале компонентов библиотеки (`EComponentSize`).
|
|
20
|
+
|
|
21
|
+
Сопутствующий `Badge.Dot` — точечный вариант (круг) для минималистичных
|
|
22
|
+
индикаторов (например, "есть непрочитанное"). Badge и BadgeDot — два независимых
|
|
23
|
+
компонента под одним barrel-экспортом.
|
|
24
|
+
|
|
25
|
+
Используй `Badge` когда: нужна краткая метка статуса/счётчика с текстом или
|
|
26
|
+
иконкой ("NEW", "12", "Beta").
|
|
27
|
+
Используй `Badge.Dot` когда: нужен просто цветной кружок без текста.
|
|
28
|
+
Не используй когда: нужен удаляемый тег с текстом (используй `Chip` или `Tag`);
|
|
29
|
+
нужен большой статус-блок с описанием (используй `MarkerStatus`).
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Файловая структура
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
src/components/Badge/
|
|
37
|
+
├── Badge.tsx # React.forwardRef, compound: Badge + Badge.Dot
|
|
38
|
+
├── BadgeDot.tsx # React.forwardRef, отдельный компонент (не subcomponent)
|
|
39
|
+
├── types.ts # IBadgeProps, IBadgeDotProps, IBadgeContentProps
|
|
40
|
+
├── index.ts # Barrel: types + Badge (+ Badge.Dot через compound)
|
|
41
|
+
├── styles/
|
|
42
|
+
│ ├── Badge.module.less # Root .badge (SM/MD/LG: height + border-radius)
|
|
43
|
+
│ └── BadgeDot.module.less # Root .badgeDot (SM/MD/LG: width+height, border-radius 50%)
|
|
44
|
+
├── components/ # Внутренние subcomponents (не экспортируются)
|
|
45
|
+
│ ├── BadgeContent.tsx # React.FC с паддингами по size
|
|
46
|
+
│ ├── BadgePrefix.tsx # React.FC, display: contents (не создаёт DOM-слоя)
|
|
47
|
+
│ ├── BadgePostfix.tsx # React.FC, display: contents
|
|
48
|
+
│ └── styles/
|
|
49
|
+
│ ├── BadgeContent.module.less # Паддинги SM=4px / MD=6px / LG=8px + noPaddingLeft/Right
|
|
50
|
+
│ ├── BadgePrefix.module.less # display: contents
|
|
51
|
+
│ └── BadgePostfix.module.less # display: contents
|
|
52
|
+
└── tests/Badge.test.tsx
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Особенности:
|
|
56
|
+
- **`Badge` + `Badge.Dot` через `Object.assign`** — compound-паттерн, как у
|
|
57
|
+
`AlertProcess`. BadgeDot также экспортирован из `index.ts` (через `./Badge`),
|
|
58
|
+
но рекомендуемый путь — через `Badge.Dot`.
|
|
59
|
+
- **`prefix`/`postfix` через `display: contents`** — обёртки не добавляют визуального
|
|
60
|
+
слоя, являются только семантическими якорями для DOM-тестов.
|
|
61
|
+
- **`components/` папка** — прямо не экспортируется, subcomponents видны только Badge.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Варианты и props
|
|
66
|
+
|
|
67
|
+
### `IBadgeProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "prefix" | "postfix">`
|
|
68
|
+
|
|
69
|
+
**Важно:** `prefix` и `postfix` НЕ стандартные HTML-атрибуты — они переопределены
|
|
70
|
+
через `Omit` и изменяют семантику.
|
|
71
|
+
|
|
72
|
+
| Prop | Тип | Обязателен | Описание |
|
|
73
|
+
|---|---|---|---|
|
|
74
|
+
| `size` | `EComponentSize` (`SM`, `MD`, `LG`) | Да | Определяет высоту (16/20/24px), border-radius и внутренние паддинги. |
|
|
75
|
+
| `children` | `React.ReactNode` | Нет | Основной контент (текст/иконка/число). Если не передан — рендерится только prefix+postfix. |
|
|
76
|
+
| `prefix` | `React.ReactNode` | Нет | Обычно иконка слева. При наличии — у BadgeContent убирается `padding-left`. |
|
|
77
|
+
| `postfix` | `React.ReactNode` | Нет | Обычно иконка или мини-кнопка справа. При наличии — у BadgeContent убирается `padding-right`. |
|
|
78
|
+
| `className` | `string` | Нет | Объединяется с `styles.badge + sizeClass`. |
|
|
79
|
+
| `...HTMLSpanAttributes` | — | — | Всё остальное, кроме `prefix`/`postfix`. |
|
|
80
|
+
|
|
81
|
+
### `IBadgeDotProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children">`
|
|
82
|
+
|
|
83
|
+
| Prop | Тип | Обязателен | Описание |
|
|
84
|
+
|---|---|---|---|
|
|
85
|
+
| `size` | `EComponentSize` | Да | Диаметр точки: SM=6px, MD=8px, LG=10px. |
|
|
86
|
+
| `children` | `never` | — | Явно запрещено через `never` — точка без контента. |
|
|
87
|
+
| `className` | `string` | Нет | Объединяется с `styles.badgeDot + sizeClass`. |
|
|
88
|
+
| `...HTMLSpanAttributes` | — | — | Стандартные атрибуты `<span>`. |
|
|
89
|
+
|
|
90
|
+
### Размеры
|
|
91
|
+
|
|
92
|
+
**Badge (горизонтальная плашка):**
|
|
93
|
+
|
|
94
|
+
| size | Height | Border-radius | Content padding-x |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| `SM` | 16px | 4px | 4px |
|
|
97
|
+
| `MD` | 20px | 6px | 6px |
|
|
98
|
+
| `LG` | 24px | 8px | 8px |
|
|
99
|
+
|
|
100
|
+
**Badge.Dot (круг):**
|
|
101
|
+
|
|
102
|
+
| size | Diameter |
|
|
103
|
+
|---|---|
|
|
104
|
+
| `SM` | 6px |
|
|
105
|
+
| `MD` | 8px |
|
|
106
|
+
| `LG` | 10px |
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Ключевые особенности реализации
|
|
111
|
+
|
|
112
|
+
### `createSizeToClassNameMap` вместо локального маппинга
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
const SIZE_TO_CLASS_NAME_MAP = createSizeToClassNameMap(styles);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Утилита `src/utils/classNameMaps.ts` возвращает `{ [SM]: styles.sm, [MD]: styles.md, [LG]: styles.lg }`.
|
|
119
|
+
Используется во всех Badge-файлах (`Badge.tsx`, `BadgeDot.tsx`, `BadgeContent.tsx`).
|
|
120
|
+
Это единый паттерн — не дублировать маппинг локально.
|
|
121
|
+
|
|
122
|
+
Если понадобится новый размер (XS, XL) — обновлять **и** `EComponentSize`, **и**
|
|
123
|
+
`createSizeToClassNameMap`, **и** LESS-файлы. Помни: `createSizeToClassNameMap`
|
|
124
|
+
типизирован как `Record<EComponentSize, string>` — TypeScript заставит добавить
|
|
125
|
+
ключ.
|
|
126
|
+
|
|
127
|
+
### `Omit<HTMLAttributes, "prefix" | "postfix">` — реальная проблема
|
|
128
|
+
|
|
129
|
+
HTML-атрибут `prefix` (устаревший, для RDFa) существует на некоторых тегах.
|
|
130
|
+
TypeScript не распознаёт его на `<span>`, но React.HTMLAttributes включает его
|
|
131
|
+
через dom-типы. Без `Omit` prop `prefix` компонента конфликтует с HTML-атрибутом
|
|
132
|
+
в типах. Не удалять Omit.
|
|
133
|
+
|
|
134
|
+
### `BadgePrefix` / `BadgePostfix` — `display: contents`
|
|
135
|
+
|
|
136
|
+
```less
|
|
137
|
+
.badgePrefix { display: contents; }
|
|
138
|
+
.badgePostfix { display: contents; }
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Обёртка не создаёт box — её children рендерятся так, как будто `<span>`
|
|
142
|
+
вообще нет, но в DOM он есть. Это позволяет:
|
|
143
|
+
- Применять семантический класс для тестов.
|
|
144
|
+
- Не нарушать flex-лейаут родителя.
|
|
145
|
+
- Не добавлять лишних паддингов.
|
|
146
|
+
|
|
147
|
+
**`display: contents` имеет a11y-баг в Safari <14** — он убирает роль элемента
|
|
148
|
+
для screen reader. Для `<span>` без семантической роли это не проблема, но помни
|
|
149
|
+
при расширении (не добавлять `role="button"` на BadgePrefix без тестирования).
|
|
150
|
+
|
|
151
|
+
### `BadgeContent` убирает паддинги при наличии prefix/postfix
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
<BadgeContent
|
|
155
|
+
size={size}
|
|
156
|
+
noPaddingLeft={Boolean(prefix)}
|
|
157
|
+
noPaddingRight={Boolean(postfix)}
|
|
158
|
+
>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Это делает `prefix/postfix` "приклеенными" к контенту без двойного отступа. Если
|
|
162
|
+
пишешь новый subcomponent внутри Badge — следуй этому паттерну (не добавляй
|
|
163
|
+
горизонтальные паддинги на subcomponent-уровне, только на BadgeContent).
|
|
164
|
+
|
|
165
|
+
### Compound `Badge.Dot`
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
export const Badge = Object.assign(
|
|
169
|
+
React.forwardRef<HTMLSpanElement, IBadgeProps>(...),
|
|
170
|
+
{ Dot: BadgeDot },
|
|
171
|
+
);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Тот же паттерн, что у `AlertProcess.Spoiler`. Одновременно `BadgeDot` экспортируется
|
|
175
|
+
из `index.ts` через `./Badge` напрямую, но **рекомендуемое использование** —
|
|
176
|
+
через `Badge.Dot` (единый API).
|
|
177
|
+
|
|
178
|
+
### Один цветовой токен на оба
|
|
179
|
+
|
|
180
|
+
`--triplex-next-Badge-Background` используется и для Badge, и для BadgeDot. Нет
|
|
181
|
+
отдельного токена для `BadgeDot-Background` — оба разделяют цвет. Если нужны
|
|
182
|
+
разные цвета (например, зелёная точка при сером Badge) — потребитель
|
|
183
|
+
переопределяет через `style`/`className`.
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Инварианты
|
|
188
|
+
|
|
189
|
+
- **`forwardRef`** — обязателен на Badge и BadgeDot. Не убирать.
|
|
190
|
+
- **`size` обязателен** — без default value, чтобы потребитель явно выбирал масштаб.
|
|
191
|
+
- **`EComponentSize`** — общий enum из `src/enums/EComponentSize`, не делай
|
|
192
|
+
локальный аналог. Badge входит в семейство компонентов, использующих единый
|
|
193
|
+
SM/MD/LG.
|
|
194
|
+
- **`BadgeDot.children: never`** — не превращать в обычный slot. Компонент
|
|
195
|
+
намеренно пустой.
|
|
196
|
+
- **`Omit<HTMLAttributes, "prefix" | "postfix">`** — не убирать, конфликт типов.
|
|
197
|
+
- **`display: contents` в BadgePrefix/BadgePostfix** — не менять на `inline-flex`.
|
|
198
|
+
Меняет лейаут и ломает `noPaddingLeft/Right` логику в BadgeContent.
|
|
199
|
+
- **`Badge.Dot` через Object.assign** — не убирать, потребители импортируют
|
|
200
|
+
через compound.
|
|
201
|
+
- **Background-токен един** для Badge и BadgeDot — не разделять без согласования
|
|
202
|
+
с дизайнером.
|
|
203
|
+
- **`white-space: nowrap`** на Badge — не убирать, иначе длинный контент ломается
|
|
204
|
+
на несколько строк и разваливает высоту.
|
|
205
|
+
- **BadgeContent/Prefix/Postfix — внутренние** — не экспортировать через barrel.
|
|
206
|
+
Потребители используют только `prefix`/`postfix` props.
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Accessibility
|
|
211
|
+
|
|
212
|
+
- **Никаких ARIA-ролей по умолчанию** — Badge семантически нейтрален. Если
|
|
213
|
+
Badge отображает число непрочитанных сообщений — потребитель обязан обеспечить
|
|
214
|
+
озвучку: `aria-label="5 непрочитанных сообщений"` или `role="status"`.
|
|
215
|
+
- **Для статусного Badge** (например, "Online") — потребитель должен добавить
|
|
216
|
+
`role="status"` и `aria-label` / `title`, иначе screen reader прочитает только
|
|
217
|
+
визуальный текст, без контекста.
|
|
218
|
+
- **BadgeDot** — чистая визуальная точка без текста. **Обязан** получать
|
|
219
|
+
`aria-label` от потребителя, иначе не воспринимается screen reader'ом. Или,
|
|
220
|
+
если это чисто декоративный индикатор рядом с другим текстом — `aria-hidden="true"`.
|
|
221
|
+
- **`display: contents`** на prefix/postfix — в современных браузерах не ломает
|
|
222
|
+
a11y, но в Safari <14 может. Если поддержка старого Safari критична, делай
|
|
223
|
+
тесты.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Дизайн-токены
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
--triplex-next-Badge-Background # Фон Badge и BadgeDot (единый токен)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Цвет текста внутри Badge определяется `color: inherit` от родителя (нет явного
|
|
234
|
+
токена) — потребитель задаёт цвет через `Typography`-компоненты или `style`.
|
|
235
|
+
|
|
236
|
+
Высоты, радиусы, паддинги, размеры точки — жёсткие значения в LESS, не токенизированы.
|
|
237
|
+
Кандидат на рефакторинг при общей токенизации размеров.
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Связанные компоненты
|
|
242
|
+
|
|
243
|
+
- `Avatar` (`src/components/Avatar`) — часто комбинируется с Badge: Badge на углу
|
|
244
|
+
Avatar как индикатор статуса. Позиционирование — задача потребителя.
|
|
245
|
+
- `Chip` (`src/components/Chip`) — "большой Badge" с возможностью закрытия и
|
|
246
|
+
интерактивностью. Разная семантика: Badge = индикатор, Chip = тег.
|
|
247
|
+
- `Tag` / `TagColor` / `TagGroup` (`src/components/Tag`) — ещё больший уровень:
|
|
248
|
+
стилизованные метки категорий с цветами.
|
|
249
|
+
- `MarkerStatus` (`src/components/MarkerStatus`) — крупный блок статуса с иконкой
|
|
250
|
+
и текстом (тип сообщения).
|
|
251
|
+
- `EComponentSize` (`src/enums/EComponentSize`) — общий enum трёх размеров.
|
|
252
|
+
- `createSizeToClassNameMap` (`src/utils/classNameMaps.ts`) — утилита
|
|
253
|
+
размер → class.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Stories
|
|
258
|
+
|
|
259
|
+
`stories/Badge/Badge.stories.tsx`
|
|
260
|
+
Файлы примеров: `stories/Badge/examples/`
|
|
261
|
+
|
|
262
|
+
| Story | Example file | Что демонстрирует |
|
|
263
|
+
|---|---|---|
|
|
264
|
+
| `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль `size` |
|
|
265
|
+
| `Default` | `DefaultExample.tsx` | Базовое использование |
|
|
266
|
+
| `Sizes` | `SizesExample.tsx` | Все три размера Badge |
|
|
267
|
+
| `WithPrefixAndPostfix` | `WithPrefixAndPostfixExample.tsx` | Badge с иконкой слева и/или справа |
|
|
268
|
+
| `DotSizes` | `DotSizesExample.tsx` | Три размера Badge.Dot |
|
|
269
|
+
| `Example` | `ProductionExample.tsx` | Реальные кейсы композиции |
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## История изменений
|
|
274
|
+
|
|
275
|
+
| Дата | Изменение |
|
|
276
|
+
|---|---|
|
|
277
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Body
|
|
3
|
+
category: Layout
|
|
4
|
+
figma-node: ""
|
|
5
|
+
figma-file: ""
|
|
6
|
+
related: [Page, Header, Footer]
|
|
7
|
+
tokens: []
|
|
8
|
+
stories: ""
|
|
9
|
+
version: "1.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Body
|
|
13
|
+
|
|
14
|
+
## Назначение
|
|
15
|
+
|
|
16
|
+
Минимальный layout-контейнер для содержимого страницы. Создаёт двухуровневую
|
|
17
|
+
структуру `<div>` (root + inner) с `display: flex` и `flex-grow: 1` на inner,
|
|
18
|
+
что позволяет контенту растягиваться на всю доступную высоту.
|
|
19
|
+
|
|
20
|
+
В текущей архитектуре `Body` — примитив, используемый внутри `BodyPage`
|
|
21
|
+
(экспортируется как `Page.Body` в stories). Как самостоятельный публичный
|
|
22
|
+
компонент применяется редко — чаще через `Page.Body` с дополнительными
|
|
23
|
+
props (`type`, `verticalMargin`).
|
|
24
|
+
|
|
25
|
+
Используй когда: собираешь кастомный layout страницы и хочешь переиспользовать
|
|
26
|
+
flex-обёртку без привязки к Page.
|
|
27
|
+
Не используй когда: строишь страницу по стандартному паттерну — бери `Page.Body`,
|
|
28
|
+
там уже есть Island, verticalMargin и поддержка типов.
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Файловая структура
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
src/components/Body/
|
|
36
|
+
├── Body.tsx # React.forwardRef, thin wrapper
|
|
37
|
+
├── index.ts # Barrel
|
|
38
|
+
├── styles/Body.module.less # .body (flex) + .bodyInner (flex-grow: 1)
|
|
39
|
+
└── __tests__/Body.test.tsx
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Особенности:
|
|
43
|
+
- Нет LESS-токенов — компонент чисто структурный.
|
|
44
|
+
- **Нет собственных stories** — документируется косвенно через `Page.Body`
|
|
45
|
+
(stories/Page/BodyPage.stories.tsx).
|
|
46
|
+
- **Импорт через публичный путь, а не через `../Body`**: в `BodyPage.tsx` путь
|
|
47
|
+
`@sberbusiness/triplex-next/components/Body/Body` — это сохранено намеренно,
|
|
48
|
+
paths-alias для работы в монорепозитории потребителей.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Варианты и props
|
|
53
|
+
|
|
54
|
+
### `IBodyProps extends React.HTMLAttributes<HTMLDivElement>`
|
|
55
|
+
|
|
56
|
+
Интерфейс пустой — используется наследование от HTMLAttributes как есть.
|
|
57
|
+
|
|
58
|
+
| Prop | Тип | Описание |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| `children` | `React.ReactNode` | Контент, рендерится внутри inner-div. |
|
|
61
|
+
| `className` | `string` | Объединяется с `.body` через `clsx`. |
|
|
62
|
+
| `...HTMLDivAttributes` | — | Всё стандартное для `<div>`. |
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Ключевые особенности реализации
|
|
67
|
+
|
|
68
|
+
### Двухуровневая обёртка
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<div className={clsx(styles.body, className)} {...rest} data-tx={...} ref={ref}>
|
|
72
|
+
<div className={styles.bodyInner}>{children}</div>
|
|
73
|
+
</div>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Root — `display: flex; position: relative`. Inner — `flex-grow: 1; width: 100%;
|
|
77
|
+
position: relative`. Двойной уровень нужен, чтобы:
|
|
78
|
+
- Root мог получать `className` и event handler'ы от потребителя без поломки
|
|
79
|
+
flex-layout.
|
|
80
|
+
- Inner гарантированно занимал всю ширину/высоту, что критично для корректного
|
|
81
|
+
позиционирования абсолютных потомков (position: relative на обоих уровнях).
|
|
82
|
+
|
|
83
|
+
### ref идёт на root
|
|
84
|
+
|
|
85
|
+
`forwardRef` прокидывает ref на **внешний div**, не на inner. Это сохраняет
|
|
86
|
+
стабильный контракт (ref → тот же DOM-элемент, что получает className и spread
|
|
87
|
+
props).
|
|
88
|
+
|
|
89
|
+
### `data-tx` только на root
|
|
90
|
+
|
|
91
|
+
Версия пакета ставится только на внешний div — второй раз на inner не нужен.
|
|
92
|
+
|
|
93
|
+
### Пустой интерфейс `IBodyProps`
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
export interface IBodyProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
ESLint может предлагать заменить на type-alias `type IBodyProps = React.HTMLAttributes<HTMLDivElement>`,
|
|
100
|
+
но `interface` сохранён для возможности расширения в будущем (например, если
|
|
101
|
+
потребуется добавить `verticalMargin` на уровень Body, а не BodyPage). Не
|
|
102
|
+
переписывать на type.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Инварианты
|
|
107
|
+
|
|
108
|
+
- **`forwardRef`** — обязателен. Ref идёт на root div.
|
|
109
|
+
- **`data-tx={process.env.npm_package_version}`** — не удалять (версия для
|
|
110
|
+
отладки).
|
|
111
|
+
- **Двухуровневая структура (`.body` → `.bodyInner`)** — не схлопывать в один
|
|
112
|
+
div. От этого зависит lafyut-контракт потребителей, особенно `BodyPage`
|
|
113
|
+
(он оборачивает Body в Island для типа FIRST).
|
|
114
|
+
- **`position: relative` на обоих уровнях** — не убирать. Потребители могут
|
|
115
|
+
полагаться на то, что абсолютно спозиционированные элементы привязаны к
|
|
116
|
+
этим контейнерам.
|
|
117
|
+
- **`flex-grow: 1` на inner** — не убирать. Обеспечивает поведение "body
|
|
118
|
+
занимает всё доступное место по высоте".
|
|
119
|
+
- **`IBodyProps` как interface (не type)** — сохранить для будущего расширения.
|
|
120
|
+
- **Нет своих дизайн-токенов** — не добавлять без согласования (компонент
|
|
121
|
+
намеренно стилистически нейтрален, цвет/шрифт/отступы задаёт потребитель
|
|
122
|
+
или родитель).
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Accessibility
|
|
127
|
+
|
|
128
|
+
- **Нет собственной ARIA-роли** — `<div>` семантически нейтрален. Если нужна
|
|
129
|
+
semantic main-область — потребитель передаёт `role="main"` через `...rest`
|
|
130
|
+
или использует `<main>` как обёртку снаружи.
|
|
131
|
+
- **Не перехватывает фокус, не манипулирует tabindex** — полностью прозрачен
|
|
132
|
+
для навигации.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Дизайн-токены
|
|
137
|
+
|
|
138
|
+
Нет — компонент структурный, без визуального оформления.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Связанные компоненты
|
|
143
|
+
|
|
144
|
+
- `Page` (`src/components/Page`) — страничный layout. Содержит Header / Body /
|
|
145
|
+
Footer как compound-пропсы.
|
|
146
|
+
- `BodyPage` / `Page.Body` (`src/components/Page/components/BodyPage.tsx`) —
|
|
147
|
+
расширенный Body с поддержкой `type` (FIRST/SECOND), `verticalMargin`,
|
|
148
|
+
опциональной обёрткой в Island. В большинстве сценариев потребитель использует
|
|
149
|
+
Page.Body, а не Body напрямую.
|
|
150
|
+
- `Header` / `Page.Header`, `Footer` / `Page.Footer` — соседние компоненты страницы.
|
|
151
|
+
- `Island` (`src/components/Island`) — используется внутри `Page.Body` типа FIRST,
|
|
152
|
+
даёт body карточное оформление.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Stories
|
|
157
|
+
|
|
158
|
+
Отдельных stories нет. Поведение Body показано через `Page.Body` в
|
|
159
|
+
`stories/Page/BodyPage.stories.tsx` с вариациями `type` и `verticalMargin`.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## История изменений
|
|
164
|
+
|
|
165
|
+
| Дата | Изменение |
|
|
166
|
+
|---|---|
|
|
167
|
+
| 2026-04-18 | Создан документ |
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
component: Button
|
|
3
|
+
category: Buttons
|
|
4
|
+
figma-node: "1-328"
|
|
5
|
+
figma-file: "https://www.figma.com/design/MeAqaaLV9acAgoBOkZC9C2/-W--LIB-DSN-01-Components-DCB-Next-v.1.3.0"
|
|
6
|
+
related: [ButtonIcon, ButtonDropdown, ButtonDropdownExtended]
|
|
7
|
+
tokens:
|
|
8
|
+
- --triplex-next-Button-General_Background_Default
|
|
9
|
+
- --triplex-next-Button-General_Color_Default
|
|
10
|
+
- --triplex-next-Button-General_Background_Hover
|
|
11
|
+
- --triplex-next-Button-General_Color_Hover
|
|
12
|
+
- --triplex-next-Button-General_Background_Active
|
|
13
|
+
- --triplex-next-Button-General_Color_Active
|
|
14
|
+
- --triplex-next-Button-General_Shadow_Focus
|
|
15
|
+
- --triplex-next-Button-General_Background_Disabled
|
|
16
|
+
- --triplex-next-Button-General_Color_Disabled
|
|
17
|
+
- --triplex-next-Button-Secondary_Background_Default
|
|
18
|
+
- --triplex-next-Button-Secondary_Color_Default
|
|
19
|
+
- --triplex-next-Button-Secondary_Background_Hover
|
|
20
|
+
- --triplex-next-Button-Secondary_Color_Hover
|
|
21
|
+
- --triplex-next-Button-Secondary_Background_Active
|
|
22
|
+
- --triplex-next-Button-Secondary_Color_Active
|
|
23
|
+
- --triplex-next-Button-Secondary_Shadow_Focus
|
|
24
|
+
- --triplex-next-Button-Secondary_Background_Disabled
|
|
25
|
+
- --triplex-next-Button-Secondary_Color_Disabled
|
|
26
|
+
- --triplex-next-Button-SecondaryLight_Background_Default
|
|
27
|
+
- --triplex-next-Button-SecondaryLight_Color_Default
|
|
28
|
+
- --triplex-next-Button-SecondaryLight_Background_Hover
|
|
29
|
+
- --triplex-next-Button-SecondaryLight_Color_Hover
|
|
30
|
+
- --triplex-next-Button-SecondaryLight_Background_Active
|
|
31
|
+
- --triplex-next-Button-SecondaryLight_Color_Active
|
|
32
|
+
- --triplex-next-Button-SecondaryLight_Shadow_Focus
|
|
33
|
+
- --triplex-next-Button-SecondaryLight_Background_Disabled
|
|
34
|
+
- --triplex-next-Button-SecondaryLight_Color_Disabled
|
|
35
|
+
- --triplex-next-Button-Danger_Background_Default
|
|
36
|
+
- --triplex-next-Button-Danger_Color_Default
|
|
37
|
+
- --triplex-next-Button-Danger_Background_Hover
|
|
38
|
+
- --triplex-next-Button-Danger_Color_Hover
|
|
39
|
+
- --triplex-next-Button-Danger_Background_Active
|
|
40
|
+
- --triplex-next-Button-Danger_Color_Active
|
|
41
|
+
- --triplex-next-Button-Danger_Shadow_Focus
|
|
42
|
+
- --triplex-next-Button-Danger_Background_Disabled
|
|
43
|
+
- --triplex-next-Button-Danger_Color_Disabled
|
|
44
|
+
- --triplex-next-Button-Link_Color_Default
|
|
45
|
+
- --triplex-next-Button-Link_Color_Hover
|
|
46
|
+
- --triplex-next-Button-Link_Color_Active
|
|
47
|
+
- --triplex-next-Button-Link_Shadow_Focus
|
|
48
|
+
- --triplex-next-Button-Link_Color_Disabled
|
|
49
|
+
- --triplex-next-Button-Icon_Shadow_Focus
|
|
50
|
+
stories: stories/Buttons/Button.stories.tsx
|
|
51
|
+
version: "1.0"
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
# Button
|
|
55
|
+
|
|
56
|
+
## Назначение
|
|
57
|
+
|
|
58
|
+
Основной интерактивный элемент для запуска действий. Существует в пяти визуальных темах
|
|
59
|
+
и трёх размерах. Поддерживает состояния загрузки, иконки и полноширинный режим.
|
|
60
|
+
|
|
61
|
+
Используй `Button` когда: нужна кнопка с текстом (с иконкой или без).
|
|
62
|
+
Используй `ButtonIcon` когда: нужна кнопка только с иконкой без текста.
|
|
63
|
+
Используй `ButtonDropdown` когда: нужен выбор из нескольких действий.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Файловая структура
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
src/components/Button/
|
|
71
|
+
├── Button.tsx # Основной компонент, union type TButtonProps
|
|
72
|
+
├── ButtonBase.tsx # Базовый <button>, extends HTML attrs
|
|
73
|
+
├── ButtonIcon.tsx # Иконочная кнопка (squircle / circle)
|
|
74
|
+
├── ButtonDropdown.tsx # Кнопка с выпадающим меню
|
|
75
|
+
├── ButtonDropdownExtended.tsx # Контейнер с кастомным dropdown
|
|
76
|
+
├── enums.ts # EButtonTheme, EButtonDotsTheme, EButtonIconShape
|
|
77
|
+
├── index.ts # Barrel exports
|
|
78
|
+
└── styles/
|
|
79
|
+
├── Button.module.less # Размеры, block, loading, base layout
|
|
80
|
+
├── ButtonGeneral.module.less # Тема GENERAL
|
|
81
|
+
├── ButtonSecondary.module.less
|
|
82
|
+
├── ButtonSecondaryLight.module.less
|
|
83
|
+
├── ButtonDanger.module.less
|
|
84
|
+
├── ButtonLink.module.less # Тема LINK — нет min-width, нет bg
|
|
85
|
+
├── ButtonIcon.module.less # Стили ButtonIcon
|
|
86
|
+
├── ButtonDropdown.module.less
|
|
87
|
+
└── ButtonDropdownExtended.module.less
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Варианты и props
|
|
93
|
+
|
|
94
|
+
### Темы (`EButtonTheme`)
|
|
95
|
+
|
|
96
|
+
| Значение | Описание | Поддерживает loading/icon/block |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `GENERAL` | Основной стиль (primary) | Да |
|
|
99
|
+
| `SECONDARY` | Вторичный | Да |
|
|
100
|
+
| `SECONDARY_LIGHT` | Вторичный светлый (для тёмных фонов) | Да |
|
|
101
|
+
| `DANGER` | Деструктивное действие | Да |
|
|
102
|
+
| `LINK` | Текстовая ссылка | Нет — `loading`, `icon`, `block` запрещены через `never` |
|
|
103
|
+
|
|
104
|
+
### Размеры (`EComponentSize`)
|
|
105
|
+
|
|
106
|
+
| Значение | Высота | Padding | Border-radius | Font-size |
|
|
107
|
+
|---|---|---|---|---|
|
|
108
|
+
| `SM` | 28px | 0 12px | 6px | 12px |
|
|
109
|
+
| `MD` | 40px | 0 20px | 8px | 14px |
|
|
110
|
+
| `LG` | 56px | 0 24px | 10px | 16px |
|
|
111
|
+
|
|
112
|
+
### Props компонента `Button`
|
|
113
|
+
|
|
114
|
+
| Prop | Тип | Обязателен | Описание |
|
|
115
|
+
|---|---|---|---|
|
|
116
|
+
| `theme` | `EButtonTheme` | Да | Визуальный стиль |
|
|
117
|
+
| `size` | `EComponentSize` | Да | Размер |
|
|
118
|
+
| `block` | `boolean` | Нет | Полноширинный режим (только не-LINK темы) |
|
|
119
|
+
| `loading` | `boolean` | Нет | Состояние загрузки: скрывает контент, показывает спиннер (только не-LINK темы) |
|
|
120
|
+
| `icon` | `React.ReactElement` | Нет | Иконка слева от текста; если без `children` — кнопка становится квадратной |
|
|
121
|
+
| `children` | `React.ReactNode` | Нет | Текст кнопки |
|
|
122
|
+
| `...HTMLButtonAttributes` | — | — | Все стандартные атрибуты `<button>` |
|
|
123
|
+
|
|
124
|
+
### Props компонента `ButtonIcon`
|
|
125
|
+
|
|
126
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
127
|
+
|---|---|---|---|
|
|
128
|
+
| `shape` | `EButtonIconShape` | `SQUIRCLE` | Форма: `SQUIRCLE` (4px radius) или `CIRCLE` (50%) |
|
|
129
|
+
| `active` | `boolean` | `false` | Визуальное активное состояние |
|
|
130
|
+
| `...HTMLButtonAttributes` | — | — | Включая `disabled` |
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## Ключевые особенности реализации
|
|
135
|
+
|
|
136
|
+
### Иконка без текста
|
|
137
|
+
Если передан `icon` без `children` — добавляется класс `.icon`, который делает кнопку квадратной:
|
|
138
|
+
```tsx
|
|
139
|
+
// Button.tsx — логика определения icon-only режима
|
|
140
|
+
const iconOnly = Boolean(icon) && !children;
|
|
141
|
+
<button className={clsx(styles.button, { [styles.icon]: iconOnly })}>
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Состояние загрузки
|
|
145
|
+
- `loading` скрывает контент через `visibility: hidden` (не `display: none`) — сохраняет размеры,
|
|
146
|
+
- устанавливает `tabIndex={-1}` — кнопка недоступна с клавиатуры
|
|
147
|
+
- Тема лоадера: `SECONDARY` и `SECONDARY_LIGHT` → `ELoaderSmallTheme.BRAND`, остальные → `ELoaderSmallTheme.NEUTRAL`
|
|
148
|
+
|
|
149
|
+
### `aria-expanded` управляет визуалом
|
|
150
|
+
Состояние "раскрыто" (например, когда кнопка открывает dropdown) управляется через `aria-expanded`:
|
|
151
|
+
```tsx
|
|
152
|
+
<Button aria-expanded={true} ...> → добавляет CSS-классы .expanded и .active
|
|
153
|
+
```
|
|
154
|
+
Отдельного prop `expanded` нет — используй стандартный HTML-атрибут.
|
|
155
|
+
|
|
156
|
+
### Тема LINK
|
|
157
|
+
- Нет `min-width`
|
|
158
|
+
- `background: transparent`
|
|
159
|
+
- `padding` по вертикали отличается от других тем (меньше)
|
|
160
|
+
- `block`, `loading`, `icon` — тип `never` в интерфейсе, TypeScript запрещает передачу
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Accessibility
|
|
165
|
+
|
|
166
|
+
- Нативный `<button>` — полная поддержка клавиатуры (Tab, Enter, Space) без дополнительных атрибутов.
|
|
167
|
+
- **`ButtonIcon`**: иконочная кнопка без видимого текста — потребитель **обязан** передать `aria-label` через `...rest`. Библиотека мультиязычная, текст не хардкодится.
|
|
168
|
+
- **`loading`**: устанавливает `tabIndex={-1}` — кнопка исключается из tab-порядка. Если нужна доступность состояния загрузки для скринридеров, потребитель добавляет `aria-busy="true"` через props.
|
|
169
|
+
- **`aria-expanded`**: управляет визуальным состоянием "раскрыто" (добавляет CSS-классы `.expanded`, `.active`). Передаётся потребителем при использовании кнопки как триггера dropdown.
|
|
170
|
+
- Фокус-стиль через `:focus-visible` — виден только при клавиатурной навигации.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Дизайн-токены
|
|
175
|
+
|
|
176
|
+
Паттерн: `--triplex-next-Button-{Theme}_{Property}_{State}`
|
|
177
|
+
|
|
178
|
+
Каждая тема (кроме LINK) имеет полный набор:
|
|
179
|
+
- `_Background_Default/Hover/Active/Disabled`
|
|
180
|
+
- `_Color_Default/Hover/Active/Disabled`
|
|
181
|
+
- `_Shadow_Focus`
|
|
182
|
+
|
|
183
|
+
Тема LINK — только `_Color_*` и `_Shadow_Focus` (нет фона).
|
|
184
|
+
|
|
185
|
+
При добавлении нового визуального состояния нужен новый токен в `src/generated/themesCssVariables.css`.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Инварианты
|
|
190
|
+
|
|
191
|
+
- **`forwardRef`** — обязателен на `Button`, `ButtonBase`, `ButtonIcon`, `ButtonDropdown`. Не убирать.
|
|
192
|
+
- **`TButtonProps` union type** — должен включать все тематические интерфейсы. При добавлении новой темы — добавь интерфейс в union.
|
|
193
|
+
- **`EButtonTheme` значения** — не переименовывать. Это публичное API.
|
|
194
|
+
- **`EComponentSize`** — общий enum из `src/enums/EComponentSize`, не делай локальный аналог.
|
|
195
|
+
- **Размеры (28px/40px/56px)** — не менять без согласования с дизайнером, другие компоненты ориентируются на эти размеры.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Связанные компоненты
|
|
200
|
+
|
|
201
|
+
- `ButtonIcon` (`src/components/Button/ButtonIcon.tsx`) — иконочная кнопка, часть того же компонента
|
|
202
|
+
- `ButtonDropdown` (`src/components/Button/ButtonDropdown.tsx`) — кнопка с выпадающим меню опций
|
|
203
|
+
- `ButtonDropdownExtended` — контейнер для кастомного dropdown с render-функциями
|
|
204
|
+
- `Loader` (`src/components/Loader`) — используется внутри Button для состояния загрузки
|
|
205
|
+
- `Dropdown` (`src/components/Dropdown`) — используется внутри ButtonDropdown
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Stories
|
|
210
|
+
|
|
211
|
+
`stories/Buttons/Button.stories.tsx`
|
|
212
|
+
Файлы примеров: `stories/Buttons/examples/Button/`
|
|
213
|
+
|
|
214
|
+
| Story | Example file | Что демонстрирует |
|
|
215
|
+
|---|---|---|
|
|
216
|
+
| `Playground` | `PlaygroundExample.tsx` | Интерактивный контроль всех props |
|
|
217
|
+
| `Default` | `DefaultExample.tsx` | Базовое использование |
|
|
218
|
+
| `States` | `StatesExample.tsx` | Expanded, loading, disabled |
|
|
219
|
+
| `Sizes` | `SizesExample.tsx` | SM / MD / LG для всех тем |
|
|
220
|
+
| `Themes` | `ThemesExample.tsx` | Все пять тем |
|
|
221
|
+
| `WithIcon` | `WithIconExample.tsx` | Icon-only и text+icon |
|
|
222
|
+
| `BlockMode` | `BlockModeExample.tsx` | Полноширинный режим |
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## История изменений
|
|
227
|
+
|
|
228
|
+
| Дата | Изменение |
|
|
229
|
+
|---|---|
|
|
230
|
+
| 2026-03-31 | Создан документ (пилот AI-Ready) |
|