Техническая документация
Дизайн-система, реестры и правила разработки
Раздел для разработки и подрядчиков. Описание проекта простым языком — в «Как устроен проект». Живая витрина компонентов — дизайн-система.
Реестры на этой странице рендерятся из тех же данных, что и сайт. Добавили тему в src/data/moods.ts — она появилась здесь сама; переписывать таблицы руками не нужно и нельзя.
Содержание
Дизайн-система
Компонент не использует сырых значений — только токены. Значения ниже собраны из src/styles/tokens/*.css; таблица-источник — docs/design/TOKENS.md.
Цвет — сырые шкалы
| Токен | Значение | Токен | Значение |
|---|---|---|---|
--c-brand-950 | #050F26 | --c-ice-0 | #FFFFFF |
--c-brand-900 | #081B3F | --c-ice-50 | #F8FAFF |
--c-brand-800 | #0E2A63 | --c-ice-100 | #EFF3FB |
--c-brand-700 | #14357F | --c-ice-200 | #E1E9F5 |
--c-brand-600 | #1E40AF | --c-ice-300 | #C9D6E8 |
--c-brand-500 | #2563EB | --c-ice-400 | #9DAFC7 |
--c-brand-400 | #3B82F6 | --c-ice-500 | #6D7F98 |
--c-brand-300 | #7DA9FF | --c-ice-600 | #4A5A73 |
--c-brand-200 | #B4CCFF | --c-ice-700 | #2E3D54 |
--c-brand-100 | #DCE7FF | --c-ice-800 | #1A2537 |
--c-brand-50 | #F1F6FF | --c-ice-900 | #0C1421 |
| Токен | Значение |
|---|---|
--c-gold-600 | #A8801F |
--c-gold-500 | #C9A84C |
--c-gold-400 | #DCC077 |
--c-gold-300 | #EBD9A6 |
--c-live | #E11D48 |
--c-success | #0FA968 |
--c-warning | #E8A33D |
--c-danger | #DC2626 |
Семантика
Компоненты работают только с ней. Тёмная тема — атрибут секции (<section data-theme="dark">), а не переключатель пользователя: атом внутри тёмной секции перекрашивается сам.
| Токен | Образец |
|---|---|
--color-bg | #F8FAFF· var(--c-ice-50) |
--color-bg-subtle | #EFF3FB· var(--c-ice-100) |
--color-surface | #FFFFFF· var(--c-ice-0) |
--color-surface-2 | #F8FAFF· var(--c-ice-50) |
--color-text | #0C1421· var(--c-ice-900) |
--color-text-muted | #4A5A73· var(--c-ice-600) |
--color-border | #C9D6E8· var(--c-ice-300) |
--color-accent | #1E40AF· var(--c-brand-600) |
--color-accent-hover | #14357F· var(--c-brand-700) |
--color-accent-soft | #F1F6FF· var(--c-brand-50) |
--color-focus | #3B82F6· var(--c-brand-400) |
--color-gold | #C9A84C· var(--c-gold-500) |
Типографика
| Роль | Размер |
|---|---|
| display-1 | clamp(2.75rem, 1.2rem + 6.4vw, 6.5rem) |
| display-2 | clamp(2.25rem, 1.3rem + 4.2vw, 4rem) |
| h1 | clamp(2rem, 1.35rem + 2.6vw, 3rem) |
| h2 | clamp(1.6rem, 1.25rem + 1.6vw, 2.25rem) |
| h3 | clamp(1.25rem, 1.1rem + 0.8vw, 1.5rem) |
| lead | clamp(1.06rem, 1rem + 0.4vw, 1.25rem) |
| body | 1rem |
| sm | 0.875rem |
| label | 0.75rem / tracking .08em |
Пространство, радиусы, тени, слои
| Шаг |
|---|
1 · 4px |
2 · 8px |
3 · 12px |
4 · 16px |
5 · 24px |
6 · 32px |
7 · 48px |
8 · 64px |
9 · 96px |
10 · 128px |
| Радиус | Токен |
|---|---|
--r-xs | |
--r-sm | |
--r-md | |
--r-lg | |
--r-xl | |
--r-full |
| Тень | Токен |
|---|---|
--shadow-1 | |
--shadow-2 | |
--shadow-3 | |
--glow-accent | |
--glow-gold |
| Слой |
|---|
--z-base · 0 |
--z-sticky · 100 |
--z-header · 200 |
--z-dropdown · 300 |
--z-overlay · 400 |
--z-modal · 500 |
--z-toast · 600 |
Движение
| Длительность | Значение |
|---|---|
--dur-instant | 120ms |
--dur-fast | 200ms |
--dur-base | 320ms |
--dur-slow | 520ms |
--dur-cine | 820ms |
| Кривая | Значение |
|---|---|
--ease-standard | cubic-bezier(.2,.6,.2,1) |
--ease-enter | cubic-bezier(0,.7,.2,1) |
--ease-exit | cubic-bezier(.4,0,1,1) |
--ease-spring | cubic-bezier(.34,1.56,.64,1) |
Поверхности и стекло
Стекло видно только там, где под ним есть что размывать. На светлом фоне backdrop-filter не ловит ничего, и карточка растворяется в секции. Поэтому стекло — только поверх изображения или тёмного фона (шапка над героем, подписи поверх кадра, панель над схемой регионов), а на светлых секциях — плотная поверхность --surface-1 с ледяной гранью --edge-highlight. Наглядно — в разделе «Материалы» витрины дизайн-системы.
Ритм секций и ледяной излом
Границы между секциями — не черта и не полоса, а полигональный излом: два слоя треугольных граней с разными углами, плоская заливка без градиентов внутри грани и обязательная пара «блик / глубина». Слой заезжает под контент соседних секций, поэтому граница блоков исчезает и страница читается единым массивом. Геометрия генерируется из seed (src/data/facets.ts), руками правятся только seed и палитра: полигоны, забитые в разметку, никто потом не осмелится трогать.
Тона секций и приёмы лежат в src/data/transitions.ts, а правила (излом только между светлым и тёмным, изломов не больше трёх плюс одно поле поперёк секции, не больше двух тёмных секций подряд, фактура только на светлой) проверяет scripts/test/transitions.test.mjs — нарушение роняет тест, а не всплывает на приёмке.
С 20.08 граней на главной нет ни одной: владелец забраковал приём как слишком грубый. Стык рисует мягкое растворение — градиент из фона верхней секции в фон нижней, тона берутся из того же реестра. Пять кандидатов на замену стоят рядом в лаборатории /lab/transitions/; колонка «приём» в реестре осталась описанием и ждёт выбора владельца.
| Секция | Тон | Фактура | Приём в реестре |
|---|---|---|---|
| Герой | dark | — | — |
| Новости | light | — | ледяной излом · seed 17 |
| Календарь | light-2 | glow | растворение |
| Специалистам | light | — | растворение |
| Сборная | light-2 | — | растворение |
| Дисциплины | dark | — | ледяной излом · seed 43 |
| Представительства | dark-2 | — | растворение |
| Медиа | light-2 | grain | ледяной излом · seed 91 |
| Партнёры | light | — | растворение |
Событийные темы
Сайт реагирует на события, а не на человека: время суток, праздник, идущий старт. Профилирования и трекеров нет — контекст одинаков для всех, кто зашёл в эту минуту.
Активно не более одного настроения одновременно — с наибольшим приоритетом среди подходящих. Суточный слой (data-daypart) действует всегда и меняет только освещение. Траур — не «ещё одна тема», а стоп-кран: он гасит декор и анимации всех остальных.
Уважение к посетителю: переключатель «Спокойный вид» в подвале отключает декор и переживает перезагрузку; при prefers-reduced-motion декор статичен; в рабочих разделах и рядом с материалами с флагом sensitive декора нет вовсе.
| id | Название | Когда | Приоритет | Слои | Включена |
|---|---|---|---|---|---|
mourning | Траур | Включается вручную из админки, снимается вручную | 100 | light | да |
live-event | Идёт соревнование | Пока есть старт со статусом «идёт» | 80 | priority, light | да |
victory | Победа | Включается вручную после крупной победы, живёт 48 часов | 70 | light, copy | да |
figure-skating-day-ru | День фигурного катания в России | 8 января | 65 | light, decor | да |
new-year | Новогоднее | 20 декабря — 8 января | 60 | light, decor | да |
state-holiday | Государственный праздник | 23 февраля, 8 марта, 9 мая, 12 июня | 55 | light, copy | да |
world-ice-skating-day | Всемирный день конькобежного спорта | Декабрь, дату ISU объявляет каждый год отдельно | 50 | light, copy | да |
season-start | Открытие сезона | 1–30 сентября | 40 | priority, copy | да |
frost | Морозно | Календарная зима | 30 | light, decor | да |
pre-holiday | Канун праздника | За один-два дня до праздника из реестра | 20 | copy | да |
Дата всемирного дня конькобежного спорта хранится по годам (dateByYear), а не считается формулой: ISU объявляет её каждый год отдельно — в 2025 это было 14 декабря, хотя на сайте события упоминается «первое воскресенье декабря». Год без даты — тема молчит, без ошибок и без угадывания.
Примерить любую тему можно на витрине дизайн-системы.
Сайты представительств
Права — флаг на пару «блок × регион». Включается в панели управления отдельно для каждого региона. Выключенный блок на сайте региона всё равно есть — его наполняет федерация. Сотрудники федерации могут отредактировать содержимое любого сайта.
| Блок | Что показывает | Что даёт региону разрешение | Если регион не заполнил |
|---|---|---|---|
| Обложка | Фотография и название представительства | Заменить фотографию и заголовок | Федеральный кадр и название региона из справочника |
| О представительстве | Текст о региональной организации | Редактировать текст | Общий текст федерации о работе представительств |
| Новости | Лента новостей региона | Публиковать свои новости | Федеральные новости с отметкой региона |
| События | Календарь стартов региона | Вести свой календарь | Всероссийские старты, которые проходят в этом регионе |
| Фотогалерея | Снимки соревнований и тренировок | Загружать фотографии | Блок не показывается, пока нет ни одного снимка |
| Тренеры и специалисты | Список специалистов представительства | Вести список | Блок не показывается, пока список пуст |
| Контакты | Адрес, телефон, почта представительства | Менять адрес, телефон, e-mail | Контакты из справочника регионов |
| Документы | Файлы регионального уровня | Публиковать файлы | Ссылка на федеральный раздел «Специалистам» |
| Партнёры | Логотипы партнёров региона | Добавлять логотипы | Партнёры федерации |
Карта разделов и переезд адресов
Ничего не выбрасываем. Единственное осознанное слияние — две новостные ленты. Контент не мигрируем, старый сайт остаётся на old.fsrussia.ru.
| Было | Стало у нас | Комментарий |
|---|---|---|
/news + /novosti-federatsii + /intervyu | /news/ | Одна лента с рубриками: новости, анонсы, результаты, интервью, документы |
/sbornaya | /team/ + /athletes/<slug>/ | 121 карточка — картотека с фильтрами |
/sorevnovaniya | /events/ + /events/<slug>/ | Календарь с прошедшими и предстоящими |
Дисциплины (6) | /disciplines/ + /disciplines/<slug>/ | Шесть, включая любительское и балеты |
/obshchie-dokumenty, /kollegiya-sudej, /otchety | /specialists/ | Единый документный раздел с категориями, ~70 файлов |
/antidoping, /anti-doping-seminars | /specialists/antidoping/ | 49 файлов, структура сохраняется как есть |
/testy | /specialists/tests/ | Текстовый методический раздел, не архив файлов |
/press-tsentr | /press/ | Аккредитации и контакты для СМИ |
/federatsiya | /about/ | О федерации и Исполком; отсюда же ссылка на /docs/ |
— | /regions/ | Новое: карта и представительства |
— | /search/ | Новое: сквозной поиск |
301-редиректы
Без них поисковая выдача уходит в никуда. Глубокие ссылки на конкретные материалы уходят на old.fsrussia.ru тем же путём.
| Откуда | Куда |
|---|---|
/news | /news/ |
/novosti-federatsii | /news/ |
/sbornaya | /team/ |
/sorevnovaniya | /events/ |
/antidoping | /specialists/antidoping/ |
/obshchie-dokumenty | /specialists/ |
/kollegiya-sudej | /specialists/ |
/otchety | /specialists/ |
/testy | /specialists/tests/ |
/press-tsentr | /press/ |
/federatsiya | /about/ |
Порядок блоков главной
| № | Блок |
|---|---|
| 1 | Полоса партнёров над шапкой |
| 2 | Герой |
| 3 | Лайв или ближайший старт — когда есть |
| 4 | Новости — главный поток |
| 5 | Календарь соревнований |
| 6 | Специалистам: документы |
| 7 | Сборная |
| 8 | Дисциплины |
| 9 | Карта представительств |
| 10 | Медиа |
| 11 | Партнёры-витрина |
Данные и интеграции
Правило: страница не ходит в чужой API напрямую. Путь один — страница → src/api/ → фикстура или внешний сервис. Когда сервис коллег появится, меняется реализация функции, а вёрстка не трогается.
| Сущность | Владелец | Сейчас | Функция api | Форма | Замечание |
|---|---|---|---|---|---|
| Новости | сервисы коллег | демо-данные | getNews, getNewsBySlug | NewsItem | Заголовки и лиды сняты с действующего fsrussia.ru |
| Соревнования | сервисы коллег | демо-данные | getEvents, getUpcomingEvents, getLiveEvent | CompetitionEvent | Календарь сезона 2026/2027 из утверждённого Исполкомом PDF |
| Результаты и протоколы | сервисы коллег | данных пока нет | getResultsByEvent | ResultRow | Опубликованных протоколов сезона нет; выдумывать баллы нельзя |
| Спортсмены | сервисы коллег | демо-данные | getAthletes, getAthleteBySlug | Athlete | Состав и портреты — с опубликованной федерацией страницы сборной |
| Регионы и представительства | мы | демо-данные | getRegions, getRegionById, getRegionStats | Region | Справочник ведём сами; под сшивку с orgs коллег есть externalOrgId |
| Медиа | сервисы коллег | демо-данные | getMedia | MediaItem | Своих видеофайлов нет — у роликов только постер |
| Поиск | мы | демо-данные | search, getSearchSuggestions | SearchHit | Индекс собирается из тех же фикстур один раз на модуль |
Правила разработки
Как добавить
Новую событийную тему
- Запись в src/data/moods.ts: id, условие активации, приоритет, слои, строка микрокопии
- Файл src/styles/moods/<id>.css — только переопределения токенов
- Если нужен декор — компонент в components/mood/decor/ и ветка в MoodDecor
- Проверить приоритет против соседних тем: активной может быть только одна
- Примерить на /styleguide/#moods
Новый блок регионального сайта
- Компонент блока
- Запись в реестре блоков (src/data/blocks.ts)
- Фолбэк на случай, если регион блок не заполнил
- Тумблер «регион может редактировать» появится в панели автоматически
Новый источник данных
- Строка в docs/integrations/CONTRACT.md — кто владелец сущности
- Тип в src/types/
- Фикстура той же формы в src/data/fixtures/
- Функция в src/api/ — страница потребляет только её
Разделы и модули
| Раздел | Адрес | Статус | Назначение |
|---|---|---|---|
| Главная | / | готово | Витрина портала: новости, календарь, документы, сборная, регионы |
| Представительства | /regions/ | готово | Карта России и справочник 89 субъектов |
| Поиск | /search/ | готово | Сквозной поиск по спортсменам, новостям, соревнованиям и разделам |
| Как устроен проект | /docs/ | готово | Описание проекта простым языком — для согласования с федерацией |
| Техническая документация | /handbook/ | готово | Дизайн-система, реестры и правила разработки |
| Дизайн-система | /styleguide/ | готово | Живая витрина токенов, атомов и движения |
| Панель управления | /admin/ | в работе | Демонстрация: сайты регионов, права на блоки, контент, интеграции |
| Новости | /news/ | готово | Лента и карточка материала с рубриками |
| Соревнования | /events/ | готово | Календарь, страница турнира, вкладки; протоколы — за системой федерации |
| Сборная и картотека | /team/ | готово | Составы, картотека с фильтрами и карточки спортсменов |
| Специалистам | — | планируется | Документы, судьям, тренерам, антидопинг, тесты |
| Сайт представительства | — | планируется | Шаблон регионального сайта на поддомене |
Версии
Что менялось в системе, а не в контенте. Полная история правок — в docs/CHANGELOG.md репозитория.
| Дата | Что изменилось |
|---|---|
| 19.08.2026 | Каркас, дизайн-система и токены; статический экспорт |
| 19.08.2026 | Слой данных на реальном контенте федерации, главная страница |
| 19.08.2026 | Раздел «Как устроен проект» для согласования |
| 19.08.2026 | Карта представительств, сквозной поиск, панель управления |
| 19.08.2026 | Фотографии вместо заглушек, цветные логотипы партнёров, полоса спонсоров |
| 19.08.2026 | Событийные темы: реестр, расчёт, декор, примерка |
| 19.08.2026 | Техническая документация — эта страница |