From 900f85f8ac98a3d06620bd2f85cc137ca3f17175 Mon Sep 17 00:00:00 2001 From: Anders Olsson Date: Mon, 8 Jun 2026 23:45:24 +0200 Subject: [PATCH] refactor(web): adopt useLang + segmentClass/rowStateClass across sites (#66) --- web/src/authorities/authorities-page.tsx | 12 +++++------- web/src/fields/field-list.tsx | 12 +++++++----- web/src/objects/field-input.tsx | 5 +++-- web/src/objects/object-detail.tsx | 5 +++-- web/src/objects/objects-table.tsx | 7 +++---- web/src/search/search-panel.tsx | 5 ++--- web/src/search/search-result-row.tsx | 3 ++- web/src/vocab/vocabulary-list.tsx | 8 +++++--- web/src/vocab/vocabulary-terms.tsx | 5 +++-- 9 files changed, 33 insertions(+), 29 deletions(-) diff --git a/web/src/authorities/authorities-page.tsx b/web/src/authorities/authorities-page.tsx index 85035c6..a21afb6 100644 --- a/web/src/authorities/authorities-page.tsx +++ b/web/src/authorities/authorities-page.tsx @@ -6,17 +6,17 @@ import { FilteredRecordList } from "../components/filtered-record-list"; import { LabelledRecordCreateForm } from "../components/labelled-record-create-form"; import { PageTitle } from "@/components/ui/page-title"; import { AuthorityRow } from "./authority-row"; -import { focusRing } from "../lib/focus-ring"; +import { useLang } from "../lib/use-lang"; +import { segmentClass } from "../lib/class-recipes"; import { useDocumentTitle } from "../lib/use-document-title"; import { useBreadcrumb } from "../shell/use-breadcrumb"; -import { cn } from "@/lib/utils"; const KINDS = ["person", "organisation", "place"] as const; export function AuthoritiesPage() { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const { kind } = useParams(); - const lang = i18n.language.startsWith("sv") ? "sv" : "en"; + const lang = useLang(); const isValidKind = (KINDS as readonly string[]).includes(kind ?? ""); const currentKind = isValidKind ? (kind as string) : "person"; @@ -37,9 +37,7 @@ export function AuthoritiesPage() { - cn("rounded-md px-3 py-1 text-sm", focusRing, isActive ? "bg-primary text-primary-foreground" : "border") - } + className={({ isActive }) => segmentClass(isActive, "px-3 py-1 text-sm")} > {t(`authorities.${k}`)} diff --git a/web/src/fields/field-list.tsx b/web/src/fields/field-list.tsx index 1838ddd..9888734 100644 --- a/web/src/fields/field-list.tsx +++ b/web/src/fields/field-list.tsx @@ -3,6 +3,8 @@ import { useTranslation } from "react-i18next"; import type { components } from "../api/schema"; import { useFieldDefinitions, useDeleteFieldDefinition } from "../api/queries"; +import { useLang } from "../lib/use-lang"; +import { rowStateClass } from "../lib/class-recipes"; import { labelText } from "../lib/labels"; import { byLabel, compareStrings } from "../lib/sort"; import { focusRing } from "../lib/focus-ring"; @@ -21,10 +23,10 @@ export function FieldList({ selectedKey: string | null; onSelect: (def: FieldDefinitionView) => void; }) { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const { data, isLoading, isError } = useFieldDefinitions(); const deleteField = useDeleteFieldDefinition(); - const lang = i18n.language.startsWith("sv") ? "sv" : "en"; + const lang = useLang(); const [filter, setFilter] = useState(""); if (isLoading) return ; @@ -82,9 +84,9 @@ export function FieldList({ {[...defs].sort(byLabel(lang)).map((def) => (
  • @@ -248,9 +249,7 @@ export function ObjectsTable() { navigate(`/objects/${object.id}?${params}`)} - className={`cursor-pointer border-b text-sm ${ - selected ? "bg-primary/10" : "hover:bg-muted" - }`} + className={`cursor-pointer border-b text-sm ${rowStateClass(selected)}`} > setVisibility(value)} - className={cn("rounded-md px-2 py-0.5", focusRing, active ? "bg-primary text-primary-foreground" : "border")} + className={segmentClass(active, "px-2 py-0.5")} > {value === "all" ? t("search.all") : t(`visibility.${value}`)} diff --git a/web/src/search/search-result-row.tsx b/web/src/search/search-result-row.tsx index 5f54d56..99ae43f 100644 --- a/web/src/search/search-result-row.tsx +++ b/web/src/search/search-result-row.tsx @@ -2,6 +2,7 @@ import { NavLink } from "react-router-dom"; import type { components } from "../api/schema"; import { VisibilityBadge } from "../objects/visibility-badge"; +import { rowStateClass } from "../lib/class-recipes"; import { Highlight } from "./highlight"; type SearchHitView = components["schemas"]["SearchHitView"]; @@ -12,7 +13,7 @@ export function SearchResultRow({ hit }: { hit: SearchHitView }) { - `block border-b px-3 py-2 ${isActive ? "bg-primary/10" : "hover:bg-muted"}` + `block border-b px-3 py-2 ${rowStateClass(isActive)}` } >
    {hit.object_name}
    diff --git a/web/src/vocab/vocabulary-list.tsx b/web/src/vocab/vocabulary-list.tsx index 581d09b..9f0ecec 100644 --- a/web/src/vocab/vocabulary-list.tsx +++ b/web/src/vocab/vocabulary-list.tsx @@ -3,6 +3,8 @@ import { NavLink } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useVocabularies, useCreateVocabulary, useRenameVocabulary, useDeleteVocabulary } from "../api/queries"; +import { useLang } from "../lib/use-lang"; +import { rowStateClass } from "../lib/class-recipes"; import { byKey } from "../lib/sort"; import { DeleteConfirmDialog } from "../components/delete-confirm-dialog"; import { MutationError } from "../components/mutation-error"; @@ -12,9 +14,9 @@ import { Label } from "@/components/ui/label"; import { ListSkeleton } from "@/components/ui/skeletons"; export function VocabularyList() { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); - const lang = i18n.language.startsWith("sv") ? "sv" : "en"; + const lang = useLang(); const { data, isLoading, isError } = useVocabularies(); @@ -110,7 +112,7 @@ export function VocabularyList() { - `block flex-1 px-3 py-2 text-sm ${isActive ? "bg-primary/10" : "hover:bg-muted"}` + `block flex-1 px-3 py-2 text-sm ${rowStateClass(isActive)}` } > {v.key} diff --git a/web/src/vocab/vocabulary-terms.tsx b/web/src/vocab/vocabulary-terms.tsx index 402379e..d8705e8 100644 --- a/web/src/vocab/vocabulary-terms.tsx +++ b/web/src/vocab/vocabulary-terms.tsx @@ -2,15 +2,16 @@ import { useParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { useTerms, useAddTerm, useVocabularies } from "../api/queries"; +import { useLang } from "../lib/use-lang"; import { useBreadcrumb } from "../shell/use-breadcrumb"; import { FilteredRecordList } from "../components/filtered-record-list"; import { LabelledRecordCreateForm } from "../components/labelled-record-create-form"; import { TermRow } from "./term-row"; export function VocabularyTerms() { - const { t, i18n } = useTranslation(); + const { t } = useTranslation(); const { id } = useParams(); - const lang = i18n.language.startsWith("sv") ? "sv" : "en"; + const lang = useLang(); const { data: terms, isLoading, isError } = useTerms(id); const addTerm = useAddTerm();