diff --git a/website/content/components/_meta.tsx b/website/content/components/_meta.tsx
index 88a17cfc48..7260d6a211 100644
--- a/website/content/components/_meta.tsx
+++ b/website/content/components/_meta.tsx
@@ -178,6 +178,21 @@ const meta: MetaRecord = {
'use-modal-manager': 'useModalManager',
'use-today-date': 'useTodayDate',
'visually-hidden': 'VisuallyHidden',
+
+ // Эти страницы нужны только для MCP, поэтому скрыты из навигации
+ '_partials': { display: 'hidden' },
+ 'action-sheet-item': { display: 'hidden' },
+ 'footer': { display: 'hidden' },
+ 'header': { display: 'hidden' },
+ 'list': { display: 'hidden' },
+ 'panel-header-button': { display: 'hidden' },
+ 'panel-header-content': { display: 'hidden' },
+ 'panel-spinner': { display: 'hidden' },
+ 'split-col': { display: 'hidden' },
+ 'subnavigation-button': { display: 'hidden' },
+ 'tabbar': { display: 'hidden' },
+ 'tabbar-item': { display: 'hidden' },
+ 'tabs-item': { display: 'hidden' },
};
export default meta;
diff --git a/website/content/components/_partials/action-sheet-item-content.mdx b/website/content/components/_partials/action-sheet-item-content.mdx
new file mode 100644
index 0000000000..3f3b7e7062
--- /dev/null
+++ b/website/content/components/_partials/action-sheet-item-content.mdx
@@ -0,0 +1,222 @@
+Подкомпонент для отображения элемента всплывающего меню [`ActionSheet`](/components/action-sheet). Каждому компоненту можно задать различные режимы отображения,
+добавлять иконки и метаданные.
+
+
+ ```jsx
+ Сохранить
+ ```
+
+
+### Цвет
+
+Задаётся свойством `mode`.
+
+#### `"default"`
+
+Стандартный цвет отображения текста, используется в действиях, где нет необходимости в привлечении дополнительного внимания.
+
+
+ ```jsx
+ Сохранить
+ ```
+
+
+#### `"destructive"`
+
+Цвет критических действий (чаще всего красный), старайтесь располагать такие действия сверху списка,
+где они наиболее заметны.
+
+
+ ```jsx
+ Удалить
+ ```
+
+
+#### ~`"cancel"`~
+
+> **@deprecated** Since 8.0.0. Значение `"cancel"` устарело и будет удалено в **VKUI v10**.
+> Используйте компонент [`ActionSheetDefaultIosCloseItem`](/components/action-sheet#action-sheet-default-ios-close-item) или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
+
+Цвет действия отмены.
+
+
+ ```jsx
+ Отмена
+ ```
+
+
+### ~Кнопка "Отмена"~
+
+> **@deprecated** Since 8.0.0. Свойство `isCancelItem` устарело и будет удалено в **VKUI v10**.
+> Используйте компонент [`ActionSheetDefaultIosCloseItem`](/components/action-sheet#action-sheet-default-ios-close-item) или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
+
+Свойство `isCancelItem` позволяет пометить пункт действия как "Отмена".
+
+Согласно рекомендациям **Apple** в `ActionSheet` должен быть вариант действия "Отмена", который
+бы позволял закрывать всплывающее окно без выполнения дополнительных действий.
+
+> Обратите внимание, что такой компонент необходимо передавать в свойство `iosCloseItem` у `ActionSheet`,
+> потому что данный компонент должен визуально отделяться от остальных пунктов.
+
+Подробнее с использованием можно ознакомиться на странице [`ActionSheet`](/components/action-sheet#cancel-item).
+
+### Текстовые элементы
+
+Основной контент компонента (заголовок) можно задать, передав в свойство `children` необходимый текст:
+
+
+ ```jsx
+ Скорость воспроизведения
+ ```
+
+
+Свойство `subtitle` позволяет отобразить дополнительный текст под заголовком:
+
+
+ ```jsx
+ Скорость воспроизведения
+ ```
+
+
+Свойство `meta` даёт возможность отобразить небольшой пояснительный текст или индикатор рядом с заголовком:
+
+
+ ```jsx
+ }>
+ Закрепить запись
+
+ ```
+
+
+#### Многострочный режим
+
+По умолчанию большое количество текста обрезается и заменяется на многоточие, поддерживая однострочный режим отображения.
+Это поведение можно отключить (_для всех текстовых элементов_) с помощью свойства `multiline`:
+
+
+ ```jsx
+
+ Очень длинный заголовок просто для примера, старайтесь избегать такого
+
+ ```
+
+
+### Контент в начале/в конце
+
+В компоненте доступна возможность добавления дополнительного контента слева и/или справа от текста,
+задаётся свойством `before` и `after` соответственно.
+Наиболее частый вариант использования свойств `before`/`after` - иконки или аватары.
+
+В соответствии с рекомендациями дизайн-системы, для десктопного представления (`compact`-режим) следует
+использовать иконки размером `20px`, для мобильного представления (`regular`-режим) — `28px`.
+Проще всего это сделать, используя компонент [`AdaptiveIconRenderer`](/components/adaptive-icon-renderer).
+
+
+ ```jsx
+
+ }
+ >
+ Редактировать профиль
+
+ ```
+
+
+### Состояния
+
+#### `disabled`
+
+Свойство позволяет отключить возможность взаимодействия с пунктом меню.
+
+
+ ```jsx
+
+ Субтитры
+
+ ```
+
+
+#### `selectable`
+
+Свойство даёт возможность выбирать элемент (визуальная и нативная имитация элемента радиокнопки).
+При использовании данного свойства вы также можете передавать стандартные свойства радиокнопок, для управления поведением:
+
+- `name` — имя группы для радиокнопок;
+- `value` — значение радиокнопки;
+- `defaultChecked` — установить выбранным по умолчанию;
+- `checked` и [`onChange`](#onchange) — для контролируемого извне использования выбранного значения;
+
+
+
+```jsx
+const [filter, setFilter] = useState('Нормальная');
+
+const onChange = (e) => {
+ // e.target.value будет равно значению, переданному в `value` выбранного компонента `ActionSheetItem`
+ setFilter(e.target.value);
+};
+
+return ['0.25x', '0.5x', '0.75x', 'Нормальная', '1.25x', '1.5x', '2x', '3x'].map((speed) => (
+
+ {speed}
+
+));
+```
+
+
+
+Дополнительно через свойство `iconChecked` есть возможность изменить иконки радиокнопки, которая рисуется по умолчанию.
+
+
+ ```jsx
+
+ }
+ >
+ 0.75x
+
+ ```
+
+
+### Обработчики событий
+
+#### `onClick`/ `onImmediateClick`
+
+Нажатие на пункт меню можно обработать с помощью свойств `onClick` и `onImmediateClick`.
+
+По умолчанию `onClick` будет вызван после завершения анимации скрытия всплывающего меню и после вызова `onClosed`.
+Из этого следует, что в объекте события значение поля `currentTarget` будет не определено.
+Если вам нужен объект события именно на момент нажатия, воспользуйтесь `onImmediateClick`.
+
+> По умолчанию клик на пункт меню автоматически вызывает закрытие всплывающего меню (функцию, переданную в `onClosed` у `ActionSheet`).
+>
+> Если такое поведение нежелательно, то используйте свойство `autoCloseDisabled`. В таком случае закрытие всплывающего окна
+> следует вызывать самостоятельно.
+
+#### `onChange`
+
+Если задано свойство `selectable={true}`, то выбор пункта следует обрабатывать с помощью свойства `onChange`.
+Пример можно увидеть [выше](#selectable).
+
+### Ссылки
+
+Если указать свойство `href`, компонент будет рендериться как ссылка ``.
+Также можно задать стандартное свойство `target`:
+
+```jsx
+
+ Перейти на vk.com
+
+```
diff --git a/website/content/components/_partials/footer-content.mdx b/website/content/components/_partials/footer-content.mdx
new file mode 100644
index 0000000000..d81c9983ef
--- /dev/null
+++ b/website/content/components/_partials/footer-content.mdx
@@ -0,0 +1,82 @@
+Подвал группы. Передаётся в конце `children`.
+
+{/* @example-description: Базовый подвал `Footer` для мета-информации группы. */}
+
+ ```jsx
+
+ ```
+
+
+### Доступность (a11y) [#a11y]
+
+#### Семантическая роль
+
+По умолчанию использует HTML-тег ``, дополнительно задаётся роль `role="contentinfo"` ([для поддержки Safari\<=13](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer#accessibility)).
+
+Предназначен для:
+
+- контактной информации;
+- ссылок на разделы сайта;
+- копирайта и юридических данных;
+- мета-информации о содержимом.
+
+#### Ключевые правила
+
+| Сценарий | Решение | Почему важно |
+| -------------------------- | ----------------------------- | ---------------------------------- |
+| Глобальный подвал страницы | Только один на страницу | Соответствие стандартам `WAI-ARIA` |
+| Несколько подвалов | Добавить `aria-label` каждому | Различение разделов скринридерами |
+| Декоративный элемент | `` | Избежать ложной семантики |
+
+#### Контекст использования
+
+В данном примере первый `Footer` "локальный", потому что находится внутри секционного контента (компонент `Group`)
+и содержит мета-информацию, а второй `Footer` - глобальный, потому что относится ко всей странице.
+
+{/* @example-description: Локальный и глобальный `Footer` в одном макете для разных контекстов. */}
+
+ ```jsx
+
+ Статьи}>
+ {}}>
+ Связь между употреблением шоколада и получением Нобелевской премии
+
+ {}}>Кошка как нелинейный элемент в квантовой системе
+ {}}>Алгоритм оптимального поедания пиццы
+ Теги: наука, исследования
+
+
+
+ ```
+
+
+#### Множество
+
+Несколько подвалов без контекста скринридеры воспринимают как дубли, чтобы этого избежать,
+добавляйте `aria-label` каждому компоненту:
+
+```jsx
+
+
+
+```
+
+#### Пользовательский тэг
+
+Используйте `Component="div"` если:
+
+- контент не соответствует семантике подвала;
+- элемент используется для визуального оформления;
+- уже есть глобальный подвал на странице.
+
+```jsx
+// Декоративный раздел
+Информация на данной странице является конфиденциальной.
+```
diff --git a/website/content/components/_partials/header-content.mdx b/website/content/components/_partials/header-content.mdx
new file mode 100644
index 0000000000..862b591436
--- /dev/null
+++ b/website/content/components/_partials/header-content.mdx
@@ -0,0 +1,69 @@
+import { BlockWrapper } from '@/components/wrappers';
+
+Заголовок группы. Передаётся либо в свойство `header`, либо в начале `children`, либо в `Group.Header`.
+
+{/* @example-description: Отдельный `Header` с индикатором и правым управляющим элементом. */}
+
+ ```jsx
+
+ ```
+
+
+### Рекомендуемые размеры иконок
+
+| Свойство | Расположение | Рекомендуемый размер |
+| ---------------- | ----------------------- | -------------------- |
+| `before` | Слева от всего контента | `28px` |
+| `beforeTitle` | Слева от заголовка | `16px` |
+| `afterTitle` | Справа от заголовка | `16px` |
+| `beforeSubtitle` | Слева от подзаголовка | `12px` |
+| `afterSubtitle` | Справа от подзаголовка | `12px` |
+
+### Дополнительные элементы
+
+- `indicator` — отображает счётчик/статус:
+
+ ```jsx
+
+ ```
+
+- `after` — контент справа от всего заголовка:
+
+ ```jsx
+ }>Настройки
+ ```
+
+### Пример использования
+
+{/* @example-description: Расширенный пример `Header` с иконками, подзаголовком, счетчиком и ссылкой. */}
+
+ ```jsx
+ }
+ beforeTitle={ }
+ afterTitle={ }
+ beforeSubtitle={ }
+ afterSubtitle={ }
+ subtitle="SOHN — Conrad"
+ subtitleComponent="h3"
+ indicator={
+
+ 3
+
+ }
+ after={ Показать все}
+ >
+ Плейлисты
+
+ }
+ >
+
+ Контент
+
+
+ ```
+
diff --git a/website/content/components/_partials/list-content.mdx b/website/content/components/_partials/list-content.mdx
new file mode 100644
index 0000000000..cc6ba70c8a
--- /dev/null
+++ b/website/content/components/_partials/list-content.mdx
@@ -0,0 +1,51 @@
+Специализированный контейнер для работы с компонентами ` | `.
+Обеспечивает правильное отображение и взаимодействие элементов.
+Также можно использовать как семантический контейнер для обычных `Cell`.
+
+{/* @example-description: Пример `List` с перетаскиваемыми элементами `Cell` и обновлением порядка. */}
+
+
+```jsx
+const [draggingList, updateDraggingList] = React.useState([
+ 'Say',
+ 'Hello',
+ 'To',
+ 'My',
+ 'Little',
+ 'Friend',
+]);
+
+const onDragFinish = ({ from, to }) => {
+ const _list = [...draggingList];
+ _list.splice(from, 1);
+ _list.splice(to, 0, draggingList[from]);
+ updateDraggingList(_list);
+};
+
+return (
+
+ {draggingList.map((item) => (
+ | } draggable onDragFinish={onDragFinish}>
+ {item}
+
+ ))}
+
+);
+```
+
+
+
+### Отступы между элементами
+
+Контролируется свойством `gap`:
+
+```jsx
+
+ | }>Профиль
+ | }>Настройки
+
+```
+
+### Доступность (a11y) [#list-a11y]
+
+- Автоматически добавляет `role="list"`.
diff --git a/website/content/components/_partials/panel-header-button-content.mdx b/website/content/components/_partials/panel-header-button-content.mdx
new file mode 100644
index 0000000000..389ef5d378
--- /dev/null
+++ b/website/content/components/_partials/panel-header-button-content.mdx
@@ -0,0 +1,88 @@
+Подкомпонент для отрисовки кнопки в шапке – передаётся в свойство `before` и/или `after` компонента [`PanelHeader`](/components/panel-header).
+
+{/* @example-description: Базовый `PanelHeaderButton` с иконкой действия в шапке. */}
+
+ ```jsx
+
+
+
+ ```
+
+
+### Контент
+
+В качестве содержимого компонента передавайте в свойство `children` либо [иконку](https://vkcom.github.io/icons/),
+либо текст. Текстовые кнопки чаще всего используются в iOS, но есть исключения для android.
+
+Обратите внимание, что для планшетов и десктопов рекомендуется использовать кнопки размером `24px`,
+а для мобильных устройств - размером `28px` (возможно, будет полезен [AdaptiveIconRenderer](/components/adaptive-icon-renderer)).
+
+Если нужно несколько кнопок в ряд, то используйте `React.Fragment`:
+
+{/* @example-description: Несколько кнопок в шапке с группировкой через `React.Fragment`. */}
+
+ ```jsx
+
+
+
+
+
+
+
+
+ ```
+
+
+### Пресеты
+
+#### PanelHeaderBack [#panel-header-back]
+
+Кнопка назад в экранах в рамках одного сценария ([`View`](/components/view)). Внутри инкапсулирована логика показа нужной иконки для платформы.
+Также можно передать свойство `label`, для отображения текста, который будет виден на платформах vkcom и iOS, но будет скрыт на Android.
+С помощью свойств `hideLabelOnVKCom` и `hideLabelOnIOS` можно также визуально скрыть `label` на соответствующих платформах, он будет виден только для скринридеров.
+
+{/* @example-description: Кнопка возврата `PanelHeaderBack` с платформенной иконкой. */}
+
+ ```jsx
+
+ ```
+
+
+#### PanelHeaderClose [#panel-header-close]
+
+Кнопка "Отмена" в модальных окнах для закрытия текущего [`View`](/components/view) в рамках [`View`](/components/root). На iOS будет
+показан текст, передаваемый как `label`, на Android и Desktop - ` ` или ` `. Если
+передать свойство `label`, то на Android и Desktop он будет скрыт, но виден для скринридеров.
+
+{/* @example-description: Кнопка закрытия `PanelHeaderClose` для модальных и навигационных сценариев. */}
+
+ ```jsx
+
+ ```
+
+
+#### PanelHeaderEdit [#panel-header-edit]
+
+Кнопка "Редактировать". Принимает свойство `isActive`, которое определяет состояние кнопки (включен ли режим редактирования).
+Для указания кастомных текстов для состояний можно использовать соответствующие свойства `doneLabel` и `editLabel`. Данные тексты
+будут видны на iOS, а на Android и Desktop они будет скрыты, но видны для скринридеров.
+
+{/* @example-description: Кнопка редактирования `PanelHeaderEdit` с переключаемым состоянием. */}
+
+ ```jsx
+
+ ```
+
+
+#### PanelHeaderSubmit [#panel-header-submit]
+
+Кнопка "Готово" в модальных окнах для закрытия текущего [`View`](/components/view) в рамках [`View`](/components/root) и сохранения
+какого-либо результата. На iOS будет показан текст, передаваемый как `label`, на Android и Desktop - ` `
+или ` `. Если передать свойство `label`, то на Android и Desktop текст будет скрыт, но виден для скринридеров.
+
+{/* @example-description: Кнопка подтверждения `PanelHeaderSubmit` для завершения действия. */}
+
+ ```jsx
+
+ ```
+
diff --git a/website/content/components/_partials/panel-header-content-content.mdx b/website/content/components/_partials/panel-header-content-content.mdx
new file mode 100644
index 0000000000..edd761cdb2
--- /dev/null
+++ b/website/content/components/_partials/panel-header-content-content.mdx
@@ -0,0 +1,41 @@
+Подкомпонент, предназначенный для создания сложного контента в [`PanelHeader`](/components/panel-header), включая добавление аватаров и подзаголовков.
+
+{/* @example-description: `PanelHeaderContent` с аватаром и подзаголовком в составе шапки. */}
+
+ ```jsx
+ }>
+ Жук Петрович
+
+ ```
+
+
+### Текстовые элементы
+
+#### Заголовок
+
+Текст заголовка следует передавать в свойство `children` данного компонента.
+
+#### Дополнительный контент заголовка
+
+В свойство `aside` можно передать дополнительный контент (чаще всего, иконку размером `12px`), который будет
+располагаться справа от заголовка.
+
+#### Подзаголовок
+
+Подзаголовок, располагающийся под заголовком, следует передавать в свойство `subtitle`.
+
+### Контент в начале
+
+В компоненте доступна возможность добавления дополнительного контента в начале через свойство `before`.
+Наиболее частый вариант использования свойства `before` - аватары (компонент `Avatar`).
+
+Следует руководствоваться следующими правилами:
+
+- на мобильных устройствах старайтесь использовать аватары размером `36px`;
+- на планшетах и десктопах аватары размером `32px`.
+
+### Обработчики событий
+
+Компонент позволяет обрабатывать нажатия через свойство `onClick`. В таком случае вся шапка становится кликабельным
+элементом (`role="button"`), поэтому старайтесь не вкладывать другие интерактивные элементы (кнопки, ссылки), чтобы
+не нарушать `a11y`.
diff --git a/website/content/components/_partials/panel-spinner-content.mdx b/website/content/components/_partials/panel-spinner-content.mdx
new file mode 100644
index 0000000000..935e07b5de
--- /dev/null
+++ b/website/content/components/_partials/panel-spinner-content.mdx
@@ -0,0 +1,46 @@
+import { FixedLayoutWrapper } from '@/components/wrappers';
+
+Индикатор загрузки внутри экрана. Автоматически добавляет стандартные отступы и центрирование.
+
+{/* @example-description: Использование `PanelSpinner` для индикации загрузки внутри панели. */}
+
+
+```jsx
+
+ PanelSpinner
+
+
+```
+
+
+
+### Свойства
+
+Наследует все свойства компонента [`Spinner`](/components/spinner).
+
+- `size` — размер индикатора.
+- `disableAnimation` — отключение анимации.
+- `noColor` — наследование цвета.
+
+#### Высота компонента
+
+Задается с помощью свойства `height`:
+
+```jsx
+
+```
+
+### Когда использовать
+
+- При загрузке контента внутри экрана.
+- Когда нужен центрированный спиннер с отступами.
+- Для полностраничной загрузки (в сочетании с кастомной высотой).
+
+### Альтернативы
+
+- [`Spinner`](/components/spinner) — для встроенной загрузки внутри элементов.
+- [`ScreenSpinner`](/components/screen-spinner) — для модальной загрузки поверх интерфейса.
+
+### Доступность (a11y) [#a11y]
+
+Следует придерживаться тех же правил, что и для компонента [`Spinner`](/components/spinner).
diff --git a/website/content/components/_partials/split-col-content.mdx b/website/content/components/_partials/split-col-content.mdx
new file mode 100644
index 0000000000..c21a793cc5
--- /dev/null
+++ b/website/content/components/_partials/split-col-content.mdx
@@ -0,0 +1,31 @@
+Подкомпонент для отрисовки колонки в многоколоночном интерфейсе.
+
+### Позиционирование
+
+Свойство `fixed` даёт возможность задать стиль `position: fixed` для колонки.
+Обычно используется для боковых колонок, не позволяя им прокручиваться с основным контентом и всегда оставаться в области видимости.
+
+- `true` — стиль применяется;
+- `false` — стиль не применяется.
+
+### Размеры
+
+С помощью свойств `width`, `minWidth` и `maxWidth` можно управлять шириной колонки. Принимаются либо числовое (в пикселях), либо
+строковое (токены или другие единицы измерения) значения.
+
+```jsx
+
+ {/* контент */}
+
+```
+
+Свойство `stretchedOnMobile` позволит колонке растягиваться на всю доступную ширину на устройствах шириной меньше `tablet`.
+
+### Отступы
+
+Свойство `autoSpaced` добавляет фиксированные боковые отступы колонке на устройствах с шириной больше `smallTablet`.
+
+### Анимации [#animation]
+
+Через свойство `animate` можно управлять включением/отключением анимаций при переходах во [`View`](/components/view). По умолчанию
+анимации при переходах включены только для мобильных устройств.
diff --git a/website/content/components/_partials/subnavigation-button-content.mdx b/website/content/components/_partials/subnavigation-button-content.mdx
new file mode 100644
index 0000000000..7b066ab03b
--- /dev/null
+++ b/website/content/components/_partials/subnavigation-button-content.mdx
@@ -0,0 +1,154 @@
+Кнопка/ссылка для использования внутри [`SubnavigationBar`](/components/subnavigation-bar). Предназначена для навигации между подразделами или управления
+контентом (активация фильтров, открытие модальных окон).
+
+{/* @example-description: Одиночная кнопка `SubnavigationButton` с иконкой в слоте `before`. */}
+
+ ```jsx
+ {}} before={ }>
+ Избранное
+
+ ```
+
+
+### Состояния
+
+`selected` — выделяет кнопку как активную. Используйте для индикации текущего раздела или применённого фильтра.
+
+{/* @example-description: Пример состояния `selected` у `SubnavigationButton` внутри панели навигации. */}
+
+ ```jsx
+
+ {}}>
+ Выбран
+
+ {}}>Не выбран
+
+ ```
+
+
+### Режимы отображения
+
+Задается свойством `mode`:
+
+- `primary` — первичный вид для привлечения внимания;
+- `outline` — вид с обводкой;
+- `tertiary` — третичный вид без фона.
+
+### Внешний вид
+
+Задается свойством `appearance`.
+
+#### `accent`
+
+{/* @example-description: Сравнение режимов `primary`, `outline` и `tertiary` в `appearance="accent"`. */}
+
+ ```jsx
+
+ {}}>
+ primary accent selected
+
+ {}}>
+ primary accent
+
+
+
+ {}}>
+ outline accent selected
+
+ {}}>
+ outline accent
+
+
+
+ {}}>
+ tertiary accent selected
+
+ {}}>
+ tertiary accent
+
+
+ ```
+
+
+#### `neutral`
+
+{/* @example-description: Сравнение режимов `primary`, `outline` и `tertiary` в `appearance="neutral"`. */}
+
+ ```jsx
+
+ {}}>
+ primary neutral selected
+
+ {}}>
+ primary neutral
+
+
+
+ {}}>
+ outline neutral selected
+
+ {}}>
+ outline neutral
+
+
+
+ {}}>
+ tertiary neutral selected
+
+ {}}>
+ tertiary neutral
+
+
+ ```
+
+
+### Размеры и контент
+
+Размер самой кнопки задается свойством `size`:
+
+- `s` — компактный;
+- `m` — стандартный;
+- `l` — увеличенный.
+
+`textLevel` — отдельно настраивает размер текста (1 — крупный, 3 — мелкий).
+Полезно в режиме `fixed` у родительского [`SubnavigationBar`](/components/subnavigation-bar).
+
+{/* @example-description: Пример размеров `SubnavigationButton` (`s`, `m`, `l`). */}
+
+ ```jsx
+ {}}>
+ size="s"
+
+ {}}>
+ size="m"
+
+ {}}>
+ size="l"
+
+ ```
+
+
+### Дополнительные элементы
+
+- `before` — иконка перед текстом (рекомендуемый размер `24px`).
+- `after` — счётчик или бейдж (рекомендуется использовать только `Counter size="s"` или `Badge`).
+- `chevron` — добавляет стрелку-индикатор справа.
+
+{/* @example-description: Кнопка с дополнительными элементами: `before`, `after` со счётчиком и `chevron`. */}
+
+ ```jsx
+ }
+ selected
+ chevron
+ after={
+
+ Применено: 3
+
+ }
+ onClick={() => {}}
+ >
+ Фильтры
+
+ ```
+
diff --git a/website/content/components/_partials/tabbar-content.mdx b/website/content/components/_partials/tabbar-content.mdx
new file mode 100644
index 0000000000..deca588b7e
--- /dev/null
+++ b/website/content/components/_partials/tabbar-content.mdx
@@ -0,0 +1,41 @@
+import { FixedLayoutWrapper } from '@/components/wrappers';
+
+Подкомпонент прибивает элементы навигации ([`TabbarItem`](#tabbar-item)) к низу экрана. Передаётся в свойство `tabbar` компонента [`Epic`](/components/epic).
+
+{/* @example-description: Базовый `Tabbar` с двумя пунктами и активным разделом. */}
+
+ ```jsx
+
+
+
+
+
+
+
+
+ ```
+
+
+### Выравнивание [#tabbar-align]
+
+В случае, если в `Tabbar` передан один или два элемента [`TabbarItem`](#tabbar-item), контент внутри этих элементов располагается
+по горизонтали, в остальных случаях контент располагается вертикально.
+
+С помощью свойства `mode` у `Tabbar` можно переопределить это поведение.
+
+- `"vertical"` — задаёт всегда вертикальное расположение;
+- `"horizontal"` — задаёт всегда горизонтальное расположение.
+
+{/* @example-description: Принудительное вертикальное выравнивание элементов `Tabbar` через `mode="vertical"`. */}
+
+ ```jsx
+
+
+
+
+
+
+
+
+ ```
+
diff --git a/website/content/components/_partials/tabbar-item-content.mdx b/website/content/components/_partials/tabbar-item-content.mdx
new file mode 100644
index 0000000000..7ad2842f44
--- /dev/null
+++ b/website/content/components/_partials/tabbar-item-content.mdx
@@ -0,0 +1,84 @@
+Подкомпонент позволяет создать навигационный элемент. Чаще всего представлен иконкой размером `28px`. Допускается использовать текст
+рядом с иконкой. Иконку необходимо передавать в свойство `children`, текст — в свойство `label`.
+
+{/* @example-description: Пример `TabbarItem` с иконкой и текстовой подписью. */}
+
+ ```jsx
+
+
+
+ ```
+
+
+Иконка и текст могут располагаться либо горизонтально, либо вертикально. Управлять этим поведением можно с помощью свойства `mode` у
+[`Tabbar`](/components/tabbar#tabbar-align).
+
+### Выбранное состояние
+
+Используйте свойство `selected`, чтобы показать текущий активный раздел.
+
+{/* @example-description: Выбранный `TabbarItem` с текстом для скринридера через `VisuallyHidden`. */}
+
+ ```jsx
+
+ {/* Данный текст будет озвучен скринридером */}
+ Профиль
+
+
+ ```
+
+
+### Индикатор
+
+С помощью свойства `indicator` можно задать для компонента счётчик или индикатор уведомления.
+Передавайте компоненты `Counter` с `size="s"` или `Badge`.
+
+{/* @example-description: `TabbarItem` с индикатором уведомления, переданным в свойство `indicator`. */}
+
+ ```jsx
+ }>
+ {/* Данный текст будет озвучен скринридером */}
+ Профиль
+
+
+ ```
+
+
+### Тэг компонента
+
+Через свойство `Component` можно переопределить тэг, который будет отрендерен компонентом (по умолчанию при
+передаче свойства `href` компонент использует тэг `a`, в иных случаях `button`);
+
+### Доступность (a11y) [#a11y]
+
+Если вы не передаете свойство `label`, то ассистивные технологии не смогут однозначно озвучить ваш элемент.
+В таком случае рекомендуется вместе с иконкой передавать в свойство `children` компонент `VisuallyHidden`
+с поясняющим текстом.
+
+```jsx
+import { Icon28UserCircleOutline } from '@vkontakte/icons';
+import { TabbarItem, VisuallyHidden } from '@vkontakte/vkui';
+
+
+ {/* Данный текст будет озвучен скринридером */}
+ Профиль
+
+ ;
+```
+
+В качестве альтернативного решение можно передать текст для скринридера в свойство `aria-label` или создать
+отдельный элемент с текстом и передать его `id` в свойство `aria-labelledby`.
+
+```jsx
+
+
+
+```
+
+```jsx
+Профиль
+
+
+
+
+```
diff --git a/website/content/components/_partials/tabs-item-content.mdx b/website/content/components/_partials/tabs-item-content.mdx
new file mode 100644
index 0000000000..6ae933fdcb
--- /dev/null
+++ b/website/content/components/_partials/tabs-item-content.mdx
@@ -0,0 +1,89 @@
+Элемент вкладки. Автоматически наследует режим отображения (`mode`) от родительского компонента [`Tabs`](/components/tabs).
+
+{/* @example-description: Базовый элемент вкладки `TabsItem`. */}
+
+ ```jsx
+ Фото
+ ```
+
+
+### Состояния
+
+#### `selected`
+
+Свойство `selected` помечает вкладку выбранной.
+
+{/* @example-description: Пример выбранной вкладки с `selected`. */}
+
+ ```jsx
+ Фото
+ ```
+
+
+#### `disabled`
+
+Свойство `disabled` блокирует взаимодействие с компонентом и добавляет визуальную индикацию недоступности.
+
+{/* @example-description: Пример недоступной вкладки с `disabled`. */}
+
+ ```jsx
+ Фото
+ ```
+
+
+### Дополнительный контент
+
+Компонент поддерживает различные варианты оформления вкладок:
+
+#### Иконки
+
+- `before` — иконка перед текстом:
+ - Для `mode="default"` используйте иконки `24px`;
+ - Для других режимов (`accent`, `secondary`) — иконки `20px`.
+- `after` — иконка после текста (например, ` `).
+
+{/* @example-description: Вкладка с дополнительным контентом в слотах `before` и `after`. */}
+
+ ```jsx
+ } after={ }>
+ Фото
+
+ ```
+
+
+#### Статус
+
+Свойство `status` — добавляет элемент для отображения состояния:
+
+- `React.ReactElement` — компонент `Badge` или `Counter` (с `size="s"`).
+- `number` — отображает текстовый блок с числом.
+
+{/* @example-description: Вкладка со статусом через `Counter` в свойстве `status`. */}
+
+ ```jsx
+
+ 12
+
+ }
+ >
+ Фото
+
+ ```
+
+
+### Состояния взаимодействия
+
+Компонент поддерживает все стандартные состояния из [`Tappable`](/components/tappable):
+
+- `hoverMode` — стиль при наведении;
+- `activeMode` — стиль при активации;
+- `focusVisibleMode` — стиль при фокусе.
+
+### Особенности использования
+
+1. Всегда используйте `TabsItem` внутри компонента [`Tabs`](/components/tabs).
+2. Для корректной работы доступности (a11y) необходимо:
+ - Указать `id` для вкладки
+ - Связать с контентом через `aria-controls` (см. документацию [`Tabs`](/components/tabs))
diff --git a/website/content/components/action-sheet-item.mdx b/website/content/components/action-sheet-item.mdx
new file mode 100644
index 0000000000..0d1b36831e
--- /dev/null
+++ b/website/content/components/action-sheet-item.mdx
@@ -0,0 +1,24 @@
+---
+description: Элемент списка действий для использования внутри ActionSheet.
+---
+
+
+
+# ActionSheetItem [tag:component]
+
+Элемент списка действий для использования внутри [`ActionSheet`](/components/action-sheet).
+Поддерживает иконки, подзаголовки, режим выбора и деструктивные действия.
+
+
+
+import ActionSheetItemContent from './_partials/action-sheet-item-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### ActionSheetItem [#action-sheet-item-api]
+
+
diff --git a/website/content/components/action-sheet.mdx b/website/content/components/action-sheet.mdx
index 8157d42e45..684ca6ea57 100644
--- a/website/content/components/action-sheet.mdx
+++ b/website/content/components/action-sheet.mdx
@@ -206,228 +206,9 @@ import { ActionSheet, ActionSheetDefaultIosCloseItem } from '@vkontakte/vkui';
## ActionSheetItem [#action-sheet-item]
-Подкомпонент для отображения элемента всплывающего меню. Каждому компоненту можно задать различные режимы отображения,
-добавлять иконки и метаданные.
+import ActionSheetItemContent from './_partials/action-sheet-item-content.mdx';
-
- ```jsx
- Сохранить
- ```
-
-
-### Цвет
-
-Задаётся свойством `mode`.
-
-#### `"default"`
-
-Стандартный цвет отображения текста, используется в действиях, где нет необходимости в привлечении дополнительного внимания.
-
-
- ```jsx
- Сохранить
- ```
-
-
-#### `"destructive"`
-
-Цвет критических действий (чаще всего красный), старайтесь располагать такие действия сверху списка,
-где они наиболее заметны.
-
-
- ```jsx
- Удалить
- ```
-
-
-#### ~`"cancel"`~
-
-> **@deprecated** Since 8.0.0. Значение `"cancel"` устарело и будет удалено в **VKUI v10**.
-> Используйте компонент [`ActionSheetDefaultIosCloseItem`](#action-sheet-default-ios-close-item) или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
-
-Цвет действия отмены.
-
-
- ```jsx
- Отмена
- ```
-
-
-### ~Кнопка "Отмена"~
-
-> **@deprecated** Since 8.0.0. Свойство `isCancelItem` устарело и будет удалено в **VKUI v10**.
-> Используйте компонент [`ActionSheetDefaultIosCloseItem`](#action-sheet-default-ios-close-item) или передайте пропсы через `slotProps.iosCloseItem` в `ActionSheet`.
-
-Свойство `isCancelItem` позволяет пометить пункт действия как "Отмена".
-
-Согласно рекомендациям **Apple** в `ActionSheet` должен быть вариант действия "Отмена", который
-бы позволял закрывать всплывающее окно без выполнения дополнительных действий.
-
-> Обратите внимание, что такой компонент необходимо передавать в свойство `iosCloseItem` у `ActionSheet`,
-> потому что данный компонент должен визуально отделяться от остальных пунктов.
-
-Подробнее с использованием можно ознакомиться на странице [`ActionSheet`](/components/action-sheet#cancel-item).
-
-### Текстовые элементы
-
-Основной контент компонента (заголовок) можно задать, передав в свойство `children` необходимый текст:
-
-
- ```jsx
- Скорость воспроизведения
- ```
-
-
-Свойство `subtitle` позволяет отобразить дополнительный текст под заголовком:
-
-
- ```jsx
- Скорость воспроизведения
- ```
-
-
-Свойство `meta` даёт возможность отобразить небольшой пояснительный текст или индикатор рядом с заголовком:
-
-
- ```jsx
- }>
- Закрепить запись
-
- ```
-
-
-#### Многострочный режим
-
-По умолчанию большое количество текста обрезается и заменяется на многоточие, поддерживая однострочный режим отображения.
-Это поведение можно отключить (_для всех текстовых элементов_) с помощью свойства `multiline`:
-
-
- ```jsx
-
- Очень длинный заголовок просто для примера, старайтесь избегать такого
-
- ```
-
-
-### Контент в начале/в конце
-
-В компоненте доступна возможность добавления дополнительного контента слева и/или справа от текста,
-задаётся свойством `before` и `after` соответственно.
-Наиболее частый вариант использования свойств `before`/`after` - иконки или аватары.
-
-В соответствии с рекомендациями дизайн-системы, для десктопного представления (`compact`-режим) следует
-использовать иконки размером `20px`, для мобильного представления (`regular`-режим) — `28px`.
-Проще всего это сделать, используя компонент [`AdaptiveIconRenderer`](/components/adaptive-icon-renderer).
-
-
- ```jsx
-
- }
- >
- Редактировать профиль
-
- ```
-
-
-### Состояния
-
-#### `disabled`
-
-Свойство позволяет отключить возможность взаимодействия с пунктом меню.
-
-
- ```jsx
-
- Субтитры
-
- ```
-
-
-#### `selectable`
-
-Свойство даёт возможность выбирать элемент (визуальная и нативная имитация элемента радиокнопки).
-При использовании данного свойства вы также можете передавать стандартные свойства радиокнопок, для управления поведением:
-
-- `name` — имя группы для радиокнопок;
-- `value` — значение радиокнопки;
-- `defaultChecked` — установить выбранным по умолчанию;
-- `checked` и [`onChange`](#onchange) — для контролируемого извне использования выбранного значения;
-
-
-
-```jsx
-const [filter, setFilter] = useState('Нормальная');
-
-const onChange = (e) => {
- // e.target.value будет равно значению, переданному в `value` выбранного компонента `ActionSheetItem`
- setFilter(e.target.value);
-};
-
-return ['0.25x', '0.5x', '0.75x', 'Нормальная', '1.25x', '1.5x', '2x', '3x'].map((speed) => (
-
- {speed}
-
-));
-```
-
-
-
-Дополнительно через свойство `iconChecked` есть возможность изменить иконки радиокнопки, которая рисуется по умолчанию.
-
-
- ```jsx
-
- }
- >
- 0.75x
-
- ```
-
-
-### Обработчики событий
-
-#### `onClick`/ `onImmediateClick`
-
-Нажатие на пункт меню можно обработать с помощью свойств `onClick` и `onImmediateClick`.
-
-По умолчанию `onClick` будет вызван после завершения анимации скрытия всплывающего меню и после вызова `onClosed`.
-Из этого следует, что в объекте события значение поля `currentTarget` будет не определено.
-Если вам нужен объект события именно на момент нажатия, воспользуйтесь `onImmediateClick`.
-
-> По умолчанию клик на пункт меню автоматически вызывает закрытие всплывающего меню (функцию, переданную в `onClosed` у `ActionSheet`).
->
-> Если такое поведение нежелательно, то используйте свойство `autoCloseDisabled`. В таком случае закрытие всплывающего окна
-> следует вызывать самостоятельно.
-
-#### `onChange`
-
-Если задано свойство `selectable={true}`, то выбор пункта следует обрабатывать с помощью свойства `onChange`.
-Пример можно увидеть [выше](#selectable).
-
-### Ссылки
-
-Если указать свойство `href`, компонент будет рендериться как ссылка ``.
-Также можно задать стандартное свойство `target`:
-
-```jsx
-
- Перейти на vk.com
-
-```
+
## Доступность (a11y) [#a11y]
diff --git a/website/content/components/cell.mdx b/website/content/components/cell.mdx
index 6611092126..566fb743e6 100644
--- a/website/content/components/cell.mdx
+++ b/website/content/components/cell.mdx
@@ -93,57 +93,9 @@ description: Расширенная версия SimpleCell с поддержк
## List [#list] [tag:component]
-Специализированный контейнер для работы с компонентами ` | `.
-Обеспечивает правильное отображение и взаимодействие элементов.
-Также можно использовать как семантический контейнер для обычных `Cell`.
-
-{/* @example-description: Пример `List` с перетаскиваемыми элементами `Cell` и обновлением порядка. */}
-
-
-```jsx
-const [draggingList, updateDraggingList] = React.useState([
- 'Say',
- 'Hello',
- 'To',
- 'My',
- 'Little',
- 'Friend',
-]);
-
-const onDragFinish = ({ from, to }) => {
- const _list = [...draggingList];
- _list.splice(from, 1);
- _list.splice(to, 0, draggingList[from]);
- updateDraggingList(_list);
-};
-
-return (
-
- {draggingList.map((item) => (
- | } draggable onDragFinish={onDragFinish}>
- {item}
-
- ))}
-
-);
-```
+import ListContent from './_partials/list-content.mdx';
-
-
-### Отступы между элементами
-
-Контролируется свойством `gap`:
-
-```jsx
-
- | }>Профиль
- | }>Настройки
-
-```
-
-### Доступность (a11y) [#list-a11y]
-
-- Автоматически добавляет `role="list"`.
+
## Свойства и методы [#api]
diff --git a/website/content/components/epic.mdx b/website/content/components/epic.mdx
index 359ac8ea75..fb6b72d45f 100644
--- a/website/content/components/epic.mdx
+++ b/website/content/components/epic.mdx
@@ -15,6 +15,8 @@ description: Компонент, реализующий интерфейс с ц
+import { FixedLayoutWrapper } from '@/components/wrappers';
+
{/* @example-description: Базовая навигация через `Epic` с двумя историями и нижним `Tabbar`. */}
@@ -89,134 +91,15 @@ Epic
## Tabbar
-Подкомпонент прибивает элементы навигации ([`TabbarItem`](#tabbar-item)) к низу экрана. Передаётся в свойство `tabbar` компонента `Epic`.
-
-import { FixedLayoutWrapper } from '@/components/wrappers';
-
-{/* @example-description: Базовый `Tabbar` с двумя пунктами и активным разделом. */}
-
- ```jsx
-
-
-
-
-
-
-
-
- ```
-
-
-### Выравнивание [#tabbar-align]
-
-В случае, если в `Tabbar` передан один или два элемента [`TabbarItem`](#tabbar-item), контент внутри этих элементов располагается
-по горизонтали, в остальных случаях контент располагается вертикально.
+import TabbarContent from './_partials/tabbar-content.mdx';
-С помощью свойства `mode` у `Tabbar` можно переопределить это поведение.
-
-- `"vertical"` — задаёт всегда вертикальное расположение;
-- `"horizontal"` — задаёт всегда горизонтальное расположение.
-
-{/* @example-description: Принудительное вертикальное выравнивание элементов `Tabbar` через `mode="vertical"`. */}
-
- ```jsx
-
-
-
-
-
-
-
-
- ```
-
+
## TabbarItem [#tabbar-item]
-Подкомпонент позволяет создать навигационный элемент. Чаще всего представлен иконкой размером `28px`. Допускается использовать текст
-рядом с иконкой. Иконку необходимо передавать в свойство `children`, текст — в свойство `label`.
-
-{/* @example-description: Пример `TabbarItem` с иконкой и текстовой подписью. */}
-
- ```jsx
-
-
-
- ```
-
-
-Иконка и текст могут располагаться либо горизонтально, либо вертикально. Управлять этим поведением можно с помощью свойства `mode` у
-[`Tabbar`](#tabbar-align).
-
-### Выбранное состояние
-
-Используйте свойство `selected`, чтобы показать текущий активный раздел.
-
-{/* @example-description: Выбранный `TabbarItem` с текстом для скринридера через `VisuallyHidden`. */}
-
- ```jsx
-
- {/* Данный текст будет озвучен скринридером */}
- Профиль
-
-
- ```
-
-
-### Индикатор
+import TabbarItemContent from './_partials/tabbar-item-content.mdx';
-С помощью свойства `indicator` можно задать для компонента счётчик или индикатор уведомления.
-Передавайте компоненты `Counter` с `size="s"` или `Badge`.
-
-{/* @example-description: `TabbarItem` с индикатором уведомления, переданным в свойство `indicator`. */}
-
- ```jsx
- }>
- {/* Данный текст будет озвучен скринридером */}
- Профиль
-
-
- ```
-
-
-### Тэг компонента
-
-Через свойство `Component` можно переопределить тэг, который будет отрендерен компонентом (по умолчанию при
-передаче свойства `href` компонент использует тэг `a`, в иных случаях `button`);
-
-### Доступность (a11y) [#a11y]
-
-Если вы не передаете свойство `label`, то ассистивные технологии не смогут однозначно озвучить ваш элемент.
-В таком случае рекомендуется вместе с иконкой передавать в свойство `children` компонент `VisuallyHidden`
-с поясняющим текстом.
-
-```jsx
-import { Icon28UserCircleOutline } from '@vkontakte/icons';
-import { TabbarItem, VisuallyHidden } from '@vkontakte/vkui';
-
-
- {/* Данный текст будет озвучен скринридером */}
- Профиль
-
- ;
-```
-
-В качестве альтернативного решение можно передать текст для скринридера в свойство `aria-label` или создать
-отдельный элемент с текстом и передать его `id` в свойство `aria-labelledby`.
-
-```jsx
-
-
-
-```
-
-```jsx
-Профиль
-
-
-
-
-```
+
## Адаптивность
diff --git a/website/content/components/footer.mdx b/website/content/components/footer.mdx
new file mode 100644
index 0000000000..b862eee7e6
--- /dev/null
+++ b/website/content/components/footer.mdx
@@ -0,0 +1,23 @@
+---
+description: Подвал группы, передаётся в конце children компонента Group.
+---
+
+
+
+# Footer [tag:component]
+
+Подвал для компонента [`Group`](/components/group). Передаётся в конце `children`.
+
+
+
+import FooterContent from './_partials/footer-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### Footer [#footer-api]
+
+
diff --git a/website/content/components/group.mdx b/website/content/components/group.mdx
index c30634e112..c31782cc64 100644
--- a/website/content/components/group.mdx
+++ b/website/content/components/group.mdx
@@ -61,158 +61,15 @@ description: Компонент для визуальной группировк
## Header [tag:component]
-Заголовок группы. Передаётся либо в свойство `header`, либо в начале `children`, либо в `Group.Header`.
+import HeaderContent from './_partials/header-content.mdx';
-{/* @example-description: Отдельный `Header` с индикатором и правым управляющим элементом. */}
-
- ```jsx
-
- ```
-
-
-### Рекомендуемые размеры иконок
-
-| Свойство | Расположение | Рекомендуемый размер |
-| ---------------- | ----------------------- | -------------------- |
-| `before` | Слева от всего контента | `28px` |
-| `beforeTitle` | Слева от заголовка | `16px` |
-| `afterTitle` | Справа от заголовка | `16px` |
-| `beforeSubtitle` | Слева от подзаголовка | `12px` |
-| `afterSubtitle` | Справа от подзаголовка | `12px` |
-
-### Дополнительные элементы
-
-- `indicator` — отображает счётчик/статус:
-
- ```jsx
-
- ```
-
-- `after` — контент справа от всего заголовка:
-
- ```jsx
- }>Настройки
- ```
-
-### Пример использования
-
-{/* @example-description: Расширенный пример `Header` с иконками, подзаголовком, счетчиком и ссылкой. */}
-
- ```jsx
- }
- beforeTitle={ }
- afterTitle={ }
- beforeSubtitle={ }
- afterSubtitle={ }
- subtitle="SOHN — Conrad"
- subtitleComponent="h3"
- indicator={
-
- 3
-
- }
- after={ Показать все}
- >
- Плейлисты
-
- }
- >
-
- Контент
-
-
- ```
-
+
## Footer [tag:component]
-Подвал группы. Передаётся в конце `children`.
-
-{/* @example-description: Базовый подвал `Footer` для мета-информации группы. */}
-
- ```jsx
-
- ```
-
-
-### Доступность (a11y) [#a11y]
-
-#### Семантическая роль
-
-По умолчанию использует HTML-тег ``, дополнительно задаётся роль `role="contentinfo"` ([для поддержки Safari\<=13](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/footer#accessibility)).
-
-Предназначен для:
-
-- контактной информации;
-- ссылок на разделы сайта;
-- копирайта и юридических данных;
-- мета-информации о содержимом.
-
-#### Ключевые правила
-
-| Сценарий | Решение | Почему важно |
-| -------------------------- | ----------------------------- | ---------------------------------- |
-| Глобальный подвал страницы | Только один на страницу | Соответствие стандартам `WAI-ARIA` |
-| Несколько подвалов | Добавить `aria-label` каждому | Различение разделов скринридерами |
-| Декоративный элемент | `` | Избежать ложной семантики |
-
-#### Контекст использования
-
-В данном примере первый `Footer` "локальный", потому что находится внутри секционного контента (компонент `Group`)
-и содержит мета-информацию, а второй `Footer` - глобальный, потому что относится ко всей странице.
-
-{/* @example-description: Локальный и глобальный `Footer` в одном макете для разных контекстов. */}
-
- ```jsx
-
- Статьи}>
- {}}>
- Связь между употреблением шоколада и получением Нобелевской премии
-
- {}}>Кошка как нелинейный элемент в квантовой системе
- {}}>Алгоритм оптимального поедания пиццы
- Теги: наука, исследования
-
-
-
- ```
-
-
-#### Множество
-
-Несколько подвалов без контекста скринридеры воспринимают как дубли, чтобы этого избежать,
-добавляйте `aria-label` каждому компоненту:
-
-```jsx
-
-
-
-```
-
-#### Пользовательский тэг
-
-Используйте `Component="div"` если:
-
-- контент не соответствует семантике подвала;
-- элемент используется для визуального оформления;
-- уже есть глобальный подвал на странице.
+import FooterContent from './_partials/footer-content.mdx';
-```jsx
-// Декоративный раздел
-Информация на данной странице является конфиденциальной.
-```
+
## Group.ExpandedContent [#group-expanded-content] [tag:component]
diff --git a/website/content/components/header.mdx b/website/content/components/header.mdx
new file mode 100644
index 0000000000..7291c3f677
--- /dev/null
+++ b/website/content/components/header.mdx
@@ -0,0 +1,23 @@
+---
+description: Заголовок группы, передаётся в свойство header компонента Group.
+---
+
+
+
+# Header [tag:component]
+
+Заголовок для компонента [`Group`](/components/group). Передаётся в свойство `header`, в начале `children`, либо через `Group.Header`.
+
+
+
+import HeaderContent from './_partials/header-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### Header [#header-api]
+
+
diff --git a/website/content/components/list.mdx b/website/content/components/list.mdx
new file mode 100644
index 0000000000..0c2f16797a
--- /dev/null
+++ b/website/content/components/list.mdx
@@ -0,0 +1,25 @@
+---
+description: Специализированный контейнер для работы с перетаскиваемыми и интерактивными Cell.
+---
+
+
+
+# List [tag:component]
+
+Специализированный контейнер для работы с компонентами [`Cell`](/components/cell).
+Обеспечивает правильное отображение и взаимодействие перетаскиваемых элементов.
+Также можно использовать как семантический контейнер для обычных `Cell`.
+
+
+
+import ListContent from './_partials/list-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### List [#list-api]
+
+
diff --git a/website/content/components/panel-header-button.mdx b/website/content/components/panel-header-button.mdx
new file mode 100644
index 0000000000..9061f393e5
--- /dev/null
+++ b/website/content/components/panel-header-button.mdx
@@ -0,0 +1,31 @@
+---
+description: Кнопка для шапки PanelHeader, передаётся в свойства before и after.
+---
+
+
+
+# PanelHeaderButton [tag:component]
+
+Кнопка для шапки [`PanelHeader`](/components/panel-header). Передаётся в свойства `before` и/или `after`.
+
+
+
+import PanelHeaderButtonContent from './_partials/panel-header-button-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### PanelHeaderButton [#panel-header-button-api]
+
+### PanelHeaderBack [#panel-header-back-api]
+
+### PanelHeaderClose [#panel-header-close-api]
+
+### PanelHeaderEdit [#panel-header-edit-api]
+
+### PanelHeaderSubmit [#panel-header-submit-api]
+
+
diff --git a/website/content/components/panel-header-content.mdx b/website/content/components/panel-header-content.mdx
new file mode 100644
index 0000000000..1be58c1c61
--- /dev/null
+++ b/website/content/components/panel-header-content.mdx
@@ -0,0 +1,23 @@
+---
+description: Подкомпонент PanelHeader для сложного контента с аватаром и подзаголовком.
+---
+
+
+
+# PanelHeaderContent [tag:component]
+
+Подкомпонент [`PanelHeader`](/components/panel-header), предназначенный для создания сложного заголовка с аватаром и подзаголовком.
+
+
+
+import PanelHeaderContentContent from './_partials/panel-header-content-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### PanelHeaderContent [#panel-header-content-api]
+
+
diff --git a/website/content/components/panel-header.mdx b/website/content/components/panel-header.mdx
index 8f89233080..9b4819eb5e 100644
--- a/website/content/components/panel-header.mdx
+++ b/website/content/components/panel-header.mdx
@@ -123,138 +123,15 @@ import { FixedLayoutWrapper } from '@/components/wrappers';
## PanelHeaderButton [#panel-header-button] [tag:component]
-Подкомпонент для отрисовки кнопки в шапке – передаётся в свойство `before` и/или `after`.
+import PanelHeaderButtonContent from './_partials/panel-header-button-content.mdx';
-{/* @example-description: Базовый `PanelHeaderButton` с иконкой действия в шапке. */}
-
- ```jsx
-
-
-
- ```
-
-
-### Контент
-
-В качестве содержимого компонента передавайте в свойство `children` либо [иконку](https://vkcom.github.io/icons/),
-либо текст. Текстовые кнопки чаще всего используются в iOS, но есть исключения для android.
-
-Обратите внимание, что для планшетов и десктопов рекомендуется использовать кнопки размером `24px`,
-а для мобильных устройств - размером `28px` (возможно, будет полезен [AdaptiveIconRenderer](/components/adaptive-icon-renderer)).
-
-Если нужно несколько кнопок в ряд, то используйте `React.Fragment`:
-
-{/* @example-description: Несколько кнопок в шапке с группировкой через `React.Fragment`. */}
-
- ```jsx
-
-
-
-
-
-
-
-
- ```
-
-
-### Пресеты
-
-#### PanelHeaderBack [#panel-header-back]
-
-Кнопка назад в экранах в рамках одного сценария ([`View`](/components/view)). Внутри инкапсулирована логика показа нужной иконки для платформы.
-Также можно передать свойство `label`, для отображения текста, который будет виден на платформах vkcom и iOS, но будет скрыт на Android.
-С помощью свойств `hideLabelOnVKCom` и `hideLabelOnIOS` можно также визуально скрыть `label` на соответствующих платформах, он будет виден только для скринридеров.
-
-{/* @example-description: Кнопка возврата `PanelHeaderBack` с платформенной иконкой. */}
-
- ```jsx
-
- ```
-
-
-#### PanelHeaderClose [#panel-header-close]
-
-Кнопка "Отмена" в модальных окнах для закрытия текущего [`View`](/components/view) в рамках [`View`](/components/root). На iOS будет
-показан текст, передаваемый как `label`, на Android и Desktop - ` ` или ` `. Если
-передать свойство `label`, то на Android и Desktop он будет скрыт, но виден для скринридеров.
-
-{/* @example-description: Кнопка закрытия `PanelHeaderClose` для модальных и навигационных сценариев. */}
-
- ```jsx
-
- ```
-
-
-#### PanelHeaderEdit [#panel-header-edit]
-
-Кнопка "Редактировать". Принимает свойство `isActive`, которое определяет состояние кнопки (включен ли режим редактирования).
-Для указания кастомных текстов для состояний можно использовать соответствующие свойства `doneLabel` и `editLabel`. Данные тексты
-будут видны на iOS, а на Android и Desktop они будет скрыты, но видны для скринридеров.
-
-{/* @example-description: Кнопка редактирования `PanelHeaderEdit` с переключаемым состоянием. */}
-
- ```jsx
-
- ```
-
-
-#### PanelHeaderSubmit [#panel-header-submit]
-
-Кнопка "Готово" в модальных окнах для закрытия текущего [`View`](/components/view) в рамках [`View`](/components/root) и сохранения
-какого-либо результата. На iOS будет показан текст, передаваемый как `label`, на Android и Desktop - ` `
-или ` `. Если передать свойство `label`, то на Android и Desktop текст будет скрыт, но виден для скринридеров.
-
-{/* @example-description: Кнопка подтверждения `PanelHeaderSubmit` для завершения действия. */}
-
- ```jsx
-
- ```
-
+
## PanelHeaderContent [#panel-header-content] [tag:component]
-Подкомпонент, предназначенный для создания сложного контента, включая добавление аватаров и подзаголовков.
-
-{/* @example-description: `PanelHeaderContent` с аватаром и подзаголовком в составе шапки. */}
-
- ```jsx
- }>
- Жук Петрович
-
- ```
-
-
-### Текстовые элементы
-
-#### Заголовок
-
-Текст заголовка следует передавать в свойство `children` данного компонента.
-
-#### Дополнительный контент заголовка
-
-В свойство `aside` можно передать дополнительный контент (чаще всего, иконку размером `12px`), который будет
-располагаться справа от заголовка.
-
-#### Подзаголовок
-
-Подзаголовок, располагающийся под заголовком, следует передавать в свойство `subtitle`.
-
-### Контент в начале
-
-В компоненте доступна возможность добавления дополнительного контента в начале через свойство `before`.
-Наиболее частый вариант использования свойства `before` - аватары (компонент `Avatar`).
-
-Следует руководствоваться следующими правилами:
-
-- на мобильных устройствах старайтесь использовать аватары размером `36px`;
-- на планшетах и десктопах аватары размером `32px`.
-
-### Обработчики событий
+import PanelHeaderContentContent from './_partials/panel-header-content-content.mdx';
-Компонент позволяет обрабатывать нажатия через свойство `onClick`. В таком случае вся шапка становится кликабельным
-элементом (`role="button"`), поэтому старайтесь не вкладывать другие интерактивные элементы (кнопки, ссылки), чтобы
-не нарушать `a11y`.
+
## Свойства и методы [#api]
diff --git a/website/content/components/panel-spinner.mdx b/website/content/components/panel-spinner.mdx
new file mode 100644
index 0000000000..8f6d67afd5
--- /dev/null
+++ b/website/content/components/panel-spinner.mdx
@@ -0,0 +1,23 @@
+---
+description: Индикатор загрузки внутри Panel с автоматическими отступами и центрированием.
+---
+
+
+
+# PanelSpinner [tag:component]
+
+Индикатор загрузки внутри [`Panel`](/components/panel). Автоматически добавляет стандартные отступы и центрирование.
+
+
+
+import PanelSpinnerContent from './_partials/panel-spinner-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### PanelSpinner [#panel-spinner-api]
+
+
diff --git a/website/content/components/panel.mdx b/website/content/components/panel.mdx
index 2f0cfe051d..3adbf8d3ef 100644
--- a/website/content/components/panel.mdx
+++ b/website/content/components/panel.mdx
@@ -81,50 +81,9 @@ import { FixedLayoutWrapper } from '@/components/wrappers';
## PanelSpinner [tag:component]
-Индикатора загрузки внутри экрана. Автоматически добавляет стандартные отступы и центрирование.
+import PanelSpinnerContent from './_partials/panel-spinner-content.mdx';
-{/* @example-description: Использование `PanelSpinner` для индикации загрузки внутри панели. */}
-
-
-```jsx
-
- PanelSpinner
-
-
-```
-
-
-
-### Свойства
-
-Наследует все свойства компонента [`Spinner`](/components/spinner).
-
-- `size` — размер индикатора.
-- `disableAnimation` — отключение анимации.
-- `noColor` — наследование цвета.
-
-#### Высота компонента
-
-Задается с помощью свойства `height`:
-
-```jsx
-
-```
-
-### Когда использовать
-
-- При загрузке контента внутри экрана.
-- Когда нужен центрированный спиннер с отступами.
-- Для полностраничной загрузки (в сочетании с кастомной высотой).
-
-### Альтернативы
-
-- [`Spinner`](/components/spinner) — для встроенной загрузки внутри элементов.
-- [`ScreenSpinner`](/components/screen-spinner) — для модальной загрузки поверх интерфейса.
-
-### Доступность (a11y) [#a11y]
-
-Следует придерживаться тех же правил, что и для компонента [`Spinner`](/components/spinner).
+
## Свойства и методы [#api]
diff --git a/website/content/components/split-col.mdx b/website/content/components/split-col.mdx
new file mode 100644
index 0000000000..1ed3459c3e
--- /dev/null
+++ b/website/content/components/split-col.mdx
@@ -0,0 +1,23 @@
+---
+description: Подкомпонент SplitLayout для отрисовки колонки в многоколоночном интерфейсе.
+---
+
+
+
+# SplitCol [tag:component]
+
+Подкомпонент [`SplitLayout`](/components/split-layout) для отрисовки колонки в многоколоночном интерфейсе.
+
+
+
+import SplitColContent from './_partials/split-col-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### SplitCol [#split-col-api]
+
+
diff --git a/website/content/components/split-layout.mdx b/website/content/components/split-layout.mdx
index b1a5a9e95e..d47a4c3ba9 100644
--- a/website/content/components/split-layout.mdx
+++ b/website/content/components/split-layout.mdx
@@ -197,37 +197,9 @@ return (
## SplitCol [#split-col] [tag:component]
-Подкомпонент для отрисовки колонки в многоколоночном интерфейсе.
+import SplitColContent from './_partials/split-col-content.mdx';
-### Позиционирование
-
-Свойство `fixed` даёт возможность задать стиль `position: fixed` для колонки.
-Обычно используется для боковых колонок, не позволяя им прокручиваться с основным контентом и всегда оставаться в области видимости.
-
-- `true` — стиль применяется;
-- `false` — стиль не применяется.
-
-### Размеры
-
-С помощью свойств `width`, `minWidth` и `maxWidth` можно управлять шириной колонки. Принимаются либо числовое (в пикселях), либо
-строковое (токены или другие единицы измерения) значения.
-
-```jsx
-
- {/* контент */}
-
-```
-
-Свойство `stretchedOnMobile` позволит колонке растягиваться на всю доступную ширину на устройствах шириной меньше `tablet`.
-
-### Отступы
-
-Свойство `autoSpaced` добавляет фиксированные боковые отступы колонке на устройствах с шириной больше `smallTablet`.
-
-### Анимации [#animation]
-
-Через свойство `animate` можно управлять включением/отключением анимаций при переходах во [`View`](/components/view). По умолчанию
-анимации при переходах включены только для мобильных устройств.
+
## Свойства и методы [#api]
diff --git a/website/content/components/subnavigation-bar.mdx b/website/content/components/subnavigation-bar.mdx
index eb5ebf6510..f79be3bfa3 100644
--- a/website/content/components/subnavigation-bar.mdx
+++ b/website/content/components/subnavigation-bar.mdx
@@ -59,160 +59,9 @@ import { BlockWrapper } from '@/components/wrappers';
## SubnavigationButton [#subnavigation-button] [tag:component]
-Кнопка/ссылка для использования внутри `SubnavigationBar`. Предназначена для навигации между подразделами или управления
-контентом (активация фильтров, открытие модальных окон).
+import SubnavigationButtonContent from './_partials/subnavigation-button-content.mdx';
-{/* @example-description: Одиночная кнопка `SubnavigationButton` с иконкой в слоте `before`. */}
-
- ```jsx
- {}} before={ }>
- Избранное
-
- ```
-
-
-### Состояния
-
-`selected` — выделяет кнопку как активную. Используйте для индикации текущего раздела или применённого фильтра.
-
-{/* @example-description: Пример состояния `selected` у `SubnavigationButton` внутри панели навигации. */}
-
- ```jsx
-
- {}}>
- Выбран
-
- {}}>Не выбран
-
- ```
-
-
-### Режимы отображения
-
-Задается свойством `mode`:
-
-- `primary` — первичный вид для привлечения внимания;
-- `outline` — вид с обводкой;
-- `tertiary` — третичный вид без фона.
-
-### Внешний вид
-
-Задается свойством `appearance`.
-
-#### `accent`
-
-{/* @example-description: Сравнение режимов `primary`, `outline` и `tertiary` в `appearance="accent"`. */}
-
- ```jsx
-
- {}}>
- primary accent selected
-
- {}}>
- primary accent
-
-
-
- {}}>
- outline accent selected
-
- {}}>
- outline accent
-
-
-
- {}}>
- tertiary accent selected
-
- {}}>
- tertiary accent
-
-
- ```
-
-
-#### `neutral`
-
-{/* @example-description: Сравнение режимов `primary`, `outline` и `tertiary` в `appearance="neutral"`. */}
-
- ```jsx
-
- {}}>
- primary neutral selected
-
- {}}>
- primary neutral
-
-
-
- {}}>
- outline neutral selected
-
- {}}>
- outline neutral
-
-
-
- {}}>
- tertiary neutral selected
-
- {}}>
- tertiary neutral
-
-
- ```
-
-
-### Размеры и контент
-
-Размер самой кнопки задается свойством `size`:
-
-- `s` — компактный;
-- `m` — стандартный;
-- `l` — увеличенный.
-
-`textLevel` — отдельно настраивает размер текста (1 — крупный, 3 — мелкий).
-Полезно в режиме `fixed` у родительского `SubnavigationBar`.
-
-{/* @example-description: Пример размеров `SubnavigationButton` (`s`, `m`, `l`). */}
-
- ```jsx
- {}}>
- size="s"
-
- {}}>
- size="m"
-
- {}}>
- size="l"
-
- ```
-
-
-### Дополнительные элементы
-
-- `before` — иконка перед текстом (рекомендуемый размер `24px`).
-- `after` — счётчик или бейдж (рекомендуется использовать только `Counter size="s"` или `Badge`).
-- `chevron` — добавляет стрелку-индикатор справа.
-
-{/* @example-description: Кнопка с дополнительными элементами: `before`, `after` со счётчиком и `chevron`. */}
-
- ```jsx
- }
- selected
- chevron
- after={
-
- Применено: 3
-
- }
- onClick={() => {}}
- >
- Фильтры
-
- ```
-
+
## Свойства и методы [#api]
diff --git a/website/content/components/subnavigation-button.mdx b/website/content/components/subnavigation-button.mdx
new file mode 100644
index 0000000000..f9684b0bcf
--- /dev/null
+++ b/website/content/components/subnavigation-button.mdx
@@ -0,0 +1,23 @@
+---
+description: Кнопка для использования внутри SubnavigationBar — навигация, фильтры, модальные окна.
+---
+
+
+
+# SubnavigationButton [tag:component]
+
+Кнопка/ссылка для использования внутри [`SubnavigationBar`](/components/subnavigation-bar). Предназначена для навигации между подразделами или управления контентом (активация фильтров, открытие модальных окон).
+
+
+
+import SubnavigationButtonContent from './_partials/subnavigation-button-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### SubnavigationButton [#subnavigation-button-api]
+
+
diff --git a/website/content/components/tabbar-item.mdx b/website/content/components/tabbar-item.mdx
new file mode 100644
index 0000000000..09892fc562
--- /dev/null
+++ b/website/content/components/tabbar-item.mdx
@@ -0,0 +1,24 @@
+---
+description: Навигационный элемент для использования внутри Tabbar.
+---
+
+
+
+# TabbarItem [tag:component]
+
+Навигационный элемент для использования внутри [`Tabbar`](/components/tabbar).
+Чаще всего представлен иконкой размером `28px` с подписью в свойстве `label`.
+
+
+
+import TabbarItemContent from './_partials/tabbar-item-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### TabbarItem [#tabbar-item-api]
+
+
diff --git a/website/content/components/tabbar.mdx b/website/content/components/tabbar.mdx
new file mode 100644
index 0000000000..d7a9e6c0b2
--- /dev/null
+++ b/website/content/components/tabbar.mdx
@@ -0,0 +1,23 @@
+---
+description: Панель навигации, закреплённая в нижней части экрана, для использования в Epic.
+---
+
+
+
+# Tabbar [tag:component]
+
+Панель навигации, закреплённая в нижней части экрана. Передаётся в свойство `tabbar` компонента [`Epic`](/components/epic).
+
+
+
+import TabbarContent from './_partials/tabbar-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### Tabbar [#tabbar-api]
+
+
diff --git a/website/content/components/tabs-item.mdx b/website/content/components/tabs-item.mdx
new file mode 100644
index 0000000000..60ff4b0158
--- /dev/null
+++ b/website/content/components/tabs-item.mdx
@@ -0,0 +1,23 @@
+---
+description: Элемент вкладки для использования внутри Tabs.
+---
+
+
+
+# TabsItem [tag:component]
+
+Элемент вкладки для использования внутри [`Tabs`](/components/tabs). Автоматически наследует режим отображения (`mode`) от родительского компонента.
+
+
+
+import TabsItemContent from './_partials/tabs-item-content.mdx';
+
+
+
+## Свойства и методы [#api]
+
+
+
+### TabsItem [#tabs-item-api]
+
+
diff --git a/website/content/components/tabs.mdx b/website/content/components/tabs.mdx
index 0ac8645b0f..2f1becefaf 100644
--- a/website/content/components/tabs.mdx
+++ b/website/content/components/tabs.mdx
@@ -121,95 +121,9 @@ const [selected, setSelected] = React.useState('news');
## TabsItem [#tabs-item] [tag:component]
-Элемент вкладки. Автоматически наследует режим отображения (`mode`) от родительского компонента `Tabs`.
+import TabsItemContent from './_partials/tabs-item-content.mdx';
-{/* @example-description: Базовый элемент вкладки `TabsItem`. */}
-
- ```jsx
- Фото
- ```
-
-
-### Состояния
-
-#### `selected`
-
-Свойство `selected` помечает вкладку выбранной.
-
-{/* @example-description: Пример выбранной вкладки с `selected`. */}
-
- ```jsx
- Фото
- ```
-
-
-#### `disabled`
-
-Свойство `disabled` блокирует взаимодействие с компонентом и добавляет визуальную индикацию недоступности.
-
-{/* @example-description: Пример недоступной вкладки с `disabled`. */}
-
- ```jsx
- Фото
- ```
-
-
-### Дополнительный контент
-
-Компонент поддерживает различные варианты оформления вкладок:
-
-#### Иконки
-
-- `before` — иконка перед текстом:
- - Для `mode="default"` используйте иконки `24px`;
- - Для других режимов (`accent`, `secondary`) — иконки `20px`.
-- `after` — иконка после текста (например, ` `).
-
-{/* @example-description: Вкладка с дополнительным контентом в слотах `before` и `after`. */}
-
- ```jsx
- } after={ }>
- Фото
-
- ```
-
-
-#### Статус
-
-Свойство `status` — добавляет элемент для отображения состояния:
-
-- `React.ReactElement` — компонент `Badge` или `Counter` (с `size="s"`).
-- `number` — отображает текстовый блок с числом.
-
-{/* @example-description: Вкладка со статусом через `Counter` в свойстве `status`. */}
-
- ```jsx
-
- 12
-
- }
- >
- Фото
-
- ```
-
-
-### Состояния взаимодействия
-
-Компонент поддерживает все стандартные состояния из [`Tappable`](/components/tappable):
-
-- `hoverMode` — стиль при наведении;
-- `activeMode` — стиль при активации;
-- `focusVisibleMode` — стиль при фокусе.
-
-### Особенности использования
-
-1. Всегда используйте `TabsItem` внутри компонента `Tabs`.
-2. Для корректной работы доступности (a11y) необходимо:
- - Указать `id` для вкладки
- - Связать с контентом через `aria-controls` (см. документацию [`Tabs`](/components/tabs))
+
## Доступность (a11y) [#a11y]
diff --git a/website/scripts/generate-mcp-data.mjs b/website/scripts/generate-mcp-data.mjs
index 57643d71ce..6f36160319 100644
--- a/website/scripts/generate-mcp-data.mjs
+++ b/website/scripts/generate-mcp-data.mjs
@@ -1,6 +1,7 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
+import { resolvePartials } from './resolvePartials.mjs';
const SCRIPT_FILE = fileURLToPath(import.meta.url);
const SCRIPT_DIR = path.dirname(SCRIPT_FILE);
@@ -34,6 +35,7 @@ function collectMdxFiles(dirPath) {
const results = [];
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
for (const entry of entries) {
+ if (entry.name === '_partials') continue;
const fullPath = path.join(dirPath, entry.name);
if (entry.isDirectory()) {
results.push(...collectMdxFiles(fullPath));
@@ -197,7 +199,8 @@ export function generateMcpData() {
const itemName = isHook(slug) ? hookKeyFromSlug(slug) : componentNameFromSlug(slug);
const description = data.description || '';
const props = docgen[itemName] || [];
- const playgroundExamples = extractPlaygroundExamples(body);
+ const resolvedBody = resolvePartials(body, filePath);
+ const playgroundExamples = extractPlaygroundExamples(resolvedBody);
const listItem = {
name: itemName,
diff --git a/website/scripts/resolvePartials.mjs b/website/scripts/resolvePartials.mjs
new file mode 100644
index 0000000000..96a0d8533a
--- /dev/null
+++ b/website/scripts/resolvePartials.mjs
@@ -0,0 +1,55 @@
+import fs from 'fs';
+import path from 'path';
+
+/**
+ * Находит в body все `import Foo from './path.mdx'`, читает содержимое файла
+ * и подставляет его вместо ` `. Работает рекурсивно — партиалы сами
+ * могут импортировать другие партиалы.
+ *
+ * @param {string} body - тело MDX-файла
+ * @param {string} filePath - абсолютный путь к исходному MDX-файлу (нужен для резолва относительных импортов)
+ * @returns {string} body с раскрытыми партиалами
+ */
+export function resolvePartials(body, filePath) {
+ const dir = path.dirname(filePath);
+
+ // import Foo from './something.mdx' (с кавычками или без точки с запятой)
+ const importRegex = /^import\s+(\w+)\s+from\s+['"]([^'"]+\.mdx)['"]\s*;?\s*$/gm;
+
+ const partials = new Map();
+ const importLinesToRemove = new Set();
+
+ let match;
+ while ((match = importRegex.exec(body)) !== null) {
+ const [fullImportLine, componentName, importRelPath] = match;
+ const fullPath = path.resolve(dir, importRelPath);
+
+ if (!fs.existsSync(fullPath)) {
+ continue;
+ }
+
+ const partialRaw = fs.readFileSync(fullPath, 'utf8');
+ const partialResolved = resolvePartials(partialRaw, fullPath);
+ partials.set(componentName, partialResolved.trim());
+ importLinesToRemove.add(fullImportLine);
+ }
+
+ if (partials.size === 0) {
+ return body;
+ }
+
+ let result = body;
+
+ for (const importLine of importLinesToRemove) {
+ result = result.replace(importLine, '');
+ }
+
+ for (const [componentName, content] of partials) {
+ const tagRegex = new RegExp(`<${componentName}\\s*/>`, 'g');
+ result = result.replace(tagRegex, content);
+ }
+
+ result = result.replace(/\n{3,}/g, '\n\n');
+
+ return result;
+}