Merge branch 'refactor/a11y-polish-touch-targets-and-dark-tints' into 'main'
refactor(a11y): 44×44 touch targets + normalize accent-bg alpha See merge request 2-6/2-6-4/terravault/ordinis!193
This commit is contained in:
@@ -317,7 +317,8 @@ function SidebarFooter({
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => i18n.changeLanguage(next)}
|
onClick={() => i18n.changeLanguage(next)}
|
||||||
className="h-7 px-2.5 rounded-md border border-line bg-surface text-cap text-ink-2 hover:bg-surface-2 hover:text-ink transition-colors"
|
// h-11 + min-w-11 — DESIGN.md §13 touch target enforcement.
|
||||||
|
className="h-11 min-w-11 px-2.5 rounded-md border border-line bg-surface text-cap text-ink-2 hover:bg-surface-2 hover:text-ink transition-colors inline-flex items-center justify-center"
|
||||||
aria-label={`Language: ${cur.toUpperCase()}, click to switch`}
|
aria-label={`Language: ${cur.toUpperCase()}, click to switch`}
|
||||||
>
|
>
|
||||||
{cur.toUpperCase()}
|
{cur.toUpperCase()}
|
||||||
@@ -398,7 +399,8 @@ function AuthedUserBlock({
|
|||||||
onClick={() => auth.signoutRedirect().catch(() => auth.removeUser())}
|
onClick={() => auth.signoutRedirect().catch(() => auth.removeUser())}
|
||||||
title={t('auth.logout', { defaultValue: 'Logout' })}
|
title={t('auth.logout', { defaultValue: 'Logout' })}
|
||||||
aria-label={t('auth.logout', { defaultValue: 'Logout' })}
|
aria-label={t('auth.logout', { defaultValue: 'Logout' })}
|
||||||
className="size-7 rounded-md text-mute hover:text-ink hover:bg-surface-2 inline-flex items-center justify-center transition-colors shrink-0"
|
// size-11 = 44×44 WCAG AAA per DESIGN.md §13.
|
||||||
|
className="size-11 rounded-md text-mute hover:text-ink hover:bg-surface-2 inline-flex items-center justify-center transition-colors shrink-0"
|
||||||
>
|
>
|
||||||
<span aria-hidden>⎋</span>
|
<span aria-hidden>⎋</span>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ export function ThemeSwitch() {
|
|||||||
<div
|
<div
|
||||||
role="radiogroup"
|
role="radiogroup"
|
||||||
aria-label={t('theme.label')}
|
aria-label={t('theme.label')}
|
||||||
className="inline-flex items-center rounded-md border border-line bg-surface h-7 overflow-hidden"
|
// h-11 = 44px WCAG AAA touch target per DESIGN.md §13.
|
||||||
|
// Segmented control: 3 buttons × w-11 = 132px total width.
|
||||||
|
className="inline-flex items-center rounded-md border border-line bg-surface h-11 overflow-hidden"
|
||||||
>
|
>
|
||||||
{items.map((item) => {
|
{items.map((item) => {
|
||||||
const Icon = item.icon
|
const Icon = item.icon
|
||||||
@@ -42,7 +44,8 @@ export function ThemeSwitch() {
|
|||||||
title={item.label}
|
title={item.label}
|
||||||
onClick={() => setPreference(item.id)}
|
onClick={() => setPreference(item.id)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex h-full w-7 items-center justify-center transition-colors',
|
// w-11 paired с parent h-11 → 44×44 per button.
|
||||||
|
'inline-flex h-full w-11 items-center justify-center transition-colors',
|
||||||
active
|
active
|
||||||
? 'bg-accent text-on-accent'
|
? 'bg-accent text-on-accent'
|
||||||
: 'text-mute hover:text-ink hover:bg-surface-2',
|
: 'text-mute hover:text-ink hover:bg-surface-2',
|
||||||
|
|||||||
@@ -29,7 +29,9 @@ export function TopBar({ onMenuClick }: { onMenuClick?: () => void }) {
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label={t('nav.menu', { defaultValue: 'Меню' })}
|
aria-label={t('nav.menu', { defaultValue: 'Меню' })}
|
||||||
onClick={onMenuClick}
|
onClick={onMenuClick}
|
||||||
className="lg:hidden -ml-1 p-1.5 rounded-sm text-ink-2 hover:text-ink hover:bg-surface-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors"
|
// size-11 = 44×44 touch target per DESIGN.md §13.
|
||||||
|
// Icon stays 20px; padding wrapper provides hit area.
|
||||||
|
className="lg:hidden -ml-1 size-11 inline-flex items-center justify-center rounded-sm text-ink-2 hover:text-ink hover:bg-surface-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring transition-colors"
|
||||||
>
|
>
|
||||||
<Menu size={20} strokeWidth={1.75} />
|
<Menu size={20} strokeWidth={1.75} />
|
||||||
</button>
|
</button>
|
||||||
@@ -153,7 +155,9 @@ function NotificationsBell() {
|
|||||||
title={t('topbar.notifications', { defaultValue: 'Уведомления' })}
|
title={t('topbar.notifications', { defaultValue: 'Уведомления' })}
|
||||||
aria-label={t('topbar.notifications', { defaultValue: 'Уведомления' })}
|
aria-label={t('topbar.notifications', { defaultValue: 'Уведомления' })}
|
||||||
onClick={() => setDrawerOpen(true)}
|
onClick={() => setDrawerOpen(true)}
|
||||||
className="relative size-7 rounded-md text-ink-2 hover:text-ink hover:bg-surface-2 inline-flex items-center justify-center transition-colors"
|
// size-11 = 44×44 WCAG AAA touch target per DESIGN.md §13.
|
||||||
|
// Bell icon stays size=14; wrapper provides hit area.
|
||||||
|
className="relative size-11 rounded-md text-ink-2 hover:text-ink hover:bg-surface-2 inline-flex items-center justify-center transition-colors"
|
||||||
>
|
>
|
||||||
<Bell size={14} strokeWidth={1.75} />
|
<Bell size={14} strokeWidth={1.75} />
|
||||||
{totalUnread > 0 && (
|
{totalUnread > 0 && (
|
||||||
|
|||||||
@@ -28,7 +28,10 @@
|
|||||||
--color-line-2: #efeae0;
|
--color-line-2: #efeae0;
|
||||||
--color-navy: #3a2818;
|
--color-navy: #3a2818;
|
||||||
--color-accent: #b05a2e;
|
--color-accent: #b05a2e;
|
||||||
--color-accent-bg: rgb(176 90 46 / 11%);
|
/* Alpha 12% across all themes per DESIGN.md §17 — was 11% (light) / 16%
|
||||||
|
* (dark); drift caused subtle saturation difference в info badges between
|
||||||
|
* themes. Visually negligible diff на light, slightly weaker tint в dark. */
|
||||||
|
--color-accent-bg: rgb(176 90 46 / 12%);
|
||||||
--color-on-accent: #ffffff;
|
--color-on-accent: #ffffff;
|
||||||
--color-green: #4f7038;
|
--color-green: #4f7038;
|
||||||
--color-green-bg: #e4ead0;
|
--color-green-bg: #e4ead0;
|
||||||
@@ -170,7 +173,8 @@
|
|||||||
--color-line-2: #2d2a27;
|
--color-line-2: #2d2a27;
|
||||||
--color-navy: #d97757;
|
--color-navy: #d97757;
|
||||||
--color-accent: #d97757;
|
--color-accent: #d97757;
|
||||||
--color-accent-bg: rgb(217 119 87 / 16%);
|
/* Alpha 12% normalized per DESIGN.md §17 — was 16% on dark theme. */
|
||||||
|
--color-accent-bg: rgb(217 119 87 / 12%);
|
||||||
--color-on-accent: #1c1a17;
|
--color-on-accent: #1c1a17;
|
||||||
--color-green: #6fa97d;
|
--color-green: #6fa97d;
|
||||||
--color-green-bg: rgb(111 169 125 / 18%);
|
--color-green-bg: rgb(111 169 125 / 18%);
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ export const TabsList = React.forwardRef<
|
|||||||
<TabsPrimitive.List
|
<TabsPrimitive.List
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex h-10 items-center gap-1 border-b border-line w-full',
|
// h-11 (44px) — DESIGN.md §13 touch target enforcement. Was h-10
|
||||||
|
// (40px) — short on WCAG AAA 44 minimum.
|
||||||
|
'inline-flex h-11 items-center gap-1 border-b border-line w-full',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -33,7 +35,8 @@ export const TabsTrigger = React.forwardRef<
|
|||||||
<TabsPrimitive.Trigger
|
<TabsPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex items-center justify-center whitespace-nowrap px-3.5 h-10 text-body text-ink-2 -mb-px',
|
// h-11 paired с TabsList h-11 — touch target enforcement.
|
||||||
|
'inline-flex items-center justify-center whitespace-nowrap px-3.5 h-11 text-body text-ink-2 -mb-px',
|
||||||
'border-b-2 border-transparent transition-all hover:text-ink',
|
'border-b-2 border-transparent transition-all hover:text-ink',
|
||||||
'focus-visible:outline-none focus-visible:text-accent',
|
'focus-visible:outline-none focus-visible:text-accent',
|
||||||
'disabled:pointer-events-none disabled:opacity-50',
|
'disabled:pointer-events-none disabled:opacity-50',
|
||||||
|
|||||||
Reference in New Issue
Block a user