@sberbusiness/triplex-next-mcp-server 1.46.0-beta → 1.48.0-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/bundle/components/AmountField.md +222 -323
- package/bundle/components/Avatar.md +138 -146
- package/bundle/components/CardStatic.md +402 -0
- package/bundle/components/CheckboxTree.md +157 -215
- package/bundle/components/CheckboxTreeExtended.md +7 -7
- package/bundle/components/ChipGroup.md +1 -1
- package/bundle/components/ChipMonthYearPicker.md +4 -4
- package/bundle/components/ChipSuggest.md +7 -6
- package/bundle/components/CollapsibleTree.md +8 -4
- package/bundle/components/CollapsibleTreeExtended.md +8 -6
- package/bundle/components/Confirm.md +346 -281
- package/bundle/components/DateRange.md +351 -210
- package/bundle/components/FooterPage.md +1 -0
- package/bundle/components/FormField.md +11 -4
- package/bundle/components/FormGroup.md +3 -2
- package/bundle/components/LightBox.md +8 -0
- package/bundle/components/ListMaster.md +2 -2
- package/bundle/components/ListTableItem.md +6 -6
- package/bundle/components/MonthYearField.md +15 -4
- package/bundle/components/Slider.md +389 -97
- package/bundle/components/SliderRange.md +486 -105
- package/bundle/components/StatusTracker.md +386 -94
- package/bundle/components/Stepper.md +355 -102
- package/bundle/components/StepperExtended.md +633 -0
- package/bundle/components/SuggestField.md +1049 -96
- package/bundle/components/SwipeableArea.md +7 -7
- package/bundle/components/Tabs.md +265 -92
- package/bundle/components/TabsExtended.md +18 -18
- package/bundle/components/TabsLine.md +301 -127
- package/bundle/components/TagColor.md +187 -66
- package/bundle/components/TagGroup.md +184 -48
- package/bundle/components/TextareaField.md +278 -70
- package/bundle/components/TopOverlay.md +17 -1
- package/bundle/components/TreeView.md +16 -7
- package/bundle/components/TriggerClickOnKeyDownEvent.md +277 -0
- package/bundle/components/UploadZone.md +318 -0
- package/bundle/guides/codestyle.md +16 -1
- package/bundle/guides/commits.md +47 -1
- package/bundle/guides/tests.md +23 -2
- package/bundle/manifest.json +48 -21
- package/bundle/release-notes/1.47.0.mdx +115 -0
- package/bundle/release-notes/1.48.0.mdx +68 -0
- package/bundle/release-notes/1.49.0.mdx +7 -0
- package/bundle/tokens.json +3 -3
- package/dist/index.js +220 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
component: Stepper
|
|
3
|
-
category:
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
category: Stepper
|
|
4
|
+
related: [StepperExtended, Step, CarouselExtended, ButtonIcon]
|
|
5
|
+
tokens:
|
|
6
|
+
- Stepper.ButtonWrapper_Background_Next
|
|
7
|
+
- Stepper.ButtonWrapper_Background_Prev
|
|
8
|
+
- Stepper.Step_Background_Default
|
|
9
|
+
- Stepper.Step_Background_Disabled
|
|
10
|
+
- Stepper.Step_Background_Error
|
|
11
|
+
- Stepper.Step_Background_Error_Hover
|
|
12
|
+
- Stepper.Step_Background_Hover
|
|
13
|
+
- Stepper.Step_Background_Warning
|
|
14
|
+
- Stepper.Step_Background_Warning_Hover
|
|
15
|
+
- Stepper.Step_BorderColor_Error
|
|
16
|
+
- Stepper.Step_BorderColor_Focus
|
|
17
|
+
- Stepper.Step_BorderColor_Success
|
|
18
|
+
- Stepper.Step_BorderColor_Warning
|
|
19
|
+
- Stepper.Step_Color_Default
|
|
20
|
+
- Stepper.Step_Color_Disabled
|
|
21
|
+
- Stepper.Step_Color_Hover
|
|
8
22
|
stories: stories/Stepper/Stepper.stories.tsx
|
|
9
23
|
version: "1.0"
|
|
10
24
|
---
|
|
@@ -13,146 +27,138 @@ version: "1.0"
|
|
|
13
27
|
|
|
14
28
|
## Назначение
|
|
15
29
|
|
|
16
|
-
|
|
17
|
-
непройденными. Обёрнут в `CarouselExtended` — при overflow добавляются
|
|
18
|
-
кнопки-скроллеры и авто-прокрутка к выбранному шагу (с адаптивом по
|
|
19
|
-
breakpoint `SM_MAX`: scroll-to-center vs scroll-to-edge).
|
|
30
|
+
Лента шагов-стрелок поверх `StepperExtended` и `CarouselExtended`: компонент принимает массив шагов, сам собирает разметку, сам рендерит кнопки прокрутки для не поместившихся шагов и сам подводит выбранный шаг в видимую область.
|
|
20
31
|
|
|
21
|
-
Используй когда:
|
|
22
|
-
|
|
23
|
-
Для отдельного кружка шага — `Step`.
|
|
32
|
+
Используй когда: нужно показать прохождение многошагового сценария и дать переключаться между шагами — это первый выбор для обычной задачи.
|
|
33
|
+
Не используй когда:
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```text
|
|
30
|
-
src/components/Stepper/
|
|
31
|
-
├── Stepper.tsx # FC, оборачивает StepperExtended в CarouselExtended
|
|
32
|
-
├── StepperExtended.tsx # FC + Provider (tablist), без карусели
|
|
33
|
-
├── StepperStep.tsx # FC + StepperStep.Icon; li role=button
|
|
34
|
-
├── StepperStepIcon.tsx
|
|
35
|
-
├── StepperWrapper.tsx # статичная обёртка
|
|
36
|
-
├── StepperExtendedContext.ts
|
|
37
|
-
├── RightBorderArrow.tsx # угловой «стрелочный» separator между шагами
|
|
38
|
-
├── enums.ts # EStepperSize, EStepperStepType, EStepperStepIconType
|
|
39
|
-
└── styles/
|
|
40
|
-
```
|
|
35
|
+
- содержимое шага нестандартное (своя разметка внутри шага, свои кнопки прокрутки) — бери `StepperExtended`, `Stepper` собран поверх него;
|
|
36
|
+
- нужен нумерованный индикатор шагов с подписью и тултипом вместо ленты-стрелок — бери `Step`;
|
|
37
|
+
- шаги не переключаются пользователем и нужен только статус процесса — это не задача компонента.
|
|
41
38
|
|
|
42
39
|
---
|
|
43
40
|
|
|
44
|
-
##
|
|
41
|
+
## Варианты и props
|
|
45
42
|
|
|
46
|
-
|
|
43
|
+
`IStepperProps` расширяет `Omit<IStepperExtendedProps, "children">` (а тот — `React.HTMLAttributes<HTMLOListElement>`).
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
|---|---|---|---|
|
|
50
|
-
| `steps` | `IStepperStep[]` | — | Массив шагов: `id`, `type`, `icon?`, `disabled?`, `label?`. |
|
|
51
|
-
| `size?` | `EStepperSize` | `SM` | SM / MD / LG. |
|
|
52
|
-
| `selectedStepId?` | `string` | — | Id выбранного шага. |
|
|
53
|
-
| `onSelectStep` | `(id: string) => void` | — | Колбэк выбора. |
|
|
54
|
-
| `children` | `never` | — | Запрещено — шаги передаются через `steps`. |
|
|
55
|
-
|
|
56
|
-
`IStepperStep`:
|
|
57
|
-
```ts
|
|
58
|
-
{ id: string; type: EStepperStepType; label?: ReactNode; icon?: ReactNode; disabled?: boolean }
|
|
59
|
-
```
|
|
45
|
+
**Куда что уходит.** Компонент вынимает из props только `className`, `steps`, `size` и `selectedStepId`. `className` мерджится в корневой `<div>` карусели, а **все остальные props** уходят на `<ol role="tablist">` внутри неё. Это разные элементы: `aria-label`, `data-*`, `style`, `id`, `onClick` и прочее оказываются на списке шагов, а не на корне. В частности, `className` и `style` попадают на **разные** элементы: `<Stepper style={{width: 400}} />` задаёт ширину `<ol>`, а не корня.
|
|
60
46
|
|
|
61
|
-
###
|
|
47
|
+
### Обязательные props
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
| Prop | Тип | Описание |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| `steps` | `Array<IStepperStep>` | Состав ленты. Порядок массива = порядок прохождения: шаги до выбранного считаются пройденными, после — непройденными |
|
|
52
|
+
| `onSelectStep` | `(id: string) => void` | Запрос на смену выбранного шага. Вызывается кликом и клавишами `Enter` / `Space`, в том числе на уже выбранном шаге |
|
|
64
53
|
|
|
65
|
-
|
|
54
|
+
### Опциональные props
|
|
55
|
+
|
|
56
|
+
| Prop | Тип | По умолчанию | Описание |
|
|
66
57
|
|---|---|---|---|
|
|
67
|
-
| `size
|
|
68
|
-
| `selectedStepId
|
|
69
|
-
| `
|
|
70
|
-
| `forwardedRef?` | `Ref<HTMLOListElement>` | — | Ref на `<ol role="tablist">`. |
|
|
71
|
-
| `children` | `ReactNode` | — | `StepperExtended.Step` (`StepperStep`). |
|
|
58
|
+
| `size` | `EComponentSize` | `MD` | Один prop на весь компонент: задаёт и высоту шагов, и размер кнопок прокрутки |
|
|
59
|
+
| `selectedStepId` | `string` | — | `id` текущего шага. Компонент полностью управляемый: своего состояния выбора у него нет |
|
|
60
|
+
| `forwardedRef` | `React.Ref<HTMLOListElement>` | — | Ссылка на `<ol>` со списком шагов. Единственный ref-контракт компонента — см. «Инварианты» |
|
|
72
61
|
|
|
73
|
-
### `
|
|
62
|
+
### Поля элемента `steps` (`IStepperStep`)
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|---|---|---|
|
|
77
|
-
| `id` | `string` | Уникальный id (матчится с `selectedStepId`). |
|
|
78
|
-
| `type` | `EStepperStepType` | `NEUTRAL` / `ERROR` / `WARNING` (применяет цветовой модификатор, если !disabled). |
|
|
79
|
-
| `disabled?` | `boolean` | Блокирует выбор. |
|
|
80
|
-
| `icon?` | `ReactNode` | Обычно `<StepperStep.Icon type={EStepperStepIconType} />`. |
|
|
81
|
-
| `isInActiveStep?` | `boolean` | Непройденный шаг (индекс > selectedIndex). В `Stepper` выставляется автоматически. |
|
|
82
|
-
| `forwardedRef?` | `Ref<HTMLLIElement>` | Ref на `<li>`. В `Stepper` используется для авто-скролла. |
|
|
83
|
-
| `children` | `ReactNode` | Лейбл шага. |
|
|
84
|
-
|
|
85
|
-
Статус шага определяется композицией:
|
|
86
|
-
- `active` = `id === selectedId`
|
|
87
|
-
- `inactive` = `isInActiveStep`
|
|
88
|
-
- `completed` = `!active && !inactive`
|
|
89
|
-
- `error`/`warning` применяются поверх, когда `!disabled`.
|
|
90
|
-
|
|
91
|
-
### `StepperStep.Icon`
|
|
64
|
+
`IStepperStep` расширяет `IStepperStepProps`, то есть принимает и HTML-атрибуты `<li>`-элемента шага.
|
|
92
65
|
|
|
93
|
-
|
|
|
66
|
+
| Поле | Тип | Описание |
|
|
94
67
|
|---|---|---|
|
|
95
|
-
| `
|
|
68
|
+
| `id` | `string` | Обязательное. Сопоставляется с `selectedStepId`, приходит в `onSelectStep`, служит React-ключом |
|
|
69
|
+
| `type` | `EStepperStepType` | Обязательное. `NEUTRAL` — обычный шаг, `ERROR` / `WARNING` подсвечивают шаг цветом. У отключённого шага тип не применяется |
|
|
70
|
+
| `label` | `React.ReactNode` | Содержимое шага. Единственное поле, которое не уходит в HTML-атрибуты `<li>` |
|
|
71
|
+
| `icon` | `React.ReactNode` | Иконка статуса слева от `label`, обычно `StepperStepIcon`. Гасится вместе с шагом при `disabled` |
|
|
72
|
+
| `disabled` | `boolean` | Шаг не реагирует на клик и клавиатуру и выпадает из таб-порядка |
|
|
96
73
|
|
|
97
|
-
###
|
|
74
|
+
### Ограничения
|
|
98
75
|
|
|
99
|
-
|
|
76
|
+
- `isInActiveStep` компонент вычисляет сам по индексу шага относительно выбранного и перетирает значение, переданное в элементе `steps`.
|
|
77
|
+
- `forwardedRef` в элементе `steps`, наоборот, перетирает внутреннюю ссылку `Stepper` на шаг — после этого лента перестаёт подводить выбранный шаг в видимую область. Ссылки на шаги нужны компоненту для прокрутки; если нужен доступ к узлу шага, бери его через `forwardedRef` самого `Stepper` и DOM-обход.
|
|
78
|
+
- `id` шагов должны быть уникальными: по ним идёт сопоставление с `selectedStepId`, React-ключи и внутренняя карта ссылок на узлы.
|
|
79
|
+
- Пустой массив `steps` допустим — рендерится пустой `<ol>`.
|
|
80
|
+
- Если `selectedStepId` не задан или не найден в `steps`, пройденных шагов нет: вся лента отображается как непройденная.
|
|
100
81
|
|
|
101
82
|
---
|
|
102
83
|
|
|
103
|
-
##
|
|
84
|
+
## Дизайн-токены
|
|
104
85
|
|
|
105
|
-
|
|
86
|
+
Переопределяются через `ThemeProvider` (prop `tokens`) — см. `ThemeProvider-ai.md` →
|
|
87
|
+
«Как переопределять токены». Значения по умолчанию — `src/components/DesignTokens/components/Stepper.ts`.
|
|
106
88
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
## Логика выравнивания в Stepper
|
|
89
|
+
Семейство `Stepper.Step_*` общее для `Stepper`, `StepperExtended` и шага `StepperStep` — оформление самих шагов приходит оттуда. Собственные стили `Stepper` — только подложка под кнопками прокрутки (`ButtonWrapper_*`), она растушёвывает край ленты градиентом.
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
91
|
+
```text
|
|
92
|
+
Stepper.ButtonWrapper_Background_Prev
|
|
93
|
+
Stepper.ButtonWrapper_Background_Next
|
|
94
|
+
Stepper.Step_Background_Default
|
|
95
|
+
Stepper.Step_Background_Hover
|
|
96
|
+
Stepper.Step_Background_Disabled
|
|
97
|
+
Stepper.Step_Background_Error
|
|
98
|
+
Stepper.Step_Background_Error_Hover
|
|
99
|
+
Stepper.Step_Background_Warning
|
|
100
|
+
Stepper.Step_Background_Warning_Hover
|
|
101
|
+
Stepper.Step_BorderColor_Focus
|
|
102
|
+
Stepper.Step_BorderColor_Error
|
|
103
|
+
Stepper.Step_BorderColor_Warning
|
|
104
|
+
Stepper.Step_BorderColor_Success
|
|
105
|
+
Stepper.Step_Color_Default
|
|
106
|
+
Stepper.Step_Color_Hover
|
|
107
|
+
Stepper.Step_Color_Disabled
|
|
108
|
+
```
|
|
117
109
|
|
|
118
110
|
---
|
|
119
111
|
|
|
120
112
|
## Инварианты
|
|
121
113
|
|
|
122
|
-
-
|
|
123
|
-
-
|
|
124
|
-
-
|
|
125
|
-
-
|
|
126
|
-
-
|
|
127
|
-
-
|
|
128
|
-
-
|
|
129
|
-
-
|
|
130
|
-
- **Корневой `<ol>` — не кнопка**; клик открывается на `<li>` через `role="button"` (W3C-некомпатибельно по-строгому, но принятая конвенция проекта).
|
|
114
|
+
- **Ref-контракт — prop `forwardedRef`, а не `ref`.** `Stepper` объявлен как `React.FC`: `React.forwardRef` ему не добавляли осознанно. `CarouselExtended` отдаёт наружу ссылку на прокручиваемую ленту, а не на корневой `<div>`, а сам `Stepper` держит эту ссылку для прокрутки — поэтому `ref` пришлось бы вести на другой DOM-узел, чем уже задокументированный `forwardedRef` (`<ol>`), и получилось бы два ref-контракта на разные элементы. Добавление `forwardRef` требует сначала научить `CarouselExtended` отдавать корневой элемент.
|
|
115
|
+
- Публичные имена `Stepper`, `IStepperProps`, `IStepperStep`, `EStepperStepType`, `EStepperStepIconType` и barrel `src/components/Stepper/index.ts` — часть публичного API.
|
|
116
|
+
- `Stepper.Step = StepperStep` — статическое свойство, часть публичного API (тот же компонент, что `StepperExtended.Step`).
|
|
117
|
+
- Компонент строится на `CarouselExtended` и передаёт ему `stepPrev` / `stepNext` — величину прокрутки одним кликом, равную 30% ширины видимой области ленты. Величина пересчитывается `ResizeObserver` и до первого измерения равна нулю.
|
|
118
|
+
- Состояние шага кодируется взаимоисключающими классами `completed` / `active` / `inactive` и вычисляется по индексу относительно выбранного шага. Зафиксировано unit-тестами.
|
|
119
|
+
- Класс размера (`sm` / `md` / `lg`) вешается и на корневой `<div>` карусели, и на каждый шаг: от него зависят и высота шага, и размер кнопки прокрутки.
|
|
120
|
+
- Кнопки прокрутки исключены из таб-порядка (`tabIndex = -1`) и скрыты на экранах уже 768px — прокрутка всё равно доступна колесом, жестом и обходом шагов по `Tab`.
|
|
121
|
+
- Подводка выбранного шага в видимую область (`alignStep`) — функции модульного уровня в `Stepper.tsx` (читают геометрию DOM через `getBoundingClientRect`, проверяют `window.matchMedia` и прокручивают ленту), зафиксированы unit-тестами: на узких экранах шаг центрируется, на широких — прижимается к ближайшему краю вместе с соседним шагом.
|
|
131
122
|
|
|
132
123
|
---
|
|
133
124
|
|
|
134
125
|
## Accessibility
|
|
135
126
|
|
|
136
|
-
- `role="tablist"
|
|
137
|
-
- `
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
127
|
+
- Разметка приходит из `StepperExtended` и `StepperStep`: корневой список — `<ol role="tablist">`, каждый шаг — `<li role="button">`. Выбранный шаг помечается `aria-current="true"`, отключённый — `aria-disabled="true"` и `tabIndex = -1`.
|
|
128
|
+
- **Известное расхождение с WAI-ARIA:** дети `role="tablist"` имеют `role="button"`, а не `role="tab"`. Это текущее публичное поведение, зафиксированное тестами; смена ролей — отдельная задача с записью в release notes.
|
|
129
|
+
- **Клавиатура:** `Enter` и `Space` на шаге вызывают `onSelectStep`, для `Space` дополнительно вызывается `preventDefault`, чтобы страница не скроллилась. Других клавиш компонент не перехватывает: между шагами ходят обычным `Tab` — каждый доступный шаг находится в таб-порядке.
|
|
130
|
+
- `:focus-visible` эмулируется вручную: класс подсветки ставится, только если фокус пришёл не после `mousedown`, — клик по шагу рамку не рисует.
|
|
131
|
+
- Кнопки прокрутки компонент рендерит сам и текста не хардкодит: доступного имени у них нет, поэтому они исключены из таб-порядка и не должны быть единственным способом добраться до шага.
|
|
132
|
+
- При смене `selectedStepId` лента прокручивается плавно (анимация по кадрам, `prefers-reduced-motion` не учитывается).
|
|
141
133
|
|
|
142
134
|
---
|
|
143
135
|
|
|
144
136
|
## Связанные компоненты
|
|
145
137
|
|
|
146
|
-
- `
|
|
147
|
-
- `
|
|
148
|
-
- `
|
|
138
|
+
- `StepperExtended` — база: `Stepper` рендерит его и наследует его интерфейс (`IStepperProps extends Omit<IStepperExtendedProps, "children">`). Туда же уходят, когда нужен нестандартный состав шага.
|
|
139
|
+
- `StepperStep` — шаг ленты, доступен как `Stepper.Step` и `StepperExtended.Step`. Отдельного AI.md нет: через `Stepper` он настраивается полями элемента `steps`, вся его семантика описана выше.
|
|
140
|
+
- `StepperStepIcon` — иконка статуса шага: маппинг значения `EStepperStepIconType` (`FILLED`, `SUCCESS`, `WARNING`, `ERROR`, `WAIT`) в иконку из `@sberbusiness/icons-next`. Отдельного AI.md нет — это тривиальная обёртка с единственным prop `type`.
|
|
141
|
+
- `Step` — альтернативный визуальный паттерн шагов: нумерованный кружок с подписью и тултипом вместо ленты-стрелок.
|
|
142
|
+
- `CarouselExtended` — прокручиваемая лента, которую `Stepper` рендерит сам; ему же передаётся величина прокрутки одним кликом.
|
|
143
|
+
- `ButtonIcon` — кнопки прокрутки ленты, которые `Stepper` рендерит через render-props `buttonPrev` / `buttonNext` карусели.
|
|
149
144
|
|
|
150
145
|
---
|
|
151
146
|
|
|
152
147
|
## Stories
|
|
153
148
|
|
|
154
149
|
Основные истории: `stories/Stepper/Stepper.stories.tsx`
|
|
155
|
-
|
|
150
|
+
Файлы примеров: `stories/Stepper/examples/`
|
|
151
|
+
|
|
152
|
+
| Story | Example file | Что демонстрирует |
|
|
153
|
+
|---|---|---|
|
|
154
|
+
| `Playground` | `Playground.tsx` | Интерактивный контроль размера, типа текущего шага, количества шагов, иконок и ширины контейнера |
|
|
155
|
+
| `Default` | `Default.tsx` | Минимальный набор: три шага, выбран второй |
|
|
156
|
+
| `Sizes` | `Sizes.tsx` | Размеры SM / MD / LG |
|
|
157
|
+
| `Types` | `Types.tsx` | Типы шага `NEUTRAL`, `ERROR`, `WARNING` |
|
|
158
|
+
| `WithIcons` | `WithIcons.tsx` | Все значения `EStepperStepIconType` на шагах |
|
|
159
|
+
| `ManySteps` | `ManySteps.tsx` | Шаги не помещаются в контейнер и прокручиваются |
|
|
160
|
+
| `VisualTests` | `VisualTests.tsx` | Размеры × состояния, отключённый шаг, типы, `:focus-visible` на шаге (через `play`) |
|
|
161
|
+
| `StepperExtendedType` | — | Стори базового `StepperExtended`; живёт в этом файле до отдельной задачи по `StepperExtended` |
|
|
156
162
|
|
|
157
163
|
---
|
|
158
164
|
|
|
@@ -160,4 +166,251 @@ src/components/Stepper/
|
|
|
160
166
|
|
|
161
167
|
| Дата | Изменение |
|
|
162
168
|
|---|---|
|
|
163
|
-
| 2026-
|
|
169
|
+
| 2026-09-24 | Создан документ AI-ready для `Stepper` (TRI-84). |
|
|
170
|
+
| 2026-09-24 | AI-рефакторинг: подводка шага и кнопки прокрутки вынесены в чистые функции и отдельный компонент модульного уровня, величина прокрутки хранится одним числом вместо объекта, ссылки на узлы удалённых шагов больше не удерживаются, JSDoc проставлен на публичных полях `steps` и `size`. Публичный API (имена props, значения enum, barrel-экспорты) и разметка не изменились. Добавлены unit-тесты на состояния шагов, типы, клавиатуру, `forwardedRef`, `...rest` и подводку шага в видимую область; stories переписаны по modern pattern. |
|
|
171
|
+
| 2026-09-25 | Размер по умолчанию изменён с `LG` на `MD` по решению ревью — вместе со `StepperExtended`, чтобы компоненты не разъехались. Изменение наблюдаемое: без явного `size` шаги и кнопки прокрутки становятся меньше, описано в release notes 1.48.0. |
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Примеры использования
|
|
176
|
+
|
|
177
|
+
### Default
|
|
178
|
+
|
|
179
|
+
`stories/Stepper/examples/Default.tsx`
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
import React, { useState } from "react";
|
|
183
|
+
import { EStepperStepIconType, EStepperStepType, Stepper, StepperStepIcon } from "@sberbusiness/triplex-next";
|
|
184
|
+
|
|
185
|
+
const STEPS = [
|
|
186
|
+
{
|
|
187
|
+
id: "step1",
|
|
188
|
+
label: "Step 1",
|
|
189
|
+
type: EStepperStepType.NEUTRAL,
|
|
190
|
+
icon: <StepperStepIcon type={EStepperStepIconType.SUCCESS} />,
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
id: "step2",
|
|
194
|
+
label: "Step 2",
|
|
195
|
+
type: EStepperStepType.NEUTRAL,
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: "step3",
|
|
199
|
+
label: "Step 3",
|
|
200
|
+
type: EStepperStepType.NEUTRAL,
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
export const Default = () => {
|
|
205
|
+
const [selectedStepId, setSelectedStepId] = useState("step2");
|
|
206
|
+
|
|
207
|
+
return <Stepper steps={STEPS} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId} />;
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Sizes
|
|
212
|
+
|
|
213
|
+
`stories/Stepper/examples/Sizes.tsx`
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import React, { useState } from "react";
|
|
217
|
+
import {
|
|
218
|
+
EComponentSize,
|
|
219
|
+
EStepperStepIconType,
|
|
220
|
+
EStepperStepType,
|
|
221
|
+
Stepper,
|
|
222
|
+
StepperStepIcon,
|
|
223
|
+
} from "@sberbusiness/triplex-next";
|
|
224
|
+
|
|
225
|
+
const STEPS = [
|
|
226
|
+
{
|
|
227
|
+
id: "step1",
|
|
228
|
+
label: "Step 1",
|
|
229
|
+
type: EStepperStepType.NEUTRAL,
|
|
230
|
+
icon: <StepperStepIcon type={EStepperStepIconType.SUCCESS} />,
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
id: "step2",
|
|
234
|
+
label: "Step 2",
|
|
235
|
+
type: EStepperStepType.NEUTRAL,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: "step3",
|
|
239
|
+
label: "Step 3",
|
|
240
|
+
type: EStepperStepType.NEUTRAL,
|
|
241
|
+
},
|
|
242
|
+
];
|
|
243
|
+
|
|
244
|
+
interface ISizeItemProps {
|
|
245
|
+
size: EComponentSize;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const SizeItem = ({ size }: ISizeItemProps) => {
|
|
249
|
+
const [selectedStepId, setSelectedStepId] = useState("step2");
|
|
250
|
+
|
|
251
|
+
return (
|
|
252
|
+
<div>
|
|
253
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{size.toUpperCase()}</div>
|
|
254
|
+
<Stepper steps={STEPS} size={size} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId} />
|
|
255
|
+
</div>
|
|
256
|
+
);
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
const SIZES = Object.values(EComponentSize);
|
|
260
|
+
|
|
261
|
+
export const Sizes = () => (
|
|
262
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
263
|
+
{SIZES.map((size) => (
|
|
264
|
+
<SizeItem key={size} size={size} />
|
|
265
|
+
))}
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Types
|
|
271
|
+
|
|
272
|
+
`stories/Stepper/examples/Types.tsx`
|
|
273
|
+
|
|
274
|
+
```tsx
|
|
275
|
+
import React, { useState } from "react";
|
|
276
|
+
import {
|
|
277
|
+
EStepperStepIconType,
|
|
278
|
+
EStepperStepType,
|
|
279
|
+
IStepperStep,
|
|
280
|
+
Stepper,
|
|
281
|
+
StepperStepIcon,
|
|
282
|
+
} from "@sberbusiness/triplex-next";
|
|
283
|
+
|
|
284
|
+
/** Набор шагов, в котором второй шаг помечен переданным типом. */
|
|
285
|
+
const getSteps = (type: EStepperStepType, iconType: EStepperStepIconType): Array<IStepperStep> => [
|
|
286
|
+
{
|
|
287
|
+
id: "step1",
|
|
288
|
+
label: "Step 1",
|
|
289
|
+
type: EStepperStepType.NEUTRAL,
|
|
290
|
+
icon: <StepperStepIcon type={EStepperStepIconType.SUCCESS} />,
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
id: "step2",
|
|
294
|
+
label: "Step 2",
|
|
295
|
+
type,
|
|
296
|
+
icon: <StepperStepIcon type={iconType} />,
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
id: "step3",
|
|
300
|
+
label: "Step 3",
|
|
301
|
+
type: EStepperStepType.NEUTRAL,
|
|
302
|
+
},
|
|
303
|
+
];
|
|
304
|
+
|
|
305
|
+
interface ITypeItemProps {
|
|
306
|
+
caption: string;
|
|
307
|
+
type: EStepperStepType;
|
|
308
|
+
iconType: EStepperStepIconType;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const TypeItem = ({ caption, type, iconType }: ITypeItemProps) => {
|
|
312
|
+
const [selectedStepId, setSelectedStepId] = useState("step2");
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
<div>
|
|
316
|
+
<div style={{ marginBottom: "8px", fontSize: "16px", fontWeight: "700" }}>{caption}</div>
|
|
317
|
+
<Stepper
|
|
318
|
+
steps={getSteps(type, iconType)}
|
|
319
|
+
selectedStepId={selectedStepId}
|
|
320
|
+
onSelectStep={setSelectedStepId}
|
|
321
|
+
/>
|
|
322
|
+
</div>
|
|
323
|
+
);
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
export const Types = () => (
|
|
327
|
+
<div style={{ display: "flex", flexDirection: "column", gap: "24px" }}>
|
|
328
|
+
<TypeItem caption="NEUTRAL" type={EStepperStepType.NEUTRAL} iconType={EStepperStepIconType.WAIT} />
|
|
329
|
+
<TypeItem caption="ERROR" type={EStepperStepType.ERROR} iconType={EStepperStepIconType.ERROR} />
|
|
330
|
+
<TypeItem caption="WARNING" type={EStepperStepType.WARNING} iconType={EStepperStepIconType.WARNING} />
|
|
331
|
+
</div>
|
|
332
|
+
);
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### WithIcons
|
|
336
|
+
|
|
337
|
+
`stories/Stepper/examples/WithIcons.tsx`
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
import React, { useState } from "react";
|
|
341
|
+
import { EStepperStepIconType, EStepperStepType, Stepper, StepperStepIcon } from "@sberbusiness/triplex-next";
|
|
342
|
+
|
|
343
|
+
const STEPS = [
|
|
344
|
+
{
|
|
345
|
+
id: "step1",
|
|
346
|
+
label: "FILLED",
|
|
347
|
+
type: EStepperStepType.NEUTRAL,
|
|
348
|
+
icon: <StepperStepIcon type={EStepperStepIconType.FILLED} />,
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
id: "step2",
|
|
352
|
+
label: "SUCCESS",
|
|
353
|
+
type: EStepperStepType.NEUTRAL,
|
|
354
|
+
icon: <StepperStepIcon type={EStepperStepIconType.SUCCESS} />,
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: "step3",
|
|
358
|
+
label: "WAIT",
|
|
359
|
+
type: EStepperStepType.NEUTRAL,
|
|
360
|
+
icon: <StepperStepIcon type={EStepperStepIconType.WAIT} />,
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: "step4",
|
|
364
|
+
label: "ERROR",
|
|
365
|
+
type: EStepperStepType.ERROR,
|
|
366
|
+
icon: <StepperStepIcon type={EStepperStepIconType.ERROR} />,
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
id: "step5",
|
|
370
|
+
label: "WARNING",
|
|
371
|
+
type: EStepperStepType.WARNING,
|
|
372
|
+
icon: <StepperStepIcon type={EStepperStepIconType.WARNING} />,
|
|
373
|
+
},
|
|
374
|
+
];
|
|
375
|
+
|
|
376
|
+
export const WithIcons = () => {
|
|
377
|
+
const [selectedStepId, setSelectedStepId] = useState("step3");
|
|
378
|
+
|
|
379
|
+
return <Stepper steps={STEPS} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId} />;
|
|
380
|
+
};
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### ManySteps
|
|
384
|
+
|
|
385
|
+
`stories/Stepper/examples/ManySteps.tsx`
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
import React, { useState } from "react";
|
|
389
|
+
import {
|
|
390
|
+
EStepperStepIconType,
|
|
391
|
+
EStepperStepType,
|
|
392
|
+
IStepperStep,
|
|
393
|
+
Stepper,
|
|
394
|
+
StepperStepIcon,
|
|
395
|
+
} from "@sberbusiness/triplex-next";
|
|
396
|
+
|
|
397
|
+
const STEPS: Array<IStepperStep> = Array.from({ length: 15 }, (_, index) => ({
|
|
398
|
+
id: `step${index + 1}`,
|
|
399
|
+
label: `Step ${index + 1}`,
|
|
400
|
+
type: EStepperStepType.NEUTRAL,
|
|
401
|
+
icon: index < 4 ? <StepperStepIcon type={EStepperStepIconType.SUCCESS} /> : undefined,
|
|
402
|
+
}));
|
|
403
|
+
|
|
404
|
+
export const ManySteps = () => {
|
|
405
|
+
const [selectedStepId, setSelectedStepId] = useState("step2");
|
|
406
|
+
|
|
407
|
+
return (
|
|
408
|
+
// Контейнер уже ленты шагов: лишние шаги уезжают за край и прокручиваются.
|
|
409
|
+
// Кнопки прокрутки появляются по наведению на ленту и скрыты на узких экранах.
|
|
410
|
+
<div style={{ maxWidth: "480px" }}>
|
|
411
|
+
<Stepper steps={STEPS} selectedStepId={selectedStepId} onSelectStep={setSelectedStepId} />
|
|
412
|
+
</div>
|
|
413
|
+
);
|
|
414
|
+
};
|
|
415
|
+
```
|
|
416
|
+
|