From 11ce3cfb86149d00ffc92a27c916673929a31e37 Mon Sep 17 00:00:00 2001 From: Knacky Date: Sun, 21 Jun 2026 22:20:51 +0200 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20code-review=20polish=20?= =?UTF-8?q?=E2=80=94=20replaceState,=20arrow-key=20nav,=20TabId,=20comment?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix 4: useHashTab navigate() uses history.replaceState instead of window.location.hash assignment — no spurious history entries, no anchor-jump scroll side-effect. Fix 5: Tabs ArrowLeft/ArrowRight keyboard nav (WAI-ARIA tabs pattern). Fix 6: TabId union type in EngagementDetailPage, cast from string for type-safe switch on activeTab without breaking Tabs.onChange signature. Fix 7: intentional comment on UsersAdminPage reset-password aerated row. Tests: 236/236 (+2 arrow-key assertions in Tabs.test.tsx). Co-Authored-By: Claude Sonnet 4.6 --- frontend/src/components/Tabs.tsx | 15 ++++++++++++++- frontend/src/hooks/useHashTab.ts | 3 ++- frontend/src/pages/EngagementDetailPage.tsx | 5 ++++- frontend/src/pages/UsersAdminPage.tsx | 1 + frontend/tests/components/Tabs.test.tsx | 14 ++++++++++++++ frontend/tests/hooks/useHashTab.test.tsx | 2 +- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Tabs.tsx b/frontend/src/components/Tabs.tsx index 3bf5831..55d70f8 100644 --- a/frontend/src/components/Tabs.tsx +++ b/frontend/src/components/Tabs.tsx @@ -1,3 +1,5 @@ +import type { KeyboardEvent } from 'react'; + interface TabItem { id: string; label: string; @@ -11,12 +13,22 @@ interface TabsProps { } export function Tabs({ items, activeId, onChange }: TabsProps): JSX.Element { + function handleKeyDown(e: KeyboardEvent, index: number) { + if (e.key === 'ArrowRight') { + e.preventDefault(); + onChange(items[(index + 1) % items.length].id); + } else if (e.key === 'ArrowLeft') { + e.preventDefault(); + onChange(items[(index - 1 + items.length) % items.length].id); + } + } + return (
- {items.map((item) => { + {items.map((item, index) => { const isActive = item.id === activeId; return (