diff --git a/frontend/src/components/ui/Combobox.tsx b/frontend/src/components/ui/Combobox.tsx index aa87f9ee..5b1eebfc 100644 --- a/frontend/src/components/ui/Combobox.tsx +++ b/frontend/src/components/ui/Combobox.tsx @@ -1,7 +1,8 @@ import clsx from "clsx"; import { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from "react"; import { useTranslation } from "react-i18next"; -import { Check, ChevronDown } from "lucide-react"; +import { ChevronDown } from "lucide-react"; +import { MenuCheck } from "./MenuCheck"; import { PopoverSurface, PopoverItem } from "./AnchoredPopover"; import { useAnchoredPopover } from "./anchoredPopoverHooks"; import { useScrollFade } from "../../lib/useScrollFade"; @@ -285,13 +286,7 @@ export default function Combobox({ renderOption(o, on) ) : ( <> - - {on && } - + {o.label ?? o.value} {o.count != null && ( diff --git a/frontend/src/components/ui/FilterSelect.tsx b/frontend/src/components/ui/FilterSelect.tsx index 49a821be..d310cc06 100644 --- a/frontend/src/components/ui/FilterSelect.tsx +++ b/frontend/src/components/ui/FilterSelect.tsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import { Check } from "lucide-react"; +import { MenuCheck } from "./MenuCheck"; import { SelectTrigger } from "./SelectTrigger"; import { PopoverItem, PopoverSurface } from "./AnchoredPopover"; import { useAnchoredPopover } from "./anchoredPopoverHooks"; @@ -129,17 +129,7 @@ export default function FilterSelect({ on ? "text-fg" : "text-muted" }`} > - {multiple ? ( - - {on && } - - ) : ( - - )} + {o.label} {o.count != null && ( {o.count} diff --git a/frontend/src/components/ui/menuCheck.contract.test.ts b/frontend/src/components/ui/menuCheck.contract.test.ts new file mode 100644 index 00000000..3d9a97f0 --- /dev/null +++ b/frontend/src/components/ui/menuCheck.contract.test.ts @@ -0,0 +1,19 @@ +import { readdirSync, readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; + +// E28 review L2: `ui/MenuCheck` is the ONE drawn check box of a checkable row (S3e3b replaced seven +// hand-drawn copies), yet FilterSelect and Combobox still painted their own — a 14px box beside the +// menus' 16px one. The filled-box paint is the tell: it may live in MenuCheck only. +describe("the drawn check box", () => { + it("is painted by MenuCheck alone", () => { + const root = new URL("../", import.meta.url); + const offenders = readdirSync(root, { recursive: true, encoding: "utf8" }) + .filter((f) => f.endsWith(".tsx") && !f.includes(".test.") && !f.endsWith("MenuCheck.tsx")) + .filter((f) => + /border-accent bg-accent text-accent-fg/.test( + readFileSync(new URL(f.replace(/\\/g, "/"), root), "utf8"), + ), + ); + expect(offenders).toEqual([]); + }); +});