@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.
Files changed (48) hide show
  1. package/README.md +7 -7
  2. package/bundle/components/AmountField.md +222 -323
  3. package/bundle/components/Avatar.md +138 -146
  4. package/bundle/components/CardStatic.md +402 -0
  5. package/bundle/components/CheckboxTree.md +157 -215
  6. package/bundle/components/CheckboxTreeExtended.md +7 -7
  7. package/bundle/components/ChipGroup.md +1 -1
  8. package/bundle/components/ChipMonthYearPicker.md +4 -4
  9. package/bundle/components/ChipSuggest.md +7 -6
  10. package/bundle/components/CollapsibleTree.md +8 -4
  11. package/bundle/components/CollapsibleTreeExtended.md +8 -6
  12. package/bundle/components/Confirm.md +346 -281
  13. package/bundle/components/DateRange.md +351 -210
  14. package/bundle/components/FooterPage.md +1 -0
  15. package/bundle/components/FormField.md +11 -4
  16. package/bundle/components/FormGroup.md +3 -2
  17. package/bundle/components/LightBox.md +8 -0
  18. package/bundle/components/ListMaster.md +2 -2
  19. package/bundle/components/ListTableItem.md +6 -6
  20. package/bundle/components/MonthYearField.md +15 -4
  21. package/bundle/components/Slider.md +389 -97
  22. package/bundle/components/SliderRange.md +486 -105
  23. package/bundle/components/StatusTracker.md +386 -94
  24. package/bundle/components/Stepper.md +355 -102
  25. package/bundle/components/StepperExtended.md +633 -0
  26. package/bundle/components/SuggestField.md +1049 -96
  27. package/bundle/components/SwipeableArea.md +7 -7
  28. package/bundle/components/Tabs.md +265 -92
  29. package/bundle/components/TabsExtended.md +18 -18
  30. package/bundle/components/TabsLine.md +301 -127
  31. package/bundle/components/TagColor.md +187 -66
  32. package/bundle/components/TagGroup.md +184 -48
  33. package/bundle/components/TextareaField.md +278 -70
  34. package/bundle/components/TopOverlay.md +17 -1
  35. package/bundle/components/TreeView.md +16 -7
  36. package/bundle/components/TriggerClickOnKeyDownEvent.md +277 -0
  37. package/bundle/components/UploadZone.md +318 -0
  38. package/bundle/guides/codestyle.md +16 -1
  39. package/bundle/guides/commits.md +47 -1
  40. package/bundle/guides/tests.md +23 -2
  41. package/bundle/manifest.json +48 -21
  42. package/bundle/release-notes/1.47.0.mdx +115 -0
  43. package/bundle/release-notes/1.48.0.mdx +68 -0
  44. package/bundle/release-notes/1.49.0.mdx +7 -0
  45. package/bundle/tokens.json +3 -3
  46. package/dist/index.js +220 -6
  47. package/dist/index.js.map +1 -1
  48. package/package.json +1 -1
@@ -1,10 +1,24 @@
1
1
  ---
2
2
  component: Stepper
3
- category: Navigation
4
- figma-node: ""
5
- figma-file: ""
6
- related: [Step, CarouselExtended, ButtonIcon]
7
- tokens: []
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
- заявки). Для ручной сборки из шагов без карусели — `StepperExtended`.
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
- ## Публичный API
41
+ ## Варианты и props
45
42
 
46
- ### `Stepper` — готовый виджет
43
+ `IStepperProps` расширяет `Omit<IStepperExtendedProps, "children">` (а тот — `React.HTMLAttributes<HTMLOListElement>`).
47
44
 
48
- | Prop | Тип | Default | Описание |
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
- ### `StepperExtended` — без карусели
47
+ ### Обязательные props
62
48
 
63
- Для ручной сборки (напр. в вертикальном layout).
49
+ | Prop | Тип | Описание |
50
+ |---|---|---|
51
+ | `steps` | `Array<IStepperStep>` | Состав ленты. Порядок массива = порядок прохождения: шаги до выбранного считаются пройденными, после — непройденными |
52
+ | `onSelectStep` | `(id: string) => void` | Запрос на смену выбранного шага. Вызывается кликом и клавишами `Enter` / `Space`, в том числе на уже выбранном шаге |
64
53
 
65
- | Prop | Тип | Default | Описание |
54
+ ### Опциональные props
55
+
56
+ | Prop | Тип | По умолчанию | Описание |
66
57
  |---|---|---|---|
67
- | `size?` | `EStepperSize` | `SM` | Прокидывается в Context. |
68
- | `selectedStepId?` | `string` | — | Id активного шага. |
69
- | `onSelectStep` | `(id: string) => void` | — | Колбэк. |
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
- ### `StepperStep` (`Stepper.Step` / `StepperExtended.Step`)
62
+ ### Поля элемента `steps` (`IStepperStep`)
74
63
 
75
- | Prop | Тип | Описание |
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
- | Prop | Тип | Описание |
66
+ | Поле | Тип | Описание |
94
67
  |---|---|---|
95
- | `type` | `EStepperStepIconType` | `FILLED` / `SUCCESS` / `ERROR` / `WARNING` / `WAIT`. |
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
- ### `Stepper.Wrapper` / `StepperExtended.Wrapper`
74
+ ### Ограничения
98
75
 
99
- Простой `<div>` с `className="stepperWrapper"` — layout-контейнер для размещения Stepper в шапке/панели.
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
- ## Контекст (`StepperExtendedContext`)
84
+ ## Дизайн-токены
104
85
 
105
- Хранит `selectedId`, `size`, `onSelectStep`. `StepperStep` — потребитель этого контекста.
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
- При смене `selectedStepId`:
112
- 1. `getBoundingClientRect` для carousel и шага.
113
- 2. На узких экранах (`max-width: SM_MAX`) → scroll по центру выбранного шага.
114
- 3. На широких → scroll к краю (left/right) с паддингом `32px` (`paddingLeft/Right`).
115
-
116
- Кнопки scroll'а рендерятся через `CarouselExtended.buttonPrev/Next` с `aria-label="Прокрутить назад" / "Прокрутить вперёд"`.
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
- - **`<ol role="tablist">`** на StepperExtended, **`<li role="button">`** на StepperStep — ARIA-роли.
123
- - **`aria-current`** применяется только к активному шагу (`progress ? true : undefined`). Для неактивных — должен быть `undefined`, не `false`.
124
- - **`tabIndex={disabled ? -1 : 0}`** на `<li>` — не ронять.
125
- - **Keyboard: Enter/Space** выбирают шаг. `Space` — с `preventDefault()` чтобы страница не скроллилась.
126
- - **`Stepper.children: never`** — API через `steps`.
127
- - **Публичные enums** (`EStepperSize`, `EStepperStepType`, `EStepperStepIconType`) — breaking change.
128
- - **`Stepper.Wrapper === StepperWrapper`** и **`Stepper.Step === StepperStep`** — дублируются на `Stepper` и `StepperExtended`, не удалять.
129
- - **`RightBorderArrow`** рендерится после контента каждого шага — визуальный separator. Не заменять inline-псевдоэлементом без проверки нарезки.
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"` / `role="button"` (`<li>` не tab — сделано по-проектному).
137
- - `aria-disabled={disabled}`, `aria-current={progress ? true : undefined}`.
138
- - Keyboard: Enter/Space — выбор шага. Стрелки — **не обрабатываются** (используется carousel-прокрутка). Переход Tab-ом: по одному шагу.
139
- - Авто-прокрутка при `selectedStepId` может сбить фокус визуально — но focus на `<li>` сохраняется, шаг всегда будет в видимой области.
140
- - Потребитель должен обеспечить осмысленные labels шагов (`label` или `children`) — не полагаться на номер.
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
- - `Step` — отдельный кружок шага (не используется внутри Stepper).
147
- - `CarouselExtended` — обёртка в `Stepper`.
148
- - `ButtonIcon`, `IconWrapper` — UI.
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
- Примеры: `stories/Stepper/examples/`
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-04-18 | Создан документ |
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
+