fix(mobile): enforce strict >= 44x44px touch targets on topbar, drawer close, and form builder controls
This commit is contained in:
parent
42d48618ec
commit
63b12b92ec
5 changed files with 21 additions and 16 deletions
|
|
@ -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.describe('Scenario 11: Universal Modules Catalog & Profiles', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/', { waitUntil: 'domcontentloaded' });
|
||||||
await page.waitForLoadState('domcontentloaded');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('1. First open immediately displays all 18 modules with "Все модули" active by default', async ({ page }) => {
|
test('1. First open immediately displays all 18 modules with "Все модули" active by default', async ({ page }) => {
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,7 @@ import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () => {
|
test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/', { waitUntil: 'domcontentloaded' });
|
||||||
await page.waitForLoadState('domcontentloaded');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('1. Mobile viewport (< 768px) automatically displays bottom navigation', async ({ page, viewport }) => {
|
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
|
// Close drawer
|
||||||
const closeBtn = page.locator('[data-testid="close-mobile-menu"]');
|
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 closeBtn.click();
|
||||||
await expect(drawer).not.toBeVisible();
|
await expect(drawer).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
@ -139,11 +144,12 @@ test.describe('Scenario 12: Mobile-First and Tablet Architecture Overhaul', () =
|
||||||
|
|
||||||
if (await moveDownBtn.isVisible()) {
|
if (await moveDownBtn.isVisible()) {
|
||||||
await expect(moveDownBtn).toBeVisible();
|
await expect(moveDownBtn).toBeVisible();
|
||||||
// Verify button has accessible touch target
|
// Verify button has accessible touch target >= 44x44px
|
||||||
const box = await moveDownBtn.boundingBox();
|
const box = await moveDownBtn.boundingBox();
|
||||||
expect(box).not.toBeNull();
|
expect(box).not.toBeNull();
|
||||||
if (box) {
|
if (box) {
|
||||||
expect(box.height).toBeGreaterThanOrEqual(28);
|
expect(box.height).toBeGreaterThanOrEqual(44);
|
||||||
|
expect(box.width).toBeGreaterThanOrEqual(44);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ export const MobileMenuDrawer: React.FC<MobileMenuDrawerProps> = ({ isOpen, onCl
|
||||||
|
|
||||||
<button
|
<button
|
||||||
onClick={onClose}
|
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="Закрыть меню"
|
aria-label="Закрыть меню"
|
||||||
data-testid="close-mobile-menu"
|
data-testid="close-mobile-menu"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useLocation, useNavigate } from 'react-router-dom';
|
import { useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { useDemoStore } from '../../mock/store';
|
import { useDemoStore } from '../../mock/store';
|
||||||
import { BUSINESS_PROFILES } from '../../core/profiles/profiles';
|
import { BUSINESS_PROFILES } from '../../core/profiles/profiles';
|
||||||
|
|
@ -96,7 +96,7 @@ export const Topbar: React.FC = () => {
|
||||||
{/* AI Trigger */}
|
{/* AI Trigger */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsAiDrawerOpen(true)}
|
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"
|
title="Krona AI"
|
||||||
aria-label="Krona AI"
|
aria-label="Krona AI"
|
||||||
>
|
>
|
||||||
|
|
@ -106,7 +106,7 @@ export const Topbar: React.FC = () => {
|
||||||
{/* Notifications Trigger */}
|
{/* Notifications Trigger */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsNotificationsOpen(true)}
|
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="Уведомления"
|
title="Уведомления"
|
||||||
aria-label="Уведомления"
|
aria-label="Уведомления"
|
||||||
data-testid="mobile-notifications-btn"
|
data-testid="mobile-notifications-btn"
|
||||||
|
|
@ -120,7 +120,7 @@ export const Topbar: React.FC = () => {
|
||||||
{/* Profile / Menu Drawer Trigger */}
|
{/* Profile / Menu Drawer Trigger */}
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsMobileDrawerOpen(true)}
|
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="Меню управления"
|
title="Меню управления"
|
||||||
aria-label="Открыть меню управления"
|
aria-label="Открыть меню управления"
|
||||||
data-testid="mobile-menu-btn"
|
data-testid="mobile-menu-btn"
|
||||||
|
|
|
||||||
|
|
@ -640,11 +640,11 @@ export const FormBuilder: React.FC = () => {
|
||||||
handleMoveField(section.id, fIdx, Math.max(0, fIdx - 1));
|
handleMoveField(section.id, fIdx, Math.max(0, fIdx - 1));
|
||||||
}}
|
}}
|
||||||
disabled={fIdx === 0}
|
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="Переместить вверх / влево"
|
title="Переместить вверх / влево"
|
||||||
aria-label="Переместить поле выше"
|
aria-label="Переместить поле выше"
|
||||||
>
|
>
|
||||||
<MoveUp className="w-3.5 h-3.5" />
|
<MoveUp className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -658,11 +658,11 @@ export const FormBuilder: React.FC = () => {
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
disabled={fIdx === section.fieldKeys.length - 1}
|
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="Переместить вниз / вправо"
|
title="Переместить вниз / вправо"
|
||||||
aria-label="Переместить поле ниже"
|
aria-label="Переместить поле ниже"
|
||||||
>
|
>
|
||||||
<MoveDown className="w-3.5 h-3.5" />
|
<MoveDown className="w-4 h-4" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue