@olddevs/ui 4.2.1 → 4.3.0
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/CHANGELOG.md +22 -0
- package/dist/components/navigation/MegaMenu.d.ts +43 -23
- package/dist/components/navigation/MegaMenu.d.ts.map +1 -1
- package/dist/components/navigation/MegaMenu.js +110 -47
- package/dist/components/navigation/MegaMenu.js.map +1 -1
- package/dist/components/navigation/useMenuAim.d.ts +8 -8
- package/dist/components/navigation/useMenuAim.d.ts.map +1 -1
- package/dist/components/overlays/Menu.d.ts +4 -2
- package/dist/components/overlays/Menu.d.ts.map +1 -1
- package/dist/components/overlays/Menu.js.map +1 -1
- package/docs/components/index.en.md +2 -2
- package/docs/components/index.md +1 -1
- package/docs/components/navigation/mega-menu.en.md +91 -61
- package/docs/components/navigation/mega-menu.md +86 -56
- package/docs/components/overlays/menu.en.md +8 -4
- package/docs/components/overlays/menu.md +6 -3
- package/docs/getting-started.en.md +2 -2
- package/docs/getting-started.md +1 -1
- package/docs/glossary.en.md +23 -23
- package/docs/glossary.md +22 -22
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/src/components/navigation/MegaMenu.tsx +300 -140
- package/src/components/navigation/useMenuAim.ts +19 -19
- package/src/components/overlays/Menu.tsx +12 -2
|
@@ -12,9 +12,10 @@ story: src/components/navigation/MegaMenu.stories.tsx
|
|
|
12
12
|
## Кратко для AI
|
|
13
13
|
|
|
14
14
|
`MegaMenu` — каталог магазина в духе Amazon: слева Столбец категорий, справа от наведённой Категории — её
|
|
15
|
-
|
|
15
|
+
Полка с колонками ссылок и любым своим содержимым. Это навигация по ссылкам, а не меню команд: разметка по
|
|
16
16
|
шаблону WAI-ARIA Disclosure Navigation (`nav`, кнопки с `aria-expanded`, настоящие `a`). Категории —
|
|
17
|
-
`MegaMenuCategory`
|
|
17
|
+
`MegaMenuCategory` (прямо или внутри своих компонентов, в том числе серверных), колонки — `MegaMenuGroup`,
|
|
18
|
+
ссылки — `MegaMenuLink`. Текущий раздел и текущая страница — проп `active`, как у `NavItem`. Тот же каталог
|
|
18
19
|
открывается выпадающим оверлеем от кнопки: `MegaMenuTrigger` с `MegaMenuButton` и неизменным `MegaMenu`.
|
|
19
20
|
|
|
20
21
|
## Когда использовать
|
|
@@ -22,7 +23,7 @@ story: src/components/navigation/MegaMenu.stories.tsx
|
|
|
22
23
|
- Каталог с десятком и больше разделов, у каждого — подразделы колонками: магазин, маркетплейс, справочный
|
|
23
24
|
портал.
|
|
24
25
|
- Разделы надо показать сразу, а подразделы — по наведению, не уводя пользователя со страницы.
|
|
25
|
-
- В
|
|
26
|
+
- В Полке рядом со ссылками нужно своё содержимое: промо-карточка, картинка, подборка.
|
|
26
27
|
|
|
27
28
|
## Когда не использовать
|
|
28
29
|
|
|
@@ -37,10 +38,10 @@ story: src/components/navigation/MegaMenu.stories.tsx
|
|
|
37
38
|
import { MegaMenu, MegaMenuCategory, MegaMenuGroup, MegaMenuLink } from "@olddevs/ui";
|
|
38
39
|
|
|
39
40
|
<MegaMenu aria-label="Каталог">
|
|
40
|
-
<MegaMenuCategory id="computers" label="Компьютеры" href="/computers">
|
|
41
|
+
<MegaMenuCategory id="computers" label="Компьютеры" href="/computers" active>
|
|
41
42
|
<MegaMenuGroup title="Ноутбуки" href="/computers/laptops">
|
|
42
43
|
<MegaMenuLink href="/computers/laptops/gaming">Игровые</MegaMenuLink>
|
|
43
|
-
<MegaMenuLink href="/computers/laptops/ultrabooks"
|
|
44
|
+
<MegaMenuLink href="/computers/laptops/ultrabooks" active>
|
|
44
45
|
Ультрабуки
|
|
45
46
|
</MegaMenuLink>
|
|
46
47
|
</MegaMenuGroup>
|
|
@@ -57,62 +58,75 @@ import { MegaMenu, MegaMenuCategory, MegaMenuGroup, MegaMenuLink } from "@olddev
|
|
|
57
58
|
| ------------------------------------------ | ------------ | ------------------------------------------------------------------------------------------ |
|
|
58
59
|
| `aria-label` | — | Доступное имя навигации, обязательно: на странице с несколькими `nav` их различают по нему |
|
|
59
60
|
| `value` / `defaultValue` / `onValueChange` | `null` | Открытая Категория (её `id`) или `null`, управляемо или нет |
|
|
60
|
-
| `showcaseWidth` | `"40rem"` | Ширина
|
|
61
|
+
| `showcaseWidth` | `"40rem"` | Ширина Полки, одна на все Категории: каталог не прыгает при переходе между ними |
|
|
61
62
|
| `className` | — | Классы на `nav`; ширина Столбца по умолчанию — `w-64` |
|
|
62
63
|
|
|
63
|
-
`MegaMenuCategory`: `id` — ключ для `value`; `label` — подпись в Столбце и имя
|
|
64
|
-
`link` — адрес раздела целиком; `disabled`;
|
|
65
|
-
|
|
64
|
+
`MegaMenuCategory`: `id` — ключ для `value`; `label` — подпись в Столбце и имя Полки; `icon`; `href` или
|
|
65
|
+
`link` — адрес раздела целиком; `disabled`; `active` — текущая страница лежит в этом разделе; дети —
|
|
66
|
+
содержимое Полки. У Категории с Полкой адрес становится
|
|
67
|
+
заголовком-ссылкой в начале Полки, у Категории без детей сама строка Столбца — ссылка. `link` — ссылка роутера
|
|
66
68
|
пустым элементом (`link={<Link href="/x" />}`), подпись уезжает внутрь; это отдельный проп, а не `asChild`,
|
|
67
|
-
потому что дети Категории — её
|
|
69
|
+
потому что дети Категории — её Полка.
|
|
68
70
|
|
|
69
|
-
`
|
|
70
|
-
|
|
71
|
+
`active` у Категории ставит `aria-current="true"` и красит подпись акцентным цветом — тем же, что у текущей
|
|
72
|
+
ссылки. Открыта Полка или нет, отметка остаётся: текущий раздел задаёт маршрут, а не наведение. Открытая
|
|
73
|
+
Категория по-прежнему выделена фоном, так что у одной строки бывают оба признака. Пока ни одна Полка не открыта,
|
|
74
|
+
Tab приходит в Столбец на текущий раздел. Какой раздел текущий, решает потребитель, как с `active` у `NavItem`.
|
|
71
75
|
|
|
72
|
-
|
|
76
|
+
Категории не обязаны быть прямыми детьми `MegaMenu`: их можно разложить по своим компонентам и рендерить из
|
|
77
|
+
серверного компонента Next.js. Каждая Категория сама сообщает Столбцу о себе, а Столбец не разбирает детей по
|
|
78
|
+
типу — у серверного компонента тип элемента на клиенте другой. До гидратации, пока Категории о себе не сообщили,
|
|
79
|
+
остановка Tab стоит у каждой доступной Категории; после гидратации Столбец снова одна остановка.
|
|
80
|
+
|
|
81
|
+
`MegaMenuGroup`: `title` — заголовок колонки, он же подпись списка; `href` или `link` делают заголовок ссылкой
|
|
82
|
+
(`link` — ссылка роутера пустым элементом, как у Категории); дети — `MegaMenuLink`, каждая уезжает в свой пункт
|
|
83
|
+
списка, в том числе пришедшие фрагментом.
|
|
84
|
+
|
|
85
|
+
`MegaMenuLink`: обычные пропы `a`, `icon`, `active` и `asChild`. `active` ставит `aria-current="page"` и вид
|
|
73
86
|
текущей: текущую страницу кит не вычисляет, правила сравнения адресов у каждого роутера свои. `asChild` выводит
|
|
74
|
-
ссылку элементом роутера: `<MegaMenuLink asChild><Link href="/x">Подпись</Link></MegaMenuLink>`.
|
|
87
|
+
ссылку элементом роутера: `<MegaMenuLink asChild><Link href="/x">Подпись</Link></MegaMenuLink>`. Прежнее имя
|
|
88
|
+
`current` работает до 5.0 и помечено `@deprecated`: текущий пункт навигации в ките называется `active`.
|
|
75
89
|
|
|
76
|
-
## Наведение и
|
|
90
|
+
## Наведение и Полка
|
|
77
91
|
|
|
78
|
-
Наведение мышью на Категорию открывает её
|
|
79
|
-
|
|
92
|
+
Наведение мышью на Категорию открывает её Полку сразу, без задержки. Подсвечена ровно та Категория, чья
|
|
93
|
+
Полка открыта: подсветка идёт по `aria-expanded`, а не по `:hover`. Наведение на Категорию без Полки
|
|
80
94
|
закрывает открытую — с той же оговоркой про Прицел, что ниже.
|
|
81
95
|
|
|
82
|
-
|
|
96
|
+
Полка закрывается, когда курсор ушёл и со Столбца, и с Полки, через 150 мс: короткий выход за край не
|
|
83
97
|
сбрасывает каталог. Закрывают её и нажатие указателем вне каталога, и уход фокуса со страницы каталога.
|
|
84
98
|
|
|
85
|
-
Содержимое
|
|
99
|
+
Содержимое Полки монтируется только у открытой Категории: каталог из сотни ссылок и картинок не грузит всё
|
|
86
100
|
разом. Сам регион есть всегда, скрытым: на него указывает `aria-controls` кнопки.
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
по странице», и
|
|
102
|
+
Полка — потомок своей Категории в DOM, а не портал. Поэтому порядок Tab идёт «Категория → её ссылки → дальше
|
|
103
|
+
по странице», и Полка встаёт вплотную к Столбцу без расчёта позиции. Предок с `overflow: hidden` её обрежет:
|
|
90
104
|
ставьте каталог туда, где рядом есть место.
|
|
91
105
|
|
|
92
|
-
|
|
106
|
+
Полка стоит со стороны конца строки — справа, а при письме справа налево слева. Если там не хватает места, а с
|
|
93
107
|
другой стороны хватает, она переходит на другую сторону; сторону кит меряет заранее и при смене размера окна,
|
|
94
|
-
поэтому стрелка «к
|
|
108
|
+
поэтому стрелка «к Полке» сразу смотрит туда, где Полка окажется.
|
|
95
109
|
|
|
96
110
|
## Касание и узкий экран
|
|
97
111
|
|
|
98
112
|
Касание наведения не знает, поэтому Категорию открывает само касание (`click`), без Прицела. Указатель с
|
|
99
|
-
`pointerType` «touch» или «pen» не открывает Категорию наведением и не закрывает
|
|
113
|
+
`pointerType` «touch» или «pen» не открывает Категорию наведением и не закрывает Полку уходом: перо
|
|
100
114
|
ведёт себя как палец. Повторное касание открытой Категории её не закрывает и никуда не ведёт: закрывает
|
|
101
|
-
|
|
115
|
+
Полку касание вне каталога или Escape.
|
|
102
116
|
|
|
103
117
|
Мышь ведёт себя, как раньше: наведение, Прицел и закрытие через 150 мс остаются, пока экран широкий.
|
|
104
118
|
|
|
105
|
-
На узком экране — меньше 640px, граница та же, что у подменю `Menu` и подменю Редактора, —
|
|
119
|
+
На узком экране — меньше 640px, граница та же, что у подменю `Menu` и подменю Редактора, — Полке некуда
|
|
106
120
|
встать сбоку: справа от Столбца её обрезал бы край окна. Поэтому каталог идёт «спуском»:
|
|
107
121
|
|
|
108
122
|
- Столбец занимает всю ширину, подписи Категорий переносятся, а не обрезаются.
|
|
109
|
-
- Открытая Категория (касанием, щелчком, Enter или Пробелом) заменяет Столбец своей
|
|
123
|
+
- Открытая Категория (касанием, щелчком, Enter или Пробелом) заменяет Столбец своей Полкой. Полка
|
|
110
124
|
начинается строкой «Назад» с названием Категории; если у Категории есть своя ссылка, название показывает она,
|
|
111
125
|
строкой ниже, а не строка «Назад». Ниже — колонки ссылок, одна под другой.
|
|
112
126
|
- «Назад» возвращает Столбец и ставит фокус на Категорию, из которой человек пришёл. Escape внутри
|
|
113
|
-
|
|
127
|
+
Полки работает как «Назад».
|
|
114
128
|
- Фокус при спуске переходит на «Назад»: кнопка Категории скрыта вместе со Столбцом, и фокус на ней
|
|
115
|
-
пропал бы. Стрелка в сторону Столбца в
|
|
129
|
+
пропал бы. Стрелка в сторону Столбца в Полке на узком экране ничего не делает: Столбца рядом нет.
|
|
116
130
|
- Прицела на узком экране нет, наведение мышью Категорию не открывает, а уход мыши не отменяет спуск:
|
|
117
131
|
заменять Столбец под курсором значило бы вырывать его из-под руки.
|
|
118
132
|
- Разметка остаётся по шаблону disclosure: кнопка Категории сохраняет `aria-expanded` и `aria-controls`
|
|
@@ -123,25 +137,25 @@ import { MegaMenu, MegaMenuCategory, MegaMenuGroup, MegaMenuLink } from "@olddev
|
|
|
123
137
|
|
|
124
138
|
Ширину кит читает через `matchMedia`, а не через CSS: от неё зависит состав разметки (прячется Столбец), а
|
|
125
139
|
не только вид. До гидратации и на сервере хук возвращает «широкий» (ADR-0018): сервер ширины не знает, и
|
|
126
|
-
разметка с него всегда обычная. На телефоне после гидратации
|
|
140
|
+
разметка с него всегда обычная. На телефоне после гидратации Полка, открытая `defaultValue`, один раз
|
|
127
141
|
перерисовывается спуском. На телефоне `nav` занимает всю ширину классом `max-sm:w-full`; `w-*` из `className` действует на
|
|
128
142
|
широком экране.
|
|
129
143
|
|
|
130
144
|
## Прицел
|
|
131
145
|
|
|
132
|
-
Курсор идёт от Категории к её
|
|
133
|
-
открывало их сразу,
|
|
134
|
-
куда движется курсор: пока он идёт в сторону открытой
|
|
146
|
+
Курсор идёт от Категории к её Полке наискосок и по пути задевает соседние Категории. Если бы наведение
|
|
147
|
+
открывало их сразу, Полка менялась бы у человека под рукой, и до ссылки было бы не дотянуться. Прицел смотрит,
|
|
148
|
+
куда движется курсор: пока он идёт в сторону открытой Полки, соседняя Категория наведение не перехватывает.
|
|
135
149
|
|
|
136
150
|
- Направление последнего шага курсора сравнивается с сектором от его прежней точки к двум углам ближнего края
|
|
137
|
-
|
|
151
|
+
Полки — это и есть треугольник Каменса из раздела «Откуда это». Шаг в сектор — курсор целится.
|
|
138
152
|
- Одно движение мимо прощается, два подряд — нет: тогда открывается Категория под курсором.
|
|
139
153
|
- Курсор остановился на 300 мс — открывается Категория под ним, даже если он целился. Меню не «залипает».
|
|
140
|
-
- Курсор дошёл до
|
|
154
|
+
- Курсор дошёл до Полки — отложенная смена отменяется.
|
|
141
155
|
- Щелчок по Категории открывает её сразу, мимо Прицела. Клавиатура Прицела не знает вовсе.
|
|
142
156
|
- Только мышь, и только на широком экране: касание и перо открывают Категорию сразу, а на узком экране
|
|
143
157
|
Прицела нет вовсе.
|
|
144
|
-
- Первое наведение, пока
|
|
158
|
+
- Первое наведение, пока Полки нет, открывает Категорию без всякой задержки: целиться ещё не во что.
|
|
145
159
|
|
|
146
160
|
Модель та же, что у подменю react-aria (`Menu` с `SubmenuTrigger`), чтобы два меню кита вели себя одинаково.
|
|
147
161
|
Отличий два. Смена Категории откладывается, а не гасится `pointer-events: none` на Столбце: иначе пропала бы
|
|
@@ -166,6 +180,11 @@ import { MegaMenu, MegaMenuCategory, MegaMenuGroup, MegaMenuLink } from "@olddev
|
|
|
166
180
|
внутри треугольника значит, что человек ведёт курсор к подменю, и пункты, задетые по пути, его не перехватывают.
|
|
167
181
|
Курсор вышел из треугольника — подменю меняется сразу. Свой разбор Каменс опубликовал 6 марта 2013 года.
|
|
168
182
|
|
|
183
|
+

|
|
184
|
+
|
|
185
|
+
_Анимация из [поста Бена Каменса](https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown), в
|
|
186
|
+
пересказе на Хабре._
|
|
187
|
+
|
|
169
188
|
**Плагин и математика.** По этому принципу Каменс написал jQuery-плагин `jQuery-menu-aim` и поставил его в
|
|
170
189
|
новое меню «Learn» на Khan Academy. Попадание точки в треугольник проверяется векторным произведением — с этой
|
|
171
190
|
линейной алгеброй ему помогла Софи Алперт, — но в плагине Каменс выбрал способ попроще: сравнение наклонов прямых.
|
|
@@ -189,15 +208,20 @@ import { MegaMenu, MegaMenuCategory, MegaMenuGroup, MegaMenuLink } from "@olddev
|
|
|
189
208
|
## Клавиатура и имена
|
|
190
209
|
|
|
191
210
|
- Столбец — одна остановка Tab. Стрелки вверх и вниз, Home и End ходят по Категориям; выключенные
|
|
192
|
-
пропускаются. Вернувшись Tab'ом, пользователь попадает на ту Категорию, где
|
|
193
|
-
|
|
211
|
+
пропускаются. Вернувшись Tab'ом, пользователь попадает на ту Категорию, где был; в первый раз — на открытую,
|
|
212
|
+
иначе на текущий раздел (`active`), иначе на первую.
|
|
213
|
+
- Буква на Категории переводит фокус на следующую Категорию, чья подпись с неё начинается, по кругу; та же буква
|
|
214
|
+
ещё раз — на следующую. Буквы, набранные подряд, ищут начало подписи, пауза в полсекунды сбрасывает набранное.
|
|
215
|
+
Пробел посреди набора — часть подписи («Home and garden»), а не открытие Категории.
|
|
216
|
+
Буква с Ctrl, Cmd или Alt — сочетание клавиш, каталог её не трогает.
|
|
217
|
+
- Enter, Пробел и стрелка в сторону Полки открывают её и ставят фокус на первую ссылку. У Категории-ссылки
|
|
194
218
|
Enter — переход.
|
|
195
|
-
- Внутри
|
|
196
|
-
и закрывает
|
|
197
|
-
- Пока
|
|
198
|
-
- Стрелка «к
|
|
219
|
+
- Внутри Полки работает обычный Tab. Стрелка в сторону Столбца возвращает фокус на Категорию, Escape — тоже,
|
|
220
|
+
и закрывает Полку. Tab за последней ссылкой уходит дальше по странице и закрывает Полку.
|
|
221
|
+
- Пока Полка открыта, она следует за фокусом стрелок и букв, как следует за наведением.
|
|
222
|
+
- Стрелка «к Полке» — та, что смотрит туда, где Полка стоит: при письме справа налево и у края экрана
|
|
199
223
|
стрелки меняются местами.
|
|
200
|
-
- Скринридер слышит навигацию с именем из `aria-label`, Категории — кнопками «развёрнуто / свёрнуто»,
|
|
224
|
+
- Скринридер слышит навигацию с именем из `aria-label`, Категории — кнопками «развёрнуто / свёрнуто», Полку
|
|
201
225
|
— регионом с именем Категории, колонку — списком с именем заголовка.
|
|
202
226
|
|
|
203
227
|
## Выпадающий вид
|
|
@@ -237,10 +261,10 @@ import { ListIcon } from "@olddevs/ui/icons";
|
|
|
237
261
|
- **Открытие.** Щелчок, Enter, Пробел и стрелка вниз на кнопке. Наведение каталог не открывает: он не должен
|
|
238
262
|
выпрыгивать от случайного движения мыши.
|
|
239
263
|
- **Фокус.** При открытии фокус встаёт на первую доступную Категорию (если одна из них уже открыта через `value` или
|
|
240
|
-
`defaultValue` — на неё),
|
|
264
|
+
`defaultValue` — на неё), Полка закрыта до выбора. Дальше Столбец и Полка работают как во встроенном виде.
|
|
241
265
|
- **Закрытие.** Escape на Категории, нажатие вне каталога, повторный щелчок по кнопке, переход по любой ссылке
|
|
242
266
|
(Категория, заголовок колонки, `MegaMenuLink`, в том числе ссылки роутера) и Tab за последним элементом.
|
|
243
|
-
Первый Escape внутри
|
|
267
|
+
Первый Escape внутри Полки закрывает только Полку и возвращает фокус на её Категорию; оверлей закрывает
|
|
244
268
|
следующий.
|
|
245
269
|
- **Возврат фокуса.** На кнопку фокус возвращается при Escape и при повторном щелчке. После Tab за последним
|
|
246
270
|
элементом фокус идёт дальше по странице, за кнопкой; Shift+Tab перед первым элементом возвращает на кнопку. После
|
|
@@ -248,10 +272,14 @@ import { ListIcon } from "@olddevs/ui/icons";
|
|
|
248
272
|
- **Скринридер.** Кнопка — раскрыватель с `aria-expanded` и `aria-controls`, без `aria-haspopup`: оверлей — не
|
|
249
273
|
меню и не диалог, а та же навигация с ссылками. Роли `dialog` у оверлея нет.
|
|
250
274
|
- **Слои.** Оверлей лежит на слое `popover`: выше затемнения открытого `Dialog`, ниже подтверждения. Внутри окна
|
|
251
|
-
первый Escape закрывает каталог, следующий — окно. Если фокус в открытой
|
|
275
|
+
первый Escape закрывает каталог, следующий — окно. Если фокус в открытой Полке, самый первый Escape закрывает
|
|
252
276
|
только её и возвращает фокус на Категорию.
|
|
253
|
-
-
|
|
254
|
-
|
|
277
|
+
- **Узкий экран.** Уже 640px оверлей занимает всю ширину окна за вычетом отступов по 8px с краёв, а не сжимается по
|
|
278
|
+
самой длинной подписи: подписи переносятся, длинная не выталкивает каталог за край, и ширина не меняется при
|
|
279
|
+
спуске в Категорию. Спуск, «Назад» и Escape работают внутри оверлея так же, как во встроенном виде: первый
|
|
280
|
+
Escape в Полке возвращает Столбец, следующий закрывает каталог.
|
|
281
|
+
- **Высота.** Оверлей не выше видимой области от кнопки до края окна. Столбец и Полка прокручиваются каждый
|
|
282
|
+
внутри себя (`overscroll-contain`), а не оверлей целиком: иначе рамка оверлея обрезала бы Полку, которая
|
|
255
283
|
стоит рядом со Столбцом. На iOS высота ограничена `min(24rem, 60dvh)`, как у панели `Menu`.
|
|
256
284
|
- **Появление.** Плавное, по шкале движения кита; при `prefers-reduced-motion` без анимации.
|
|
257
285
|
- **Сервер.** На сервере рисуется закрытая кнопка; оверлей монтируется в портале после открытия.
|
|
@@ -260,14 +288,16 @@ import { ListIcon } from "@olddevs/ui/icons";
|
|
|
260
288
|
|
|
261
289
|
- Реализация: `src/components/navigation/MegaMenu.tsx`, Прицел — `src/components/navigation/useMenuAim.ts`.
|
|
262
290
|
- Тесты: `tests/mega-menu.test.tsx` — роли и `aria-controls`, наведение и монтирование только открытой
|
|
263
|
-
|
|
264
|
-
Категория-ссылка, выключенная Категория, `current`, `asChild` и `link
|
|
265
|
-
|
|
291
|
+
Полки, закрытие с задержкой, roving tabindex, Enter, Escape и стрелки, Tab за последней ссылкой,
|
|
292
|
+
Категория-ссылка, выключенная Категория, `active` и алиас `current`, `asChild` и `link` (у Категории и у
|
|
293
|
+
колонки), фрагменты в колонке, текущий раздел и остановка Tab, поиск по первой букве, Категории в своих
|
|
294
|
+
компонентах, управляемое значение, нажатие вне каталога, рендер на сервере; `tests/mega-menu-aim.test.tsx` — Прицел на подменённой геометрии и поддельном
|
|
266
295
|
времени, переворот у края; `tests/mega-menu-touch.test.tsx` — касание и перо, подмена `matchMedia`, спуск
|
|
267
|
-
вместо Столбца, «Назад» и фокус, Escape, подписи из каталога сообщений,
|
|
268
|
-
|
|
296
|
+
вместо Столбца, «Назад» и фокус, Escape, подписи из каталога сообщений, спуск у Категорий в своих
|
|
297
|
+
компонентах, рендер на сервере; браузерный тест `tests-visual/mega-menu.spec.ts` — настоящая мышь наискосок и
|
|
298
|
+
вниз по Столбцу, ширина выпадающего вида на телефоне.
|
|
269
299
|
- Выпадающий вид: `tests/mega-menu-dropdown.test.tsx` — открытие щелчком и клавишами с фокусом на первой
|
|
270
|
-
Категории, все пути закрытия и возврат фокуса, Escape в
|
|
271
|
-
`popover`, порядок Escape внутри `Dialog`, рендер на сервере.
|
|
300
|
+
Категории, все пути закрытия и возврат фокуса, Escape в Полке, `open` / `defaultOpen` / `onOpenChange`, слой
|
|
301
|
+
`popover`, порядок Escape внутри `Dialog`, спуск на узком экране, рендер на сервере.
|
|
272
302
|
- История: `src/components/navigation/MegaMenu.stories.tsx` — в том числе `DropdownInTopBar`, мегаменю в шапке; на ширине
|
|
273
|
-
телефона — `PhoneColumn` и `
|
|
303
|
+
телефона — `PhoneColumn`, `PhoneDrillDown`, `PhoneDropdown` и `PhoneDropdownDrillDown`.
|
|
@@ -5,7 +5,7 @@ category: overlays
|
|
|
5
5
|
status: stable
|
|
6
6
|
source: src/components/overlays/Menu.tsx
|
|
7
7
|
story: src/components/overlays/Menu.stories.tsx
|
|
8
|
-
sourceHash:
|
|
8
|
+
sourceHash: e6bb9a14d118
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Menu
|
|
@@ -57,8 +57,11 @@ and `className`; `aria-label` is required if the button has no text, and with
|
|
|
57
57
|
`iconOnly` it never does. `Menu` accepts the usual `AriaMenuProps`, plus `offset`,
|
|
58
58
|
the gap between the panel and the button in pixels (default 6), and `placement`,
|
|
59
59
|
the side where the panel opens (default for the root menu `bottom start`; also
|
|
60
|
-
`bottom end`, `top start`, `top end`, `
|
|
61
|
-
default is described below).
|
|
60
|
+
`bottom end`, `top start`, `top end`, `end top`, `start top`, `right top` and
|
|
61
|
+
`left top`; the submenu default is described below). `end top` and `start top`
|
|
62
|
+
open beside the panel at the end or the start of the line, so they swap sides in
|
|
63
|
+
right-to-left writing; `right top` and `left top` don't depend on the writing
|
|
64
|
+
direction.
|
|
62
65
|
|
|
63
66
|
`MenuItem` accepts the `AriaMenuItem` props, `icon`, `shortcut`, `tone`,
|
|
64
67
|
`disabled` and `className`; pass the action in `onAction`. `MenuSection` accepts
|
|
@@ -72,7 +75,8 @@ the right, react-aria flips it to the left. In a right-to-left layout everything
|
|
|
72
75
|
mirrored: the submenu opens to the left of its item. On a narrow screen (up to 639px wide)
|
|
73
76
|
there is no room on either side, so the submenu opens below its item, over the
|
|
74
77
|
parent menu. An explicit `placement` on the nested `Menu` wins over the default,
|
|
75
|
-
phones included
|
|
78
|
+
phones included; to pick the side yourself without breaking right-to-left
|
|
79
|
+
writing, use `end top` or `start top`. The root menu opens as before, at `bottom start`. The Editor's
|
|
76
80
|
submenus follow the same rule.
|
|
77
81
|
|
|
78
82
|
Moving the pointer diagonally toward a submenu neither closes it nor switches to a
|
|
@@ -54,8 +54,10 @@ button look props, `icon`, `children`, `disabled`, `aria-label` и `className`;
|
|
|
54
54
|
`aria-label` обязателен, если у кнопки нет подписи; с `iconOnly` её нет всегда.
|
|
55
55
|
`Menu` принимает обычные `AriaMenuProps`, плюс `offset` — отступ панели от кнопки
|
|
56
56
|
в пикселях (умолчание 6) и `placement` — сторона раскрытия (умолчание корневого
|
|
57
|
-
меню `bottom start`; ещё `bottom end`, `top start`, `top end`, `
|
|
58
|
-
`left top`; умолчание подменю — ниже).
|
|
57
|
+
меню `bottom start`; ещё `bottom end`, `top start`, `top end`, `end top`,
|
|
58
|
+
`start top`, `right top`, `left top`; умолчание подменю — ниже). `end top` и
|
|
59
|
+
`start top` — сбоку по концу и по началу строки: при письме справа налево они
|
|
60
|
+
меняются местами. `right top` и `left top` от направления письма не зависят.
|
|
59
61
|
|
|
60
62
|
`MenuItem` принимает props `AriaMenuItem`, `icon`, `shortcut`, `tone`, `disabled`
|
|
61
63
|
и `className`; действие передавайте в `onAction`. `MenuSection` принимает
|
|
@@ -69,7 +71,8 @@ react-aria переворачивает подменю влево. При пис
|
|
|
69
71
|
подменю раскрывается слева от пункта. На узком экране (до 639px шириной) места
|
|
70
72
|
сбоку нет ни справа, ни слева, и подменю встаёт под своим пунктом, поверх
|
|
71
73
|
родительского меню. Явный `placement` у вложенного `Menu` побеждает умолчание, в
|
|
72
|
-
том числе на
|
|
74
|
+
том числе на телефоне; чтобы задать сторону самому и не сломать письмо справа
|
|
75
|
+
налево, берите `end top` или `start top`. Корневое меню раскрывается как прежде — `bottom start`.
|
|
73
76
|
То же правило у подменю Редактора.
|
|
74
77
|
|
|
75
78
|
Движение курсора к подменю по диагонали его не закрывает и не переключает на
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
sourceHash:
|
|
2
|
+
sourceHash: fdfa8cd8c38b
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Setting up `@olddevs/ui`
|
|
@@ -132,7 +132,7 @@ peer dependencies are treated as external, and the metric is gzip:
|
|
|
132
132
|
| `cn` and `tableStateToParams` | 0.6 kB |
|
|
133
133
|
| one `Button` | 1.6 kB |
|
|
134
134
|
| `DataTable` | 9.0 kB |
|
|
135
|
-
| the whole kit (`import *`) |
|
|
135
|
+
| the whole kit (`import *`) | 77.1 kB |
|
|
136
136
|
| `RichTextEditor` from `@olddevs/ui/editor`, without the engine, "start" | 70.6 kB |
|
|
137
137
|
| `RichTextEditor` with the Tiptap engine, "start" (static graph, `basic`) | 295.3 kB |
|
|
138
138
|
| `RichTextEditor` with the Tiptap engine, "full" (with all lazy chunks, `full`) | 339.1 kB |
|
package/docs/getting-started.md
CHANGED
|
@@ -129,7 +129,7 @@ peer-зависимости внешние, метрика gzip:
|
|
|
129
129
|
| `cn` и `tableStateToParams` | 0,6 кБ |
|
|
130
130
|
| одна `Button` | 1,6 кБ |
|
|
131
131
|
| `DataTable` | 9,0 кБ |
|
|
132
|
-
| весь кит целиком (`import *`) |
|
|
132
|
+
| весь кит целиком (`import *`) | 77,1 кБ |
|
|
133
133
|
| `RichTextEditor` из `@olddevs/ui/editor`, без движка, «старт» | 70,6 кБ |
|
|
134
134
|
| `RichTextEditor` вместе с движком Tiptap, «старт» (статический граф, `basic`) | 295,3 кБ |
|
|
135
135
|
| `RichTextEditor` вместе с движком Tiptap, «полный» (со всеми ленивыми чанками, `full`) | 339,1 кБ |
|
package/docs/glossary.en.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
sourceHash:
|
|
2
|
+
sourceHash: eb21f7a757f6
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Glossary of `@olddevs/ui`
|
|
@@ -44,7 +44,7 @@ Prop names are a separate vocabulary:
|
|
|
44
44
|
| Term | Meaning | Not to be confused with |
|
|
45
45
|
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
46
46
|
| **the Reference** | Markdown in the package's `docs/`: component, API and convention pages — the source of truth about the public contract. Ships in the package and is shown on the site as is | The wiki: it retells the Reference for people and is wrong when they disagree. ADRs: they explain why a decision was made |
|
|
47
|
-
| **showcase** | The kit's Storybook: stories, snapshots and accessibility checks; published to GitHub Pages | The documentation site: the showcase is a workshop, not text for a reader
|
|
47
|
+
| **showcase** | The kit's Storybook: stories, snapshots and accessibility checks; published to GitHub Pages | The documentation site: the showcase is a workshop, not text for a reader. The flyout of a mega menu |
|
|
48
48
|
| **snapshot** | A reference image of a showcase story in `tests-visual/`; taken and compared only locally (ADR-0013) | A screenshot for documentation: it checks nothing |
|
|
49
49
|
| **gate** | One automatic check that fails the run: the contrast gate (`npm run contrast`), the i18n gate, `format:check` | The release checklist: a gate is one check from its list |
|
|
50
50
|
| **release checklist** | The full list of checks before a merge and a release — the "Checks" section of `AGENTS.md`. Run locally: CI does not check pushes | A GitHub Actions workflow: it publishes the showcase and the package, but checks nothing |
|
|
@@ -108,27 +108,27 @@ The words pages use to describe how a component is operated with a mouse, a fing
|
|
|
108
108
|
How a component is named in prose. Do not use the words listed after "Do not write:": readers
|
|
109
109
|
search for a single word.
|
|
110
110
|
|
|
111
|
-
| Term | Meaning
|
|
112
|
-
| --------------------- |
|
|
113
|
-
| **dialog** | `Dialog`: a modal surface with a scrim
|
|
114
|
-
| **drawer** | `Drawer`: a modal panel that slides in from an edge
|
|
115
|
-
| **popover** | `Popover`: a non-modal panel next to the button that opened it
|
|
116
|
-
| **tooltip** | `Tooltip`: short text on hover and focus
|
|
117
|
-
| **hint** | `hint` on `FormField` and neighboring fields: text under the field that helps to fill it in
|
|
118
|
-
| **placeholder** | `placeholder`: an example value shown in an empty field that disappears on input
|
|
119
|
-
| **toast** | A global notification `toast()` in `Toaster`
|
|
120
|
-
| **checkbox** | `Checkbox`: a yes/no choice within a set
|
|
121
|
-
| **table bar** | The `toolbar` slot of `DataTable`, usually `TableToolbar`
|
|
122
|
-
| **menu trigger** | The button that opens a menu: the right part of `SplitButton`, the `Menu` button
|
|
123
|
-
| **segmented control** | `Segmented`: a row of buttons of which exactly one is selected
|
|
124
|
-
| **tag** | `Tag` in `TagGroup` and `TagInput`: a compact element with text and an optional remove button
|
|
125
|
-
| **close button** | The button with an "×" that closes a dialog, drawer, popover or notification; in a search field it is the **clear button**
|
|
126
|
-
| **shortcut list** | `ShortcutsHelp`: a dialog with a list of keyboard shortcuts
|
|
127
|
-
| **mega menu** | `MegaMenu`: a category column and the
|
|
128
|
-
| **category** | `MegaMenuCategory`: a row of the category column with a label, an icon and its own
|
|
129
|
-
| **category column** | The vertical list of categories in a mega menu
|
|
130
|
-
| **
|
|
131
|
-
| **aim** | Deferring the category switch while the pointer cuts diagonally toward the open
|
|
111
|
+
| Term | Meaning | Not to be confused with |
|
|
112
|
+
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
113
|
+
| **dialog** | `Dialog`: a modal surface with a scrim | A drawer. A browser window, which is simply called a "browser window". Do not write: modal |
|
|
114
|
+
| **drawer** | `Drawer`: a modal panel that slides in from an edge | A dialog. Do not write: sheet, slide-out panel |
|
|
115
|
+
| **popover** | `Popover`: a non-modal panel next to the button that opened it | A tooltip: it has no interactivity. Do not write: popup |
|
|
116
|
+
| **tooltip** | `Tooltip`: short text on hover and focus | A popover |
|
|
117
|
+
| **hint** | `hint` on `FormField` and neighboring fields: text under the field that helps to fill it in | A tooltip and a placeholder |
|
|
118
|
+
| **placeholder** | `placeholder`: an example value shown in an empty field that disappears on input | A hint and a tooltip |
|
|
119
|
+
| **toast** | A global notification `toast()` in `Toaster` | The Editor's Field notice: it is tied to a field |
|
|
120
|
+
| **checkbox** | `Checkbox`: a yes/no choice within a set | The `Toggle` switch (`role="switch"`): one boolean property, not a choice within a set |
|
|
121
|
+
| **table bar** | The `toolbar` slot of `DataTable`, usually `TableToolbar` | The Editor's Toolbar and the `Toolbar` primitive. Do not write: toolbar |
|
|
122
|
+
| **menu trigger** | The button that opens a menu: the right part of `SplitButton`, the `Menu` button | A popover: that is the panel that opened. Do not write: disclosure |
|
|
123
|
+
| **segmented control** | `Segmented`: a row of buttons of which exactly one is selected | `Tabs` (they switch panels) and `ToggleGroup` (zero or more selected) |
|
|
124
|
+
| **tag** | `Tag` in `TagGroup` and `TagInput`: a compact element with text and an optional remove button | The Editor's Mark and a field label |
|
|
125
|
+
| **close button** | The button with an "×" that closes a dialog, drawer, popover or notification; in a search field it is the **clear button** | A "Cancel" button. Do not write: cross |
|
|
126
|
+
| **shortcut list** | `ShortcutsHelp`: a dialog with a list of keyboard shortcuts | The Editor's Shortcuts reference: that one opens from the Toolbar and describes the Editor's shortcuts |
|
|
127
|
+
| **mega menu** | `MegaMenu`: a category column and the flyout of the hovered category, an Amazon-style catalog | `Menu`: that one is for commands, not navigation. Do not write: mega dropdown |
|
|
128
|
+
| **category** | `MegaMenuCategory`: a row of the category column with a label, an icon and its own flyout | A menu item (`MenuItem`) |
|
|
129
|
+
| **category column** | The vertical list of categories in a mega menu | `SideNav`: that one expands branches in place |
|
|
130
|
+
| **flyout** | The area next to the category column with the open category's content: link columns, promos. Before 4.3.0 it was called the showcase; the width prop is still `showcaseWidth` | The showcase: that is the kit's Storybook. The Editor toolbar, a popover |
|
|
131
|
+
| **aim** | Deferring the category switch while the pointer cuts diagonally toward the open flyout | An opening delay: aim never slows down a direct hover |
|
|
132
132
|
|
|
133
133
|
## Editor
|
|
134
134
|
|
package/docs/glossary.md
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
| Термин | Значение | Не путать с |
|
|
41
41
|
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
|
|
42
42
|
| **Справочник** | Markdown в `docs/` пакета: страницы компонентов, API и соглашения — источник правды о публичном контракте. Едет в пакете и показывается на сайте без правок | Вики: та пересказывает для людей и при расхождении неправа. ADR: те объясняют, почему так решено |
|
|
43
|
-
| **Витрина** | Storybook кита: истории, снимки и проверки доступности; публикуется на GitHub Pages | Сайтом документации: витрина — мастерская, а не текст для
|
|
43
|
+
| **Витрина** | Storybook кита: истории, снимки и проверки доступности; публикуется на GitHub Pages | Сайтом документации: витрина — мастерская, а не текст для читателя. Полкой мегаменю |
|
|
44
44
|
| **Снимок** | Эталонная картинка истории витрины в `tests-visual/`; снимается и сверяется только локально (ADR-0013) | Скриншотом для документации: он ничего не проверяет |
|
|
45
45
|
| **Гейт** | Одна автоматическая проверка, которая роняет прогон: гейт контраста (`npm run contrast`), гейт i18n, `format:check` | Воротами: гейт — одна проверка из их списка |
|
|
46
46
|
| **Ворота** | Полный список проверок перед слиянием и релизом — раздел «Checks» в `AGENTS.md`. Запускаются локально: CI пуши не проверяет | Воркфлоу GitHub Actions: те публикуют витрину и пакет, но не проверяет |
|
|
@@ -104,27 +104,27 @@
|
|
|
104
104
|
Как компонент называется по-русски в прозе. Слова после «Не пишем:» в тексте не употребляются: читатель
|
|
105
105
|
ищет по одному слову.
|
|
106
106
|
|
|
107
|
-
| Термин | Значение
|
|
108
|
-
| -------------------------- |
|
|
109
|
-
| **Окно** | `Dialog`: модальная поверхность с затемнением
|
|
110
|
-
| **Ящик** | `Drawer`: модальная панель, которая выезжает от края
|
|
111
|
-
| **Поповер** | `Popover`: немодальная панель у кнопки, которая её открыла
|
|
112
|
-
| **Подсказка** | `Tooltip`: короткий текст при наведении и фокусе
|
|
113
|
-
| **Пояснение** | `hint` у `FormField` и соседних полей: текст под полем, который помогает его заполнить
|
|
114
|
-
| **Плейсхолдер** | `placeholder`: пример значения, который виден в пустом поле и исчезает при вводе
|
|
115
|
-
| **Тост** | Глобальное уведомление `toast()` в `Toaster`
|
|
116
|
-
| **Флажок** | `Checkbox`: выбор «да / нет» в наборе
|
|
117
|
-
| **Полоса над таблицей** | Слот `toolbar` у `DataTable`, обычно `TableToolbar`
|
|
118
|
-
| **Раскрыватель** | Кнопка, которая раскрывает меню: правая часть `SplitButton`, кнопка `Menu`
|
|
119
|
-
| **Сегментированный выбор** | `Segmented`: ряд кнопок, из которых выбрана ровно одна
|
|
120
|
-
| **Тег** | `Tag` в `TagGroup` и `TagInput`: компактный элемент с текстом и необязательной кнопкой удаления
|
|
121
|
-
| **Кнопка закрытия** | Кнопка с иконкой «×», которая закрывает окно, ящик, поповер или уведомление; у поля поиска — **кнопка очистки**
|
|
122
|
-
| **Свод сочетаний** | `ShortcutsHelp`: окно со списком сочетаний клавиш
|
|
123
|
-
| **Мегаменю** | `MegaMenu`: Столбец категорий и
|
|
124
|
-
| **Категория** | `MegaMenuCategory`: строка Столбца с подписью, иконкой и своей
|
|
125
|
-
| **Столбец категорий** | Вертикальный список Категорий Мегаменю
|
|
126
|
-
|
|
|
127
|
-
| **Прицел** | Отложенная смена Категории, пока курсор идёт наискосок к открытой
|
|
107
|
+
| Термин | Значение | Не путать с |
|
|
108
|
+
| -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
|
109
|
+
| **Окно** | `Dialog`: модальная поверхность с затемнением | Ящиком. Окном браузера — его так и называем: «окно браузера». Не пишем: модалка |
|
|
110
|
+
| **Ящик** | `Drawer`: модальная панель, которая выезжает от края | Окном. Не пишем: шторка, выдвижная панель |
|
|
111
|
+
| **Поповер** | `Popover`: немодальная панель у кнопки, которая её открыла | Подсказкой: в той нет интерактива. Не пишем: попап |
|
|
112
|
+
| **Подсказка** | `Tooltip`: короткий текст при наведении и фокусе | Поповером. Не пишем: тултип |
|
|
113
|
+
| **Пояснение** | `hint` у `FormField` и соседних полей: текст под полем, который помогает его заполнить | Подсказкой (`Tooltip`) и плейсхолдером. Не пишем: подсказка поля |
|
|
114
|
+
| **Плейсхолдер** | `placeholder`: пример значения, который виден в пустом поле и исчезает при вводе | Пояснением и подсказкой. Не пишем: подсказка в поле |
|
|
115
|
+
| **Тост** | Глобальное уведомление `toast()` в `Toaster` | Сообщением поля Редактора: то привязано к полю |
|
|
116
|
+
| **Флажок** | `Checkbox`: выбор «да / нет» в наборе | Переключателем `Toggle` (`role="switch"`): одно булево свойство, а не выбор в наборе. Не пишем: чекбокс |
|
|
117
|
+
| **Полоса над таблицей** | Слот `toolbar` у `DataTable`, обычно `TableToolbar` | Панелью Редактора и примитивом `Toolbar`. Не пишем: тулбар |
|
|
118
|
+
| **Раскрыватель** | Кнопка, которая раскрывает меню: правая часть `SplitButton`, кнопка `Menu` | Поповером: тот — сама раскрывшаяся панель. Не пишем: disclosure, стрелка-меню |
|
|
119
|
+
| **Сегментированный выбор** | `Segmented`: ряд кнопок, из которых выбрана ровно одна | Вкладками `Tabs` (те переключают панели) и `ToggleGroup` (там выбрано ноль или несколько) |
|
|
120
|
+
| **Тег** | `Tag` в `TagGroup` и `TagInput`: компактный элемент с текстом и необязательной кнопкой удаления | Меткой Редактора (`Mark`) и подписью поля. Не пишем: таг |
|
|
121
|
+
| **Кнопка закрытия** | Кнопка с иконкой «×», которая закрывает окно, ящик, поповер или уведомление; у поля поиска — **кнопка очистки** | Кнопкой «Отмена». Не пишем: крестик |
|
|
122
|
+
| **Свод сочетаний** | `ShortcutsHelp`: окно со списком сочетаний клавиш | Справочником Редактора: тот открывается из Панели и описывает сочетания Редактора |
|
|
123
|
+
| **Мегаменю** | `MegaMenu`: Столбец категорий и Полка наведённой Категории — каталог в духе Amazon | `Menu`: тот для команд, а не для навигации. Не пишем: мега-дропдаун |
|
|
124
|
+
| **Категория** | `MegaMenuCategory`: строка Столбца с подписью, иконкой и своей Полкой | Пунктом меню (`MenuItem`) |
|
|
125
|
+
| **Столбец категорий** | Вертикальный список Категорий Мегаменю | `SideNav`: тот раскрывает ветки на месте |
|
|
126
|
+
| **Полка** | Область рядом со Столбцом с содержимым открытой Категории: колонки ссылок, промо. До 4.3.0 — «Витрина»; проп ширины по-прежнему `showcaseWidth` | Витриной — это Storybook кита; Панелью Редактора и поповером |
|
|
127
|
+
| **Прицел** | Отложенная смена Категории, пока курсор идёт наискосок к открытой Полке | Задержкой открытия: прямое наведение Прицел не тормозит |
|
|
128
128
|
|
|
129
129
|
## Редактор
|
|
130
130
|
|
package/llms.txt
CHANGED
|
@@ -108,7 +108,7 @@
|
|
|
108
108
|
- [Breadcrumbs](docs/components/navigation/breadcrumbs.md): `Breadcrumbs` показывает путь до текущей страницы.
|
|
109
109
|
- [Pagination](docs/components/navigation/pagination.md): `Pagination` — controlled pagination для уже разбитой на страницы коллекции.
|
|
110
110
|
- [Stepper](docs/components/navigation/stepper.md): `Stepper` показывает порядок шагов мастера; текущий индекс задаёт родитель (controlled).
|
|
111
|
-
- [MegaMenu](docs/components/navigation/mega-menu.md): `MegaMenu` — каталог магазина в духе Amazon: слева Столбец категорий, справа от наведённой Категории — её
|
|
111
|
+
- [MegaMenu](docs/components/navigation/mega-menu.md): `MegaMenu` — каталог магазина в духе Amazon: слева Столбец категорий, справа от наведённой Категории — её Полка с колонками ссылок и любым своим содержимым.
|
|
112
112
|
- [TreeView](docs/components/navigation/tree-view.md): Иерархия с раскрытием, выбором и клавиатурой на `Tree` из react-aria.
|
|
113
113
|
- [SelectionBar и useStickyOffset](docs/components/navigation/selection-bar.md): `SelectionBar` — полоса массовых действий: «Выбрано 12» и что с этим можно сделать.
|
|
114
114
|
- [ContextualSaveBar](docs/components/navigation/contextual-save-bar.md): Полоса несохранённых изменений: появляется с первой правкой формы, показывает «есть несохранённые изменения» (или их число) и две кнопки — сохранить и отменить.
|