openspec: архив change header-typewriter (спека site-header-typewriter в specs/)
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# site-header-typewriter Specification
|
||||
|
||||
## Purpose
|
||||
Логотип `dedinit()` в шапке сайта анимирован эффектом печатной машинки:
|
||||
внутри скобок блочный курсор печатает темы блога, замирает, стирает их и
|
||||
переходит к следующей — обыгрывая название как вызов функции `dedinit(...)`.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Анимация «печатная машинка» в логотипе
|
||||
|
||||
Система SHALL анимировать текст в скобках логотипа `dedinit()` на всех
|
||||
страницах сайта: блочный курсор печатает слово по одному символу, удерживает
|
||||
его ~1 секунду, стирает по одному символу, мигает на пустом месте и печатает
|
||||
следующее слово — бесконечным циклом по списку тем блога.
|
||||
|
||||
#### Scenario: Логотип печатает слова по циклу
|
||||
|
||||
- **GIVEN** открыта любая страница сайта (`/` или внутренняя), JS включён
|
||||
- **WHEN** страница загружена
|
||||
- **THEN** в `dedinit()` между скобками присутствует контейнер
|
||||
`#dedinit-typewriter` с блочным мигающим курсором, и текст посимвольно
|
||||
печатается из списка тем (например, `linux` → `llm` → `politics` → ...)
|
||||
|
||||
#### Scenario: Цикл без остановки
|
||||
|
||||
- **GIVEN** анимация запущена
|
||||
- **WHEN** прошло более 3 слов печати/стирания
|
||||
- **THEN** анимация продолжает цикл (после последнего слова переходит к
|
||||
первому), не останавливаясь и не накапливая ошибок
|
||||
|
||||
### Requirement: Бесшовный вывод (прогрессивное улучшение)
|
||||
|
||||
Система SHALL оставаться декоративным улучшением: при выключенном JS логотип
|
||||
остаётся обычным текстом `dedinit()`; при его включении — анимация
|
||||
накладывается, не ломая вёрстку и навигацию шапки.
|
||||
|
||||
#### Scenario: JS отключён — логотип статичен
|
||||
|
||||
- **GIVEN** браузер с отключённым JavaScript
|
||||
- **WHEN** страница загружена
|
||||
- **THEN** в шапке отображается обычный текст `dedinit()` без скобочного
|
||||
контейнера и без ошибок
|
||||
|
||||
### Requirement: Доступность (prefers-reduced-motion)
|
||||
|
||||
Система SHALL уважать системную настройку `prefers-reduced-motion: reduce`:
|
||||
при ней показывать первое слово списка статически, без анимации и мигания.
|
||||
|
||||
#### Scenario: Уменьшение движения
|
||||
|
||||
- **GIVEN** у пользователя включено `prefers-reduced-motion: reduce`
|
||||
- **WHEN** страница загружена
|
||||
- **THEN** внутри скобок логотипа отображается первое слово списка статично,
|
||||
курсор не мигает (CSS `animation: none`), JS-цикл не запускается
|
||||
|
||||
### Requirement: Минимальный размер и отсутствие зависимостей
|
||||
|
||||
Система SHALL реализовывать эффект без внешних зависимостей (без Alpine.js,
|
||||
без jQuery): инлайн-скрипт и CSS суммарно не более ~2 КБ.
|
||||
|
||||
#### Scenario: Нет внешних библиотек
|
||||
|
||||
- **GIVEN** собранный сайт
|
||||
- **WHEN** просматривается HTML страницы
|
||||
- **THEN** в `<head>`/футере не подключено никаких сторонних JS-библиотек для
|
||||
эффекта (только собственный инлайн-скрипт и CSS темы)
|
||||
|
||||
### Requirement: Список тем конфигурируется
|
||||
|
||||
Система SHALL позволять задавать список тем через `hugo.toml`
|
||||
(`[params.typewriter] words = [...]`), со встроенным фолбэком по умолчанию
|
||||
(`linux, llm, politics, homelab, nix`) при его отсутствии.
|
||||
|
||||
#### Scenario: Слова из конфига
|
||||
|
||||
- **GIVEN** в `hugo.toml` задан `[params.typewriter] words = ["linux","llm","politics"]`
|
||||
- **WHEN** страница собрана и открыта
|
||||
- **THEN** анимация печатает именно эти слова, в заданном порядке
|
||||
|
||||
#### Scenario: Конфиг не задан
|
||||
|
||||
- **GIVEN** в `hugo.toml` нет `[params.typewriter]`
|
||||
- **WHEN** страница собрана и открыта
|
||||
- **THEN** используется фолбэк-список по умолчанию, анимация работает
|
||||
Reference in New Issue
Block a user