diff --git a/apps/web/src/App.test.tsx b/apps/web/src/App.test.tsx index 1ac3b2f..8722b4a 100644 --- a/apps/web/src/App.test.tsx +++ b/apps/web/src/App.test.tsx @@ -250,7 +250,7 @@ describe('player', () => { const alice = makeUser('alice', 'user'); const { user, api } = await renderApp([alice], '/album/00000000-0000-4000-8000-0000000000bb', { signedInAs: alice }); - const row = (await screen.findByText('Закрой за мной дверь')).closest('[role="row"]')!; + const row = (await screen.findByText('Закрой за мной дверь')).closest('[role="listitem"]')!; await user.click(row); const bar = screen.getByRole('contentinfo', { name: 'Плеер' }); await waitFor(() => expect(within(bar).getByText('Закрой за мной дверь')).toBeInTheDocument()); diff --git a/apps/web/src/entities/catalog.tsx b/apps/web/src/entities/catalog.tsx index fd4168b..d584e16 100644 --- a/apps/web/src/entities/catalog.tsx +++ b/apps/web/src/entities/catalog.tsx @@ -132,7 +132,7 @@ export function TrackList({ const discs = new Set(tracks.map((tr) => tr.disc_no ?? 1)); let lastDisc: number | null = null; return ( -
{t('player.queue_wave')}
} , document.body, ); diff --git a/docs/design.md b/docs/design.md index 9f0569c..57af943 100644 --- a/docs/design.md +++ b/docs/design.md @@ -48,8 +48,9 @@ | `elev` | `#111726` | `#FFFFFF` | Поповеры, меню | | `hover` | `rgba(120,150,255,.07)` | `rgba(30,60,140,.06)` | Подсветка при наведении | | `line` / `line2` | `rgba(130,160,255,.10)` / `.18` | `rgba(20,35,80,.10)` / `.17` | Разделители / рамки | -| `text` / `text2` / `text3` | `#EDF1FF` / `#A0ABC6` / `#737F9C` | `#0A0F1E` / `#4B5675` / `#677290` | Текст: основной / вторичный / подписи | +| `text` / `text2` / `text3` | `#EDF1FF` / `#A0ABC6` / `#7F8BA8` | `#0A0F1E` / `#4B5675` / `#5C6785` | Текст: основной / вторичный / подписи | | `accent` / `accent2` | `#2F80FF` / `#5E9BFF` | `#1F6FF2` / `#1F6FF2` | Основной акцент, ссылки | +| `accent-fill` / `accent-fill2` | `#1A66E6` / `#1F6FF2` | `#1A63DB` / `#165ED6` | Заливка под белым текстом (кнопки, выбранные сегменты) и её hover — контраст ≥ 4.5:1 | | `accent-soft` | `rgba(47,128,255,.15)` | `rgba(31,111,242,.10)` | Активный пункт меню, фокус | | `violet` / `violet-soft` | `#9B7CFF` / `rgba(124,92,255,.16)` | `#6A47F0` / `.10` | Второй акцент (волна, бейджи) | | `ok` / `ok-soft` | `#2FD39A` | `#0E9465` | Успех | diff --git a/docs/web.md b/docs/web.md index c3573fe..d7ca76e 100644 --- a/docs/web.md +++ b/docs/web.md @@ -101,3 +101,15 @@ apps/web/src/ ## Доступность - Вся навигация с клавиатуры, видимый фокус, ARIA-роли у плеера и поиска, контраст AA. + +## Доступность + +Цель — WCAG 2.1 AA. Проверено axe-core на всех экранах в тёмной и светлой темах (с играющим треком и открытой +очередью) — нарушений нет. Правила, которые держим: +- текст на заливке акцента — только `--accent-fill` (белый текст ≥ 4.5:1), вторичный текст `--text3` — ≥ 4.5:1 + на фоне и поверхностях; +- у каждого экрана есть `h1`; у кнопок-иконок — `aria-label`, у переключателей — `aria-pressed`; +- списки треков — `role="list"` / `listitem` (строка фокусируется, Enter запускает трек, лайк и ссылки — отдельные + элементы); прогресс-бары подписаны через `aria-labelledby`; +- выезжающие панели (очередь) забирают фокус при открытии, закрываются по Escape и возвращают фокус на кнопку; +- `:focus-visible` — обводка акцентом; `prefers-reduced-motion` — анимации и Ambient выключены, волна замедлена. diff --git a/packages/design-tokens/src/generated/tokens.css b/packages/design-tokens/src/generated/tokens.css index d892b4d..b2fe815 100644 --- a/packages/design-tokens/src/generated/tokens.css +++ b/packages/design-tokens/src/generated/tokens.css @@ -22,9 +22,11 @@ --line2: rgba(130,160,255,.18); --text: #EDF1FF; --text2: #A0ABC6; - --text3: #737F9C; + --text3: #7F8BA8; --accent: #2F80FF; --accent2: #5E9BFF; + --accent-fill: #1A66E6; + --accent-fill2: #1F6FF2; --accent-soft: rgba(47,128,255,.15); --violet: #9B7CFF; --violet-soft: rgba(124,92,255,.16); @@ -56,9 +58,11 @@ --line2: rgba(20,35,80,.17); --text: #0A0F1E; --text2: #4B5675; - --text3: #677290; + --text3: #5C6785; --accent: #1F6FF2; --accent2: #1F6FF2; + --accent-fill: #1A63DB; + --accent-fill2: #165ED6; --accent-soft: rgba(31,111,242,.10); --violet: #6A47F0; --violet-soft: rgba(106,71,240,.10); @@ -90,9 +94,11 @@ --line2: rgba(20,35,80,.17); --text: #0A0F1E; --text2: #4B5675; - --text3: #677290; + --text3: #5C6785; --accent: #1F6FF2; --accent2: #1F6FF2; + --accent-fill: #1A63DB; + --accent-fill2: #165ED6; --accent-soft: rgba(31,111,242,.10); --violet: #6A47F0; --violet-soft: rgba(106,71,240,.10); @@ -123,9 +129,11 @@ --line2: rgba(130,160,255,.18); --text: #EDF1FF; --text2: #A0ABC6; - --text3: #737F9C; + --text3: #7F8BA8; --accent: #2F80FF; --accent2: #5E9BFF; + --accent-fill: #1A66E6; + --accent-fill2: #1F6FF2; --accent-soft: rgba(47,128,255,.15); --violet: #9B7CFF; --violet-soft: rgba(124,92,255,.16); diff --git a/packages/design-tokens/src/generated/tokens.ts b/packages/design-tokens/src/generated/tokens.ts index b617204..01aad6d 100644 --- a/packages/design-tokens/src/generated/tokens.ts +++ b/packages/design-tokens/src/generated/tokens.ts @@ -13,9 +13,11 @@ export const tokens = { "line2": "rgba(130,160,255,.18)", "text": "#EDF1FF", "text2": "#A0ABC6", - "text3": "#737F9C", + "text3": "#7F8BA8", "accent": "#2F80FF", "accent2": "#5E9BFF", + "accent-fill": "#1A66E6", + "accent-fill2": "#1F6FF2", "accent-soft": "rgba(47,128,255,.15)", "violet": "#9B7CFF", "violet-soft": "rgba(124,92,255,.16)", @@ -42,9 +44,11 @@ export const tokens = { "line2": "rgba(20,35,80,.17)", "text": "#0A0F1E", "text2": "#4B5675", - "text3": "#677290", + "text3": "#5C6785", "accent": "#1F6FF2", "accent2": "#1F6FF2", + "accent-fill": "#1A63DB", + "accent-fill2": "#165ED6", "accent-soft": "rgba(31,111,242,.10)", "violet": "#6A47F0", "violet-soft": "rgba(106,71,240,.10)", diff --git a/packages/design-tokens/tokens.json b/packages/design-tokens/tokens.json index 514f7d3..b867103 100644 --- a/packages/design-tokens/tokens.json +++ b/packages/design-tokens/tokens.json @@ -1,11 +1,11 @@ { - "$comment": "Источник истины дизайн-токенов (docs/design.md). После правки: pnpm --filter @pipu/design-tokens generate", + "$comment": "Источник истины дизайн-токенов (docs/design.md). После правки: pnpm --filter @pipu/design-tokens generate. accent-fill — заливка под белым текстом (контраст ≥ 4.5:1, WCAG AA)", "color": { "dark": { "bg": "#05070D", "bg2": "#080B14", "surface": "#0B0F1A", "surface2": "#121827", "surface3": "#1A2236", "elev": "#111726", "hover": "rgba(120,150,255,.07)", "line": "rgba(130,160,255,.10)", "line2": "rgba(130,160,255,.18)", - "text": "#EDF1FF", "text2": "#A0ABC6", "text3": "#737F9C", - "accent": "#2F80FF", "accent2": "#5E9BFF", "accent-soft": "rgba(47,128,255,.15)", + "text": "#EDF1FF", "text2": "#A0ABC6", "text3": "#7F8BA8", + "accent": "#2F80FF", "accent2": "#5E9BFF", "accent-fill": "#1A66E6", "accent-fill2": "#1F6FF2", "accent-soft": "rgba(47,128,255,.15)", "violet": "#9B7CFF", "violet-soft": "rgba(124,92,255,.16)", "ok": "#2FD39A", "ok-soft": "rgba(47,211,154,.14)", "warn": "#FFB547", "warn-soft": "rgba(255,181,71,.14)", "danger": "#FF5C70", "danger-soft": "rgba(255,92,112,.14)", @@ -14,8 +14,8 @@ "light": { "bg": "#F3F5FA", "bg2": "#EBEEF5", "surface": "#FFFFFF", "surface2": "#F0F3F9", "surface3": "#E4E9F3", "elev": "#FFFFFF", "hover": "rgba(30,60,140,.06)", "line": "rgba(20,35,80,.10)", "line2": "rgba(20,35,80,.17)", - "text": "#0A0F1E", "text2": "#4B5675", "text3": "#677290", - "accent": "#1F6FF2", "accent2": "#1F6FF2", "accent-soft": "rgba(31,111,242,.10)", + "text": "#0A0F1E", "text2": "#4B5675", "text3": "#5C6785", + "accent": "#1F6FF2", "accent2": "#1F6FF2", "accent-fill": "#1A63DB", "accent-fill2": "#165ED6", "accent-soft": "rgba(31,111,242,.10)", "violet": "#6A47F0", "violet-soft": "rgba(106,71,240,.10)", "ok": "#0E9465", "ok-soft": "rgba(14,148,101,.10)", "warn": "#A86200", "warn-soft": "rgba(168,98,0,.10)", "danger": "#D32F47", "danger-soft": "rgba(211,47,71,.09)", diff --git a/packages/i18n/locales/en/common.json b/packages/i18n/locales/en/common.json index 2f2b9a6..2b14df4 100644 --- a/packages/i18n/locales/en/common.json +++ b/packages/i18n/locales/en/common.json @@ -81,7 +81,8 @@ "source_wave": "My Wave", "source_queue": "Queue", "queue": "Queue", - "source_wave_seed": "Artist wave · {{label}}" + "source_wave_seed": "Artist wave · {{label}}", + "queue_wave": "The wave never ends: next tracks are picked as you listen" }, "settings": { "title": "Settings", diff --git a/packages/i18n/locales/ru/common.json b/packages/i18n/locales/ru/common.json index 427a587..a329199 100644 --- a/packages/i18n/locales/ru/common.json +++ b/packages/i18n/locales/ru/common.json @@ -81,7 +81,8 @@ "source_wave": "Моя волна", "source_queue": "Очередь", "queue": "Очередь", - "source_wave_seed": "Волна по исполнителю · {{label}}" + "source_wave_seed": "Волна по исполнителю · {{label}}", + "queue_wave": "Волна бесконечна: следующие треки подбираются по ходу прослушивания" }, "settings": { "title": "Настройки",