Перейти к содержимому

Компоненты интерфейса и доработка

Интерфейс EpoCanvas Docs написан не с нуля, а построен на нативных компонентах Starlight с помощью точечного переопределения: сохранены каркас страниц и обработка контента Starlight, а отображаемые компоненты — верхняя панель, боковая панель, оглавление, поиск и т.д. — заменены, чтобы получить нужную трёхколоночную раскладку и поведение. На этой странице описана структура этой системы компонентов и способы её изменения.


Механизм переопределения компонентов

Starlight позволяет заменить любой нативный компонент собственной реализацией через поле components в astro.config.mjs. В этом проекте переопределено 7 компонентов:

// astro.config.mjs (фрагмент)
components: {
Header: './src/components/starlight/Header.astro',
Sidebar: './src/components/starlight/Sidebar.astro',
TableOfContents: './src/components/starlight/TableOfContents.astro',
PageTitle: './src/components/starlight/PageTitle.astro',
TwoColumnContent: './src/components/starlight/TwoColumnContent.astro',
Search: './src/components/starlight/Search.astro',
Pagination: './src/components/starlight/Pagination.astro',
},

При сборке для каждой позиции рендеринга страницы Starlight сначала использует файлы, указанные здесь. Непереопределённые компоненты (например, Footer в подвале или мобильное меню) продолжают использовать нативную реализацию.


Назначение семи кастомных компонентов

Весь исходный код находится в src/components/starlight/; их объём и назначение перечислены ниже:

Файл компонентаОбъёмНазначение
Header.astroоколо 646 строкВсё содержимое верхней панели: логотип, поле поиска, основная навигация, значок версии, переключатель языка, переключатель темы, ссылки на GitHub и Telegram
Search.astroоколо 837 строкПоиск с двумя режимами: поиск по странице в верхней панели (подсветка и счётчик) + всплывающее окно поиска по всему сайту на Ctrl+K (Pagefind UI)
Pagination.astroоколо 123 строкКарточки «Предыдущая / Следующая страница» внизу: плоская тонкая рамка, заголовок фирменного цвета, косые стрелки ↙/↘, указывающие направление перехода
TwoColumnContent.astroоколо 77 строкДвухколоночный каркас из основного текста и оглавления справа; управляет фиксированной шириной правой колонки и её прокруткой
TableOfContents.astroоколо 64 строкЗаголовок «Содержание страницы», значок и список оглавления; отфильтровывает заголовок самой страницы
PageTitle.astroоколо 62 строкКрупный заголовок страницы (берётся из title во Frontmatter) и отметка времени «последнее обновление»
Sidebar.astroоколо 22 строкТонкая обёртка: переиспользует нативный компонент Starlight SidebarPersister, благодаря чему позиция прокрутки боковой панели сохраняется при переходе между страницами

Поток данных: три конфигурационных файла управляют всем интерфейсом

Кастомные компоненты сами по себе не содержат бизнес-данных; содержимое интерфейса управляется тремя конфигурационными файлами:

astro.config.mjs ──→ массивы locales + sidebar ──→ Sidebar.astro рендерит каталог слева (для каждого языка берётся соответствующий перевод)
src/config/navigation.ts ──→ navigationConfig ──→ Header.astro рендерит верхнюю навигацию и подсветку (ссылки автоматически получают языковой префикс)
src/utils/i18n.ts ──→ словарь UI_TRANSLATIONS ──→ компоненты получают строки на текущем языке на этапе сборки
  • Каталог слева распознаёт только объявления sidebar из astro.config.mjs, и новые документы обязательно нужно регистрировать здесь; поле translations каждого пункта содержит тексты меню на 10 языках;
  • Верхняя навигация: отображаемый текст каждого пункта берётся из словаря i18n.ts по ключу labelKey, а функция match определяет, какая кнопка подсвечивается на текущей странице (перед сопоставлением языковой префикс удаляется);
  • Тексты интерфейса (плейсхолдер поля поиска, заголовок «Содержание страницы», подсказка переключателя темы и т.п.) каждый компонент выводит на нужном языке напрямую на этапе сборки через getTranslation(key, lang); скриптов подмены в рантайме на странице нет.

Иными словами: чтобы изменить содержимое интерфейса, сначала найдите соответствующий конфигурационный файл; исходный код компонентов нужно трогать только при изменении внешнего вида (отступов, цветов, значков).


Ключевые детали реализации компонентов

PageTitle: заголовок страницы и фактическое время обновления

Крупный заголовок страницы читается напрямую из title во Frontmatter, поэтому не пишите заголовок первого уровня # в самом тексте. Отметка времени «последнее обновление» берётся из истории коммитов Git на этапе сборки (в astro.config.mjs включён lastUpdated: true); она обновляется автоматически при каждом коммите и не требует ручного ведения.

Sidebar.astro занимает всего около 20 строк; главное — переиспользование официального компонента Starlight SidebarPersister: при переключении страниц DOM боковой панели не пересоздаётся, благодаря чему сохраняется позиция прокрутки. В этом и состоит принцип «непрыгающего» каталога слева при переходах между страницами.

TableOfContents: генерация содержания страницы

Данные оглавления Starlight генерирует на этапе сборки, разбирая заголовки в тексте (## и ###); компонент лишь отфильтровывает сам заголовок страницы и выполняет рендеринг. Подсветку при прокрутке выполняет в браузере пользовательский элемент starlight-toc, без использования каких-либо фреймворков.

TwoColumnContent: единственный источник ширины правой колонки

Ширина колонки оглавления справа зафиксирована на 20rem при @media (min-width: 72rem) (и 21rem на сверхшироких экранах от 90rem); максимальная ширина области основного текста соответственно уменьшается на ширину правой колонки. Чтобы изменить ширину правой колонки, правьте только этот файл — не переопределяйте её кусками в других таблицах стилей.

Header: навигация, тема и язык

  • Кнопки навигации рендерятся в цикле по navigationConfig; стиль активного состояния определяется значением, возвращаемым функцией match, а ссылки через localizedHref() автоматически получают префикс текущего языка;
  • Переключатель темы записывает ключ starlight-theme в LocalStorage; при загрузке страницы начальная тема выбирается в порядке «локальный выбор → системные настройки»;
  • Каждый пункт выпадающего списка языков — реальная ссылка на версию текущей страницы на соответствующем языке: клик сразу выполняет переход, дополнительного хранения состояния нет;
  • Оба значка справа в верхней панели — GitHub и Telegram — жёстко прописаны в src/components/starlight/Header.astro, поэтому адрес меняют правкой этого файла. Telegram указывает на страницу аккаунта @epocanvas, а всплывающая подсказка берётся из строки social.telegram. Запись social в astro.config.mjs управляет отдельной группой значков внизу боковой панели; они друг на друга не влияют.

Search: поиск в двух режимах

В одном компоненте реализованы две системы поиска (подробнее — в разделе Полнотекстовый поиск и горячие клавиши):

  1. Поиск по странице: поле в верхней панели; Enter перемещает между совпадениями на текущей странице, подсветка реализована скриптом, который расставляет отметки;
  2. Поиск по всему сайту: всплывающее окно <dialog> со стандартным интерфейсом Pagefind; индекс генерируется на этапе pnpm run build.

Pagination: карточки перехода между страницами

Данные «предыдущая / следующая страница» Starlight вычисляет на этапе сборки в соответствии с порядком sidebar (Astro.locals.starlightRoute.pagination); компонент только рендерит: две равные по ширине карточки, тонкая рамка без тени, заголовок фирменного цвета, косые стрелки ↙ / ↘ при наведении сдвигаются в направлении перехода. Стрелки представляют собой инлайновые SVG-пути, и если сайт используется на языке с письмом RTL, их направление зеркалится автоматически.


Важные замечания по доработке

  • Для изменения стилей в первую очередь используйте CSS-переменные: цвета, шрифты и размеры макета собраны в переменных :root в src/styles/custom.css, см. Конфигурация сайта и настройка стилей; большинство кастомизаций не требуют изменения компонентов;
  • Компоненты трогайте только при изменении поведения: добавляя кнопки или меняя структуру, получайте тексты интерфейса через getTranslation(key, lang) и дополняйте словарь в i18n.ts строками на всех 10 языках — для пропущенных языков будет использоваться резервный механизм с отображением на китайском;
  • После изменений обязательно проверяйте локально: pnpm run dev для проверки поведения, pnpm run build для подтверждения успешного прохождения проверки типов и сборки (локальные команды описаны в Частых вопросах и устранении неполадок).

Конкретные типовые операции по кастомизации смотрите прямо в Шпаргалке по типовым доработкам.