refactor(design): one drawn check for every checkable row that cannot be an input (E28 S3e3b)

ui/MenuCheck: a box filled with the accent for a set (a minus for a group
only partly in), a bare tick for one choice, in the row's leading slot.
Replaces seven hand-drawn marks: three box sizes, a tinted box, a cross
for "on" in the table filter, a trailing tick in the language menu.
This commit is contained in:
2026-09-26 17:34:46 +02:00
parent 9c91eb5d22
commit 2b3094ffc5
10 changed files with 56 additions and 55 deletions
+29
View File
@@ -0,0 +1,29 @@
import { Check, Minus } from "lucide-react";
// The ONE drawn check of a checkable row that cannot hold the browser's own checkbox (A6) — a menu
// row, or a whole-row button whose `role` says checkbox: an `<input>` inside a `<button>` is invalid
// nesting. It sits in the row's leading icon slot, so every label in a list starts at the same x.
// - `many`: one of a set that can all be on (tags, playlists, a filter's values) — a box, filled
// with the accent when on; `mixed` for a group only partly in (a Plex show's episodes).
// - `one`: one choice of several (a language, a sort, a priority step) — a bare tick; an unticked
// choice keeps the slot empty.
// Decorative: the row carries the state (`aria-checked` on its menuitemcheckbox / radio / checkbox).
export function MenuCheck({ kind, on }: { kind: "many" | "one"; on: boolean | "mixed" }) {
if (kind === "one")
return (
<Check
aria-hidden="true"
className={`size-4 shrink-0 ${on === true ? "text-accent" : "opacity-0"}`}
/>
);
return (
<span
aria-hidden="true"
className={`grid size-4 shrink-0 place-items-center rounded border ${
on ? "border-accent bg-accent text-accent-fg" : "border-border"
}`}
>
{on === "mixed" ? <Minus className="size-3" /> : on && <Check className="size-3" />}
</span>
);
}