diff --git a/web/src/authorities/authorities-page.tsx b/web/src/authorities/authorities-page.tsx index 37c2b5f..1ce4268 100644 --- a/web/src/authorities/authorities-page.tsx +++ b/web/src/authorities/authorities-page.tsx @@ -13,8 +13,10 @@ import { ListSkeleton } from "@/components/ui/skeletons"; import { AuthorityRow } from "./authority-row"; import { byLabel } from "../lib/sort"; import { labelText } from "../lib/labels"; +import { focusRing } from "../lib/focus-ring"; import { useDocumentTitle } from "../lib/use-document-title"; import { useBreadcrumb } from "../shell/use-breadcrumb"; +import { cn } from "@/lib/utils"; type LabelInput = components["schemas"]["LabelInput"]; @@ -64,21 +66,19 @@ export function AuthoritiesPage() { return (
{t("nav.authorities")} -
+
+
{ test("kind tabs link to the other kinds", async () => { renderApp(tree(), { route: "/authorities/person" }); - expect(await screen.findByRole("tab", { name: /place/i })).toHaveAttribute("href", "/authorities/place"); + expect(await screen.findByRole("link", { name: /place/i })).toHaveAttribute("href", "/authorities/place"); }); -test("aria-selected is on the tab element and reflects the active kind", async () => { +test("aria-current marks the active kind link", async () => { renderApp(tree(), { route: "/authorities/person" }); - expect(await screen.findByRole("tab", { name: /^person$/i })).toHaveAttribute("aria-selected", "true"); - expect(screen.getByRole("tab", { name: /^place$/i })).toHaveAttribute("aria-selected", "false"); + expect(await screen.findByRole("link", { name: /^person$/i })).toHaveAttribute("aria-current", "page"); + expect(screen.getByRole("link", { name: /^place$/i })).not.toHaveAttribute("aria-current"); }); test("create without EN label shows required alert and does not POST", async () => { diff --git a/web/src/fields/field-list.tsx b/web/src/fields/field-list.tsx index 110259c..1838ddd 100644 --- a/web/src/fields/field-list.tsx +++ b/web/src/fields/field-list.tsx @@ -5,8 +5,10 @@ import type { components } from "../api/schema"; import { useFieldDefinitions, useDeleteFieldDefinition } from "../api/queries"; import { labelText } from "../lib/labels"; import { byLabel, compareStrings } from "../lib/sort"; +import { focusRing } from "../lib/focus-ring"; import { DeleteConfirmDialog } from "../components/delete-confirm-dialog"; import { Badge } from "@/components/ui/badge"; +import { cn } from "@/lib/utils"; import { Input } from "@/components/ui/input"; import { ListSkeleton } from "@/components/ui/skeletons"; @@ -86,7 +88,7 @@ export function FieldList({ > diff --git a/web/src/shell/lang-switch.tsx b/web/src/shell/lang-switch.tsx index 0e2e2a2..628fe2d 100644 --- a/web/src/shell/lang-switch.tsx +++ b/web/src/shell/lang-switch.tsx @@ -1,17 +1,23 @@ +import { useTranslation } from "react-i18next"; + import { useLocale } from "../i18n/use-locale"; +import { focusRing } from "../lib/focus-ring"; +import { cn } from "@/lib/utils"; export function LangSwitch() { + const { t } = useTranslation(); const { locale, setLocale } = useLocale(); const base = locale.startsWith("sv") ? "sv" : "en"; return ( -
+
{(["sv", "en"] as const).map((lng) => ( diff --git a/web/src/shell/theme-switch.tsx b/web/src/shell/theme-switch.tsx index e366376..266751b 100644 --- a/web/src/shell/theme-switch.tsx +++ b/web/src/shell/theme-switch.tsx @@ -3,6 +3,7 @@ import { useTranslation } from "react-i18next"; import { useTheme } from "../theme/use-theme"; import type { Theme } from "../theme/theme"; +import { focusRing } from "../lib/focus-ring"; import { cn } from "@/lib/utils"; const OPTIONS: { value: Theme; Icon: typeof Sun }[] = [ @@ -29,6 +30,7 @@ export function ThemeSwitch() { title={t(`theme.${value}`)} className={cn( "rounded-md p-1 transition-colors", + focusRing, active ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground",