From 1959283a414fb3e650c54d55e966cc52c5f4fddb Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 17 May 2026 16:16:24 +0300 Subject: [PATCH] =?UTF-8?q?fix(sf-11):=20review-pass=20=E2=80=94=20DOM.?= =?UTF-8?q?=D0=A0=D0=A4=20latin=20URL=20+=20Fragment=20key=20+=20a11y=20ke?= =?UTF-8?q?yboard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per review #285 (HIGH BLOCK): - DOM.РФ URL: кириллический slug → latin path (/services/catalog-newbuildings/object/{id}) для stable behavior - Replace <> Fragment без key → (убирает React warning при .map). Closing → - a11y: теперь имеет tabIndex, role="button", aria-expanded, onKeyDown (Enter/Space) — keyboard drill-in Inline hex tokens (medium) — отложено в follow-up (epic #271 #19). --- frontend/package-lock.json | 2 +- frontend/package.json | 2 +- .../site-finder/BestLayoutsBlock.tsx | 22 ++++++++++++++----- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 55c1e0d4..fb9a9d9b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -32,7 +32,7 @@ "openapi-typescript": "^7.0.0", "postcss": "^8.4.0", "tailwindcss": "^4.0.0", - "typescript": "^5.5.0" + "typescript": "5.9.3" } }, "node_modules/@alloc/quick-lru": { diff --git a/frontend/package.json b/frontend/package.json index f1c8daac..f79f586c 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,6 +35,6 @@ "openapi-typescript": "^7.0.0", "postcss": "^8.4.0", "tailwindcss": "^4.0.0", - "typescript": "^5.5.0" + "typescript": "5.9.3" } } diff --git a/frontend/src/components/site-finder/BestLayoutsBlock.tsx b/frontend/src/components/site-finder/BestLayoutsBlock.tsx index fc01b9cc..99394dbc 100644 --- a/frontend/src/components/site-finder/BestLayoutsBlock.tsx +++ b/frontend/src/components/site-finder/BestLayoutsBlock.tsx @@ -1,6 +1,6 @@ "use client"; -import { useState } from "react"; +import { Fragment, useState } from "react"; import { useBestLayouts } from "@/hooks/useBestLayouts"; import { API_BASE_URL } from "@/lib/api"; import type { @@ -109,7 +109,7 @@ function CompetitorDrillIn({ {visible.map((id) => ( 0; return ( - <> + { if (hasCompetitors) toggleRow(row.signature); }} + onKeyDown={(e) => { + if ( + hasCompetitors && + (e.key === "Enter" || e.key === " ") + ) { + e.preventDefault(); + toggleRow(row.signature); + } + }} + tabIndex={hasCompetitors ? 0 : undefined} + role={hasCompetitors ? "button" : undefined} + aria-expanded={hasCompetitors ? isExpanded : undefined} style={{ background: i % 2 === 0 ? "#fff" : "#fafbfc", borderBottom: isExpanded ? "none" : "1px solid #f3f4f6", @@ -352,12 +363,11 @@ function TopLayoutsTable({ rows }: { rows: TopLayoutRow[] }) { {isExpanded && hasCompetitors && ( )} - + ); })}