Frontend design-kit consistency: dead Card, duplicated segmented-control + row/icon recipes, focusRing/useLang drift #66
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: Low–Medium. From a frontend deep audit, 2026-06-08.
check:colorspasses and the app is hex-free + dark-mode-clean; these are the subtler consistency issues the guard doesn't catch.Problems
Cardcomponent.components/ui/card.tsxhas zero importers (app/tests/stories) while the app hand-builds card-like surfaces. Rots and misleads.objects-table.tsx:173(px-2 py-1, no focusRing),search-panel.tsx:76(px-2 py-0.5, focusRing),authorities-page.tsx:75(px-3 py-1 text-sm, focusRing). (The missing focus ring is tracked as an a11y defect in the a11y bundle issue.)langderivationi18n.language.startsWith("sv") ? "sv" : "en"duplicated 6× —object-detail.tsx:59,field-input.tsx:32,vocabulary-terms.tsx:24,vocabulary-list.tsx:16,field-list.tsx:27,authorities-page.tsx:28.focusRingconstant re-inlined as a raw string inshell/sidebar.tsx:46,88(every other call site importslib/focus-ring.ts).bg-primary/10/hover:bg-muted) duplicated 4× —objects-table.tsx:257,vocabulary-list.tsx:120,search-result-row.tsx:15,field-list.tsx:86(last omits the hover fallback).objects-page.tsx:54+object-detail-drawer.tsx:33instead ofButton variant="ghost" size="icon-sm".login-page.tsx:49raw<h1>instead of<PageTitle>(also dropstracking-tight); type-tag pill atfield-list.tsx:97should be<Badge variant="secondary">; mixedh-4 w-4vssize-4icon sizing (user-menu,theme-switch,header-search); inconsistent formspace-y-*density scale.Suggested fix
Extract a
SegmentedControl/ToggleGroup(or aButtonvariant) intocomponents/ui/; add auseLang()hook; import thefocusRingconstant in sidebar; arowStateClasses(isActive)helper for selected rows; adopt the kit's icon button +PageTitle+Badge; standardize onsize-4and one form-density scale. ResolveCard(adopt for detail/list surfaces or delete).Source: frontend deep audit (design-system dimension), 2026-06-08.
Done in merge
7cabebc.Shared helpers (stop future drift):
lib/use-lang.ts—useLang(): "sv" | "en"replaces the inlinei18n.language.startsWith("sv")derivation in 6 components.lib/class-recipes.ts—segmentClass(active, className?)(adopted at the 3 segmented sites — objects-table pill, search-panel facet, authorities NavLink — unifying the recipe + focus ring while keeping contextual padding) androwStateClass(active)(adopted at the 4 selected-row sites; fixes field-list's row, which was missing thehover:bg-mutedidle hover).One-off kit adoption: deleted the dead
components/ui/card.tsx; sidebar now imports thefocusRingconstant; login uses<PageTitle>(restorestracking-tight); field-list type-tag →<Badge variant="secondary">;h-4 w-4→size-4in theme-switch/user-menu/header-search; both object-detail close buttons →Button variant="ghost" size="icon-sm"(the drawer via Base UI'srenderprop).Behavior-preserving (className token sets byte-equivalent except field-list's intended added hover). 268 tests pass unchanged; typecheck/lint/build clean; check:size 216.5 KB gz (identical to baseline); check:colors clean; no new dependency; no new i18n keys; no codename.
Deferred (out of scope): a full
<SegmentedControl>/<ToggleGroup>component (the button-vs-NavLink interaction split makes a class helper the better fit) and the subjective formspace-y-*spacing scale.