refactor(header): unified menu navigation for all devices #8

Closed
opened 2026-08-07 15:20:11 +03:00 by slaid098 · 0 comments
Owner

Контекст

Шапка сайта (src/components/site-header.tsx) — grid из 3 равных колонок с условным swap: на главной и /apps бренд слева + «Утилиты» по центру, на всех остальных страницах бренд переезжает в центр, слева появляется «← Утилиты». Проблемы:

  1. Шапка «прыгает» при переходе на карточку — лого скачет слева на середину.
  2. Стрелка «← Утилиты» показывается на /contacts (и на /subscriptions) — условие ловит всё, что не root и не /apps.
  3. Навигация не масштабируется — с /subscriptions (и позже «Статьи») пунктов станет больше, а строка тесная на мобильных. Бургер-меню нет.

Решение (согласовано): унифицированное меню ☰, одинаковое на всех устройствах.

Задача

  1. Бренд всегда слева — убрать условный swap лого в центр. Чинит «прыжок» шапки.
  2. Унифицированное меню ☰ справа, рядом с переключателем языка, одинаковое на всех устройствах: кнопка открывает выпадающую панель со ссылками на разделы: «Утилиты» / «Utilities», «Подписки» / «Subscriptions». Закрытие по Esc, по клику вне, по переходу (смена pathname); aria-expanded, aria-controls, фокус-менеджмент.
  3. Стрелка «← Утилиты» уезжает из шапки на страницу src/app/[locale]/[slug]/page.tsx (над заголовком карточки). На /contacts и /subscriptions стрелки НЕТ — обычная шапка.
  4. Обновить словари header в src/lib/i18n.ts (ключи меню/пунктов, ru/en).
  5. Тесты vitest: рендер шапки, открытие/закрытие меню, наличие пунктов.

Контракты

  • Шапка идентична на всех страницах и всех устройствах: [бренд] ... [язык] [☰].
  • Меню содержит пункты всех разделов первого уровня; добавление нового раздела = один элемент в списке + ключ словаря.
  • «← назад» существует только внутри [slug]/page.tsx.

Инварианты

  • Header остаётся клиентским компонентом, sticky; визуальный стиль (bg-base, max-w-6xl, Tailwind v4) сохраняется.
  • Никаких Dynamic API (cookies()/headers()) — статика/ISR не ломается.
  • Accessibility: aria-expanded, aria-controls, закрытие по Esc, фокус-менеджмент.

Граничные случаи

  • Открытое меню + переход по ссылке → меню закрыто после навигации.
  • Открытое меню + ресайз окна → поведение одинаковое (не зависит от breakpoint).
  • EN-локаль: длинные подписи помещаются в панель.

Влияние на связанные компоненты

  • src/components/site-header.tsx — основная переработка.
  • src/app/[locale]/[slug]/page.tsx — добавляется ссылка «← назад к утилитам».
  • src/app/[locale]/contacts/page.tsx — из шапки уходит ложная стрелка.
  • src/lib/i18n.ts — секция header: новые ключи (меню, пункты).
  • src/__tests__/ — тесты header.

Вне scope

  • Контент страницы /subscriptions (отдельная задача — feat(subscriptions): personal AI subscriptions page, должна быть влита первой).
  • Футер.
  • Раздел «Статьи» и CMS — будущие задачи.

Критерии приемки

  • Бренд неподвижен слева при любых переходах; «прыжка» шапки нет.
  • Меню ☰ одинаково работает на десктопе и мобильном, содержит «Утилиты» и «Подписки».
  • «← Утилиты» отображается только на детальных страницах утилит; на /contacts и /subscriptions её нет.
  • Build, lint, тесты зелёные.
## Контекст Шапка сайта (`src/components/site-header.tsx`) — grid из 3 равных колонок с условным swap: на главной и `/apps` бренд слева + «Утилиты» по центру, на всех остальных страницах бренд переезжает в центр, слева появляется «← Утилиты». Проблемы: 1. **Шапка «прыгает»** при переходе на карточку — лого скачет слева на середину. 2. **Стрелка «← Утилиты» показывается на /contacts** (и на /subscriptions) — условие ловит всё, что не root и не `/apps`. 3. **Навигация не масштабируется** — с /subscriptions (и позже «Статьи») пунктов станет больше, а строка тесная на мобильных. Бургер-меню нет. Решение (согласовано): унифицированное меню ☰, одинаковое на всех устройствах. ## Задача 1. **Бренд всегда слева** — убрать условный swap лого в центр. Чинит «прыжок» шапки. 2. **Унифицированное меню ☰** справа, рядом с переключателем языка, одинаковое на всех устройствах: кнопка открывает выпадающую панель со ссылками на разделы: «Утилиты» / «Utilities», «Подписки» / «Subscriptions». Закрытие по Esc, по клику вне, по переходу (смена pathname); `aria-expanded`, `aria-controls`, фокус-менеджмент. 3. **Стрелка «← Утилиты» уезжает из шапки** на страницу `src/app/[locale]/[slug]/page.tsx` (над заголовком карточки). На `/contacts` и `/subscriptions` стрелки НЕТ — обычная шапка. 4. Обновить словари `header` в `src/lib/i18n.ts` (ключи меню/пунктов, ru/en). 5. Тесты vitest: рендер шапки, открытие/закрытие меню, наличие пунктов. ## Контракты - Шапка идентична на всех страницах и всех устройствах: `[бренд] ... [язык] [☰]`. - Меню содержит пункты всех разделов первого уровня; добавление нового раздела = один элемент в списке + ключ словаря. - «← назад» существует только внутри `[slug]/page.tsx`. ## Инварианты - Header остаётся клиентским компонентом, sticky; визуальный стиль (bg-base, max-w-6xl, Tailwind v4) сохраняется. - Никаких Dynamic API (`cookies()`/`headers()`) — статика/ISR не ломается. - Accessibility: `aria-expanded`, `aria-controls`, закрытие по Esc, фокус-менеджмент. ## Граничные случаи - Открытое меню + переход по ссылке → меню закрыто после навигации. - Открытое меню + ресайз окна → поведение одинаковое (не зависит от breakpoint). - EN-локаль: длинные подписи помещаются в панель. ## Влияние на связанные компоненты - `src/components/site-header.tsx` — основная переработка. - `src/app/[locale]/[slug]/page.tsx` — добавляется ссылка «← назад к утилитам». - `src/app/[locale]/contacts/page.tsx` — из шапки уходит ложная стрелка. - `src/lib/i18n.ts` — секция `header`: новые ключи (меню, пункты). - `src/__tests__/` — тесты header. ## Вне scope - Контент страницы /subscriptions (отдельная задача — feat(subscriptions): personal AI subscriptions page, должна быть влита первой). - Футер. - Раздел «Статьи» и CMS — будущие задачи. ## Критерии приемки - Бренд неподвижен слева при любых переходах; «прыжка» шапки нет. - Меню ☰ одинаково работает на десктопе и мобильном, содержит «Утилиты» и «Подписки». - «← Утилиты» отображается только на детальных страницах утилит; на `/contacts` и `/subscriptions` её нет. - Build, lint, тесты зелёные.
Sign in to join this conversation.
No labels
bug
performance
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
slaid098/slaid098-dev#8
No description provided.