Files
siftlode/frontend/src/components/ui/MenuCheck.tsx
T
peter 8312c6d592 fix(player): what is chosen on the player chrome is marked amber, not written in the accent
A light theme's accent as text on the always-dark chrome was 2.84:1 (Slate). `--chosen` is the
accent unless a scope names its own; `media-marks` (was media-focus) points it, with the focus
ring, at the media amber. A chosen track stays white with an amber tick (MenuCheck reads
`text-chosen`); a chosen settings tab or toggle is white with an amber underline (MEDIA_CHOSEN).
The theme contract test holds the token, the tick and the player components free of accent text.
2026-10-10 21:56:47 +02:00

30 lines
1.3 KiB
TypeScript

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-chosen" : "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>
);
}