fix(mobile): enforce strict >= 44x44px touch targets on topbar, drawer close, and form builder controls

This commit is contained in:
ochenstarik 2026-09-11 10:25:20 +07:00
parent 42d48618ec
commit 63b12b92ec
5 changed files with 21 additions and 16 deletions

View file

@ -1,9 +1,8 @@
import { test, expect } from '@playwright/test';
import { test, expect } from '@playwright/test';
test.describe('Scenario 11: Universal Modules Catalog & Profiles', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('domcontentloaded');
await page.goto('/', { waitUntil: 'domcontentloaded' });
});
test('1. First open immediately displays all 18 modules with "Все модули" active by default', async ({ page }) => {

View file

@ -2,8 +2,7 @@ import { test, expect } from '@playwright/test';
test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
await page.waitForLoadState('domcontentloaded');
await page.goto('/', { waitUntil: 'domcontentloaded' });
});
test('1. Mobile viewport (< 768px) automatically displays bottom navigation', async ({ page, viewport }) => {
@ -88,6 +87,12 @@ test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () =
// Close drawer
const closeBtn = page.locator('[data-testid="close-mobile-menu"]');
const closeBox = await closeBtn.boundingBox();
expect(closeBox).not.toBeNull();
if (closeBox) {
expect(closeBox.height).toBeGreaterThanOrEqual(44);
expect(closeBox.width).toBeGreaterThanOrEqual(44);
}
await closeBtn.click();
await expect(drawer).not.toBeVisible();
});
@ -139,11 +144,12 @@ test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () =
if (await moveDownBtn.isVisible()) {
await expect(moveDownBtn).toBeVisible();
// Verify button has accessible touch target
// Verify button has accessible touch target >= 44x44px
const box = await moveDownBtn.boundingBox();
expect(box).not.toBeNull();
if (box) {
expect(box.height).toBeGreaterThanOrEqual(28);
expect(box.height).toBeGreaterThanOrEqual(44);
expect(box.width).toBeGreaterThanOrEqual(44);
}
}
});

View file

@ -97,7 +97,7 @@ export const MobileMenuDrawer: React.FC<MobileMenuDrawerProps> = ({ isOpen, onCl
<button
onClick={onClose}
className="w-10 h-10 rounded-xl bg-krona-workspace border border-krona-border text-krona-secondary hover:text-krona-primary flex items-center justify-center active:scale-95 transition-all"
className="w-11 h-11 min-w-[44px] min-h-[44px] rounded-xl bg-krona-workspace border border-krona-border text-krona-secondary hover:text-krona-primary flex items-center justify-center active:scale-95 transition-all"
aria-label="Закрыть меню"
data-testid="close-mobile-menu"
>

View file

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { useDemoStore } from '../../mock/store';
import { BUSINESS_PROFILES } from '../../core/profiles/profiles';
@ -96,7 +96,7 @@ export const Topbar: React.FC = () => {
{/* AI Trigger */}
<button
onClick={() => setIsAiDrawerOpen(true)}
className="w-9 h-9 rounded-xl bg-krona-workspace text-krona-gold hover:text-krona-gold-text border border-krona-border flex items-center justify-center active:scale-95 transition-all"
className="w-11 h-11 min-w-[44px] min-h-[44px] rounded-xl bg-krona-workspace text-krona-gold hover:text-krona-gold-text border border-krona-border flex items-center justify-center active:scale-95 transition-all"
title="Krona AI"
aria-label="Krona AI"
>
@ -106,7 +106,7 @@ export const Topbar: React.FC = () => {
{/* Notifications Trigger */}
<button
onClick={() => setIsNotificationsOpen(true)}
className="relative w-9 h-9 rounded-xl bg-krona-workspace text-krona-secondary hover:text-krona-primary border border-krona-border flex items-center justify-center active:scale-95 transition-all"
className="relative w-11 h-11 min-w-[44px] min-h-[44px] rounded-xl bg-krona-workspace text-krona-secondary hover:text-krona-primary border border-krona-border flex items-center justify-center active:scale-95 transition-all"
title="Уведомления"
aria-label="Уведомления"
data-testid="mobile-notifications-btn"
@ -120,7 +120,7 @@ export const Topbar: React.FC = () => {
{/* Profile / Menu Drawer Trigger */}
<button
onClick={() => setIsMobileDrawerOpen(true)}
className="w-9 h-9 rounded-xl bg-krona-workspace text-krona-primary border border-krona-border flex items-center justify-center active:scale-95 transition-all"
className="w-11 h-11 min-w-[44px] min-h-[44px] rounded-xl bg-krona-workspace text-krona-primary border border-krona-border flex items-center justify-center active:scale-95 transition-all"
title="Меню управления"
aria-label="Открыть меню управления"
data-testid="mobile-menu-btn"

View file

@ -640,11 +640,11 @@ export const FormBuilder: React.FC = () => {
handleMoveField(section.id, fIdx, Math.max(0, fIdx - 1));
}}
disabled={fIdx === 0}
className="p-1.5 min-w-[32px] min-h-[32px] flex items-center justify-center rounded hover:bg-krona-surface hover:text-krona-primary disabled:opacity-20 transition-colors"
className="p-1.5 min-w-[44px] min-h-[44px] flex items-center justify-center rounded hover:bg-krona-surface hover:text-krona-primary disabled:opacity-20 transition-colors"
title="Переместить вверх / влево"
aria-label="Переместить поле выше"
>
<MoveUp className="w-3.5 h-3.5" />
<MoveUp className="w-4 h-4" />
</button>
<button
type="button"
@ -658,11 +658,11 @@ export const FormBuilder: React.FC = () => {
);
}}
disabled={fIdx === section.fieldKeys.length - 1}
className="p-1.5 min-w-[32px] min-h-[32px] flex items-center justify-center rounded hover:bg-krona-surface hover:text-krona-primary disabled:opacity-20 transition-colors"
className="p-1.5 min-w-[44px] min-h-[44px] flex items-center justify-center rounded hover:bg-krona-surface hover:text-krona-primary disabled:opacity-20 transition-colors"
title="Переместить вниз / вправо"
aria-label="Переместить поле ниже"
>
<MoveDown className="w-3.5 h-3.5" />
<MoveDown className="w-4 h-4" />
</button>
</div>