27 KiB
Дизайн-система сайта и игры «Вечерний детектив»
Два направления с общим логотипом: сайт помогает выбрать дело и управлять участием, игра погружает в расследование. Визуальные правила описаны здесь; единственный источник правил реализации — FRONTEND_CODE_STANDARD.md. Рабочие страницы мигрируют постепенно; образцы не меняют их оформление.
Области применения
| Направление | Где применяется | Характер |
|---|---|---|
| Сайт «Золотой вечер» | Главная, каталог, кабинет, страницы организатора, редакторы и обычные формы | Тёмные ровные панели, машинописный шрифт, ярко-жёлтые действия, лёгкие фактуры |
| Игра «Материалы дела» | Расследование команды, улики, сюжетные документы, игровое управление и печатные материалы | Существующие бумага, кожа, металл, машинописный текст, бронзовые надписи и фактурные кнопки |
Превью сюжетного документа внутри каталога или редактора использует игровой стиль; окружающие управление и формы — стиль сайта. Игровые изображения и фоны сценариев сохраняют собственное оформление.
Живые образцы
Запустить npm run dev и открыть /design-system на адресе Vite. Вкладка
«Сайт» открывается первой, «Игра» показывает отдельные материалы и управление,
«Компоненты» — последовательный каталог: заголовок компонента, живой пример,
описание контракта и код подключения; затем следующий компонент.
Страница доступна только в разработке, без входа и пункта основного меню;
маршрут и компоненты образцов исключены из production-сборки.
Все данные вымышлены. Форма, модальное окно и ход игры работают локально;
игровой ход не вызывает API и не меняет данные игры. Сайт использует SiteThemeProvider, игровые образцы —
собственный NConfigProvider: тема сайта не попадает в игровые компоненты.
Общий бренд и логотип
Использовать существующий знак: детектив в шляпе, чёрный круг, золотая окантовка. Не растягивать, не обрезать окантовку, не перерисовывать. Свободное поле — не меньше четверти диаметра; промежуток до названия — от 12 px. Размеры образцов — 48 и 144 px.
Изображение рядом с названием имеет пустой alt, самостоятельный знак —
описательный. JPEG сохраняет белый фон внутри круга, круглое размещение
допускает border-radius: 50%. Прозрачного и векторного исходника нет;
качество крупной печати и узнаваемость favicon проверяются отдельно.
Основной цвет текста обоих стилей на тёмных поверхностях — светлый #EEE,
второстепенный — #BDB8AE. Игровой бежевый #BFA07D используется точечно:
в бренде, декоративных надписях и текстовыделителе. Цвета статусов сохраняют
значение; текст на бумаге и жёлтых кнопках остаётся тёмным. Общий блок бренда
DesignBrand содержит логотип 48 px, промежуток 12 px и название
«Вечерний детектив» через HeaderText. На узком экране название может
переноситься; название направления «Материалы дела» располагается отдельно.
Общие правила: mobile-first, desktop от 1024 px, текущие контейнеры 700/1200 px, явные состояния ошибки и загрузки, доступность с клавиатуры. Шкала отступов: 4, 8, 12, 16, 24, 32, 48, 64 px. Цвета задавать семантическими CSS-переменными.
Сайт «Золотой вечер»
Палитра
Токены находятся в src/assets/base.css. --brand-bronze и бумага связывают
оформление с игрой; жёлтый primary относится к сайту, а не к игровым действиям.
| CSS-переменная | Цвет | Назначение |
|---|---|---|
--brand-background |
#111111 |
Фон сайта; текст на золотой кнопке и бумаге |
--brand-surface |
#222222 |
Карточки, панели, окна |
--brand-surface-hover |
#2E2E39 |
Подсветка поверхности при наведении |
--brand-text |
#EEEEEE |
Основной текст |
--brand-text-muted |
#BDB8AE |
Пояснения, подписи, второстепенные данные |
--brand-accent |
#FFD43B |
Основное действие, ссылки, активный элемент, focus |
--brand-accent-hover |
#FFE066 |
Наведение на основное действие |
--brand-accent-pressed |
#F5C518 |
Нажатие на основное действие |
--brand-border |
#77737F |
Границы полей и панелей |
--brand-success |
#87C99D |
Успех |
--brand-info |
#94BFEE |
Информация |
--brand-error |
#F29A9A |
Ошибка и опасное действие |
--brand-bronze |
#BFA07D |
Бренд, текстовыделитель и декоративные надписи |
--brand-paper |
#F4EDE0 |
Бумажные материалы |
Предупреждение использует золото и явную подпись. Статусы не передавать только цветом: добавлять текст и штатную иконку. Жёлтый акцент не использовать как цвет обычного текста на бумаге или белом фоне.
Типографика и компоновка
Весь стиль сайта использует существующий font_old_typer: заголовки, основной
текст, подписи, меню, кнопки, формы, таблицы и модальные окна. Новые шрифты не
загружаются. Шрифт задаётся на контейнере и в локальной теме Naive UI, чтобы
сохраняться в телепортируемых окнах. Игровая типографика остаётся прежней.
| Элемент | Размер | Вес | Межстрочный интервал |
|---|---|---|---|
| Главный заголовок | clamp(32px, 4vw, 48px) |
600 | 1.15 |
| Заголовок раздела | 28 px | 600 | 1.3 |
| Заголовок блока | 22 px | 600 | 1.4 |
| Вступление | 18 px | 400 | 1.5 |
| Основной текст | 18 px | 400 | 1.5 |
| Подпись | 14 px | 400 | 1.5 |
| Короткая надпись над разделом | 14 px | 400 | 1.5 |
| Бумажный текст | 18 px | существующий вес MessagePaper |
1.5 |
Шкала отступов: 4, 8, 12, 16, 24, 32, 48, 64 px. На мобильном экране внешние поля 16 px, на desktop — 24 px; между разделами 32 px на мобильном и 48 px на desktop, без сложения верхних и нижних отступов соседних секций. Базовое скругление 8 px. Панели имеют тонкую границу; выраженную тень оставить бумажному слою и существующим фактурным компонентам.
Использовать текущие контейнеры .width700 для дел и .width1200 для списков,
прокрутку .center-block-custom и шапку высотой 70 px. Mobile-first;
desktop-порог — @media (width >= 1024px). До него колонки складываются
вертикально, кнопки переносятся; широкая таблица прокручивается внутри себя.
Главный блок выравнивается по верхнему краю, между колонками 32 px. Внутри карточек поля 16 px на мобильном и 24 px на desktop, между элементами 16 px, перед главным действием 24 px. Отступы абзацев по умолчанию нулевые; интервалы задаются контейнерами. Не сжимать машинописный заголовок отрицательным межбуквенным интервалом. Небольшие папки каталога сохраняют подписи не меньше 14 px.
Компоненты и материалы
Использовать Naive UI. NConfigProvider берёт тему из CSS-токенов. Primary
имеет сплошную заливку #FFD43B, hover #FFE066, pressed #F5C518, текст
#111; сохранять машинописный шрифт и видимый focus. Опасное действие
использует красный акцент. Disabled и loading — штатные состояния Naive UI.
Главный блок, карточки, формы, таблицы и окна имеют ровные поверхности. Кожа
допускается как небольшая полоса в шапке (BeltBlock), бумага — в документальных фрагментах превью дела (paper.jpg);
не оформлять весь сайт стопками листов. Название с логотипом в обоих стилях использует общий DesignBrand и
существующий HeaderText: бежевый #BFA07D, машинописный шрифт 22 px,
вес 600 и разрядка 2 px. Меню и основной текст сайта используют font_old_typer.
Ссылки жёлтые на тёмном фоне; на светлом ярлыке текст тёмный. Формы имеют
подписи и ошибки у полей, таблицы — локальную прокрутку при необходимости.
Модальные окна — n-modal + n-card, заголовок, role dialog и aria-modal.
Доска расследования
Без градиентов и свечения. Главный блок использует композицию из текстовых улик: записка, билет, время отправления, номера и соединительные линии приглушённого бронзового цвета. Логотип остаётся в шапке, не заменяет обложку каждого дела. Под композицией — название, параметры и жёлтое действие.
На desktop фрагменты расположены асимметрично с небольшими поворотами;
на мобильном — вертикально, без наложения текста. Бумага использует существующую
фактуру. Машинописный шрифт допустим внутри документальных фрагментов;
описания, навигация, формы и кнопки тоже используют font_old_typer.
Документальные фрагменты декоративные, не имеют самостоятельных hover или действий. Линии не перехватывают
клики. Формы и служебные панели сохраняют ровные поверхности. Большая доска использует CaseBoard; каталог — повторяемые папки
CaseFolder с предметными обложками.
Детали досье
| Приём | Где и как применять |
|---|---|
| Папка с ярлыком | Карточка каталога, номер на выступающем ярлыке; оставлять 32 px между карточками |
| Бежевый маркер | Одно важное выражение в заголовке, тёмный текст на бежевой неровной полосе |
| Улика на обороте | Явная кнопка раскрывает цитату, aria-expanded и aria-controls; без 3D-переворота |
| Архивные разделители | Пунктир между разделами, номера и уголки на обложках; не дополнительные рамки вокруг каждого текста |
| Предметная обложка | Билет, ключ или письмо из существующих иконок и бумажных фактур; тот же символ рядом с названием |
| Заметка на полях | Короткая сюжетная подпись рядом с большой доской; на мобильном — ниже композиции |
| Штамп статуса | «Новое дело», «Скоро», «Пройдено»; только при наличии соответствующего реального состояния |
| Подсветка связи | Одна бронзовая линия становится жёлтой при hover или фокусе действия в карточке |
| Конец досье | Номер листа, название проекта, тонкая линия и «Продолжение — в следующем деле» |
Карточки поднимаются на 3 px при наведении мыши и фокусе внутри. Переходы
занимают 160 ms; при prefers-reduced-motion подъём и переходы отключаются,
раскрытие цитат продолжает работать. Touch не зависит от hover: цитата
открывается кнопкой. Декоративные слои и линии не перехватывают клики.
Три папки в образцах вымышлены, их штампы не обозначают реальные публикации
или историю пользователя. В образце дело «Скоро» имеет отключённое основное действие через отдельный
disabled; сам статус не управляет доступностью.
На рабочем сайте привязать состояния к данным; не вычислять «новое» или
«пройдено» по предположениям. Формы и таблицы сохраняют спокойный вид.
Игра «Материалы дела»
Эталон и палитра
Эталон — текущее оформление расследования команды, а не тема сайта.
Сохранить MessagePaper, IntroBlock, GameInputForm, BeltBlock,
MetalPlate и их фактуры. Окружение тёмное #111, панели #222, основной текст
#EEE, бумажный текст чёрный, декоративные надписи бронзовые #BFA07D.
Существующие мятные состояния и фактурные игровые кнопки сохраняются;
жёлтую тему сайта не передавать игровому provider.
Материалы и управление
| Материал | Источник | Применение |
|---|---|---|
| Бумага | MessagePaper, paper.jpg, paper_white.jpg |
Вступление, точки, улики и фотографии; сохранять слои и тени |
| Кожа | BeltBlock, belt.png |
Полосы управления и фактурные действия |
| Металл | MetalPlate, metal.png, pin.png |
Детали панелей, без заливки всей страницы |
| Игровое управление | GameInputForm, input_center.png, button.png |
Место назначения, счётчики и фактурная кнопка |
Машинописный шрифт сохраняется в документах и существующих игровых
компонентах; сайт использует тот же шрифт по собственным правилам компоновки. HeaderText — для
бронзовых игровых надписей. В образцах подписи на коже и металле используют
чёрную подложку 80% для читаемости. Это локальное оформление образцов,
не массовая переделка рабочих игровых компонентов.
Вступление и улика используют настоящие компоненты с демонстрационными данными. Панель хода повторяет поведение игры: успешный локальный ход очищает поле и показывает результат. В образцах панель размещена в потоке страницы; в рабочей игре остаётся её существующее фиксированное положение.
Печатные материалы
Светлые внутренние страницы, тёмный текст, небольшие золотые метки. Тёмное оформление допустимо для обложек. Не печатать свечение интерфейса. Номера, подписи и статусы должны читаться в чёрно-белом виде; сюжетные изображения сохраняют собственную стилистику.
Проверка изменённого экрана
-
На ширинах 375, 768 и 1280 px нет горизонтальной прокрутки всей страницы; таблица может прокручиваться локально.
-
Текст имеет контраст от 4.5:1; крупный текст и значимые границы управления — от 3:1. Проверять реальные пары цветов, в том числе hover и pressed.
-
Все действия доступны с клавиатуры; focus виден, окно закрывается и возвращает фокус на открывший его элемент.
-
Ошибка, успех, загрузка и пустое состояние различимы без цвета.
-
Логотип не деформирован; весь UI сайта использует
font_old_typer, включая окна. -
Компонентные стили локальны, глобальная тема изменяется только при осознанной миграции. Типы, ESLint и Stylelint проходят; изменения маршрутов проверены сборкой.
-
Переключение вкладок доступно с клавиатуры; сайт открывается первым.
-
Жёлтая тема сайта не меняет игровые кнопки и документы.
-
Игровой ход в образцах работает без сетевых запросов.
Подключение библиотеки
Компоненты находятся в src/components, импортируются напрямую и не зависят
от dev-маршрута. Отдельного пакета и глобальной регистрации нет. Демонстрационные
данные остаются в SiteDesignPreview, GameDesignPreview и ComponentDesignCatalog.
Рабочие экраны пока не мигрируют.
<script setup lang="ts">
import { NButton, NCard } from 'naive-ui'
import SiteThemeProvider from '@/components/SiteThemeProvider.vue'
import CaseFolder from '@/components/CaseFolder.vue'
function openCase(title: string) {
// Здесь родитель выполняет нужную навигацию или загрузку.
console.log(title)
}
</script>
<template>
<SiteThemeProvider>
<NCard title="Материалы"><NButton type="primary">Открыть</NButton></NCard>
<CaseFolder
number="014"
title="Последний поезд"
description="Письмо и билет"
quote="Не доверяй времени"
object="ticket"
cover-label="Материал 014 / Билет"
cover-caption="23:40 · Вагон 03"
@open="openCase"
/>
</SiteThemeProvider>
</template>
Provider читает существующие CSS-токены при монтировании, задаёт darkTheme,
цвета, машинописный шрифт и размеры Naive UI; кнопки, поля, таблицы и окна
используются непосредственно из naive-ui. Телепортируемые окна сохраняют
тему; для текста внутри NCard используйте машинописный шрифт на классе окна,
как в каталоге. --site-card-padding позволяет контейнеру задавать поля карточек.
Игровые компоненты размещайте вне provider сайта, под своим
NConfigProvider :theme="darkTheme" :theme-overrides="{}".
| Компонент | Props | Slots / события |
|---|---|---|
SiteThemeProvider |
Нет | default / нет |
DesignBrand |
Нет | Нет |
CaseFolder |
number, title, description, quote, object: ticket/key/letter, coverLabel, coverCaption; status?, disabled=false, actionLabel='Открыть дело' | Нет / open(title: string) |
CaseBoard |
label, fragments: readonly массив { number, title, text, caption?, detail?, kind?: note/ticket/timetable }, footer? | footer / нет |
ObjectCover |
object: ticket/key/letter, label, caption, status? | Нет |
StatusStamp |
text? | default заменяет text / нет |
TextHighlight |
Нет | default / нет |
SectionHeading |
title, id?, eyebrow? | default заменяет title / нет |
DossierFooter |
label | default / нет |
MessagePaper |
Нет | default / нет |
HeaderText |
Нет | default / нет |
BeltBlock |
Нет | default / нет |
MetalPlate |
Нет | default / нет |
IntroBlock |
introduction: EditableIntroduction, mode: show/show-editor/edit | default в режиме edit / update:mode |
GameInputForm |
addAction: (code: string) => Promise, allPlacesCount, newPlacesCount, gameStatus | Нет; true от addAction очищает поле |
Статус папки необязателен и только показывает текст. Доступность задаёт родитель
через disabled, подпись действия — через actionLabel. Событие open передаёт
название; маршрутизация и API остаются у родителя. Каждая цитата получает
уникальный Vue useId(), даже для повторных карточек одного дела.
Вкладки переключаются стрелками по кругу, Home открывает «Сайт», End — «Компоненты». Каталог показывает disabled, loading, ошибку и успешную форму, обрабатывает open локально и не отправляет запросы к серверу.