File size: 2,468 Bytes
9b906ea | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import React from "react";
import { Check } from "lucide-react";
import { cn } from "#/utils/utils";
import {
dropdownMenuRowClassName,
dropdownMenuRowIconClassName,
} from "#/utils/dropdown-classes";
import { ToggleSwitchVisual } from "#/ui/toggle-switch";
export function MenuRow({
icon: Icon,
label,
sublabel,
selected,
onClick,
testId,
disabled,
destructive,
variant = "radio",
}: {
icon: React.ComponentType<{ className?: string; "aria-hidden"?: boolean }>;
label: string;
/** Muted second line under the label (e.g. a threshold hint). */
sublabel?: string;
selected?: boolean;
onClick: () => void;
testId?: string;
disabled?: boolean;
/** Destructive action rows (delete/reset) render in the danger color. */
destructive?: boolean;
/**
* "radio" rows mark selection with a checkmark (mutually exclusive
* groups); "toggle" rows render a switch pill for independent on/off
* preferences that stay put after clicking (modal-style menus).
*/
variant?: "radio" | "toggle";
}) {
const role =
selected === undefined
? "menuitem"
: variant === "toggle"
? "menuitemcheckbox"
: "menuitemradio";
return (
<button
type="button"
role={role}
aria-checked={selected === undefined ? undefined : Boolean(selected)}
data-testid={testId}
disabled={disabled}
onClick={onClick}
className={cn(
"group",
dropdownMenuRowClassName,
"disabled:opacity-50",
destructive ? "text-danger" : "text-[var(--oh-foreground)]",
)}
>
<Icon
className={cn(
"h-3.5 w-3.5",
dropdownMenuRowIconClassName,
destructive &&
"text-danger group-hover:text-danger group-focus-visible:text-danger",
)}
aria-hidden
/>
<span className="min-w-0 flex-1">
<span className="block truncate">{label}</span>
{sublabel ? (
<span className="block truncate text-[10px] text-[var(--oh-muted)]/70">
{sublabel}
</span>
) : null}
</span>
{selected === undefined ? null : variant === "toggle" ? (
<ToggleSwitchVisual
enabled={Boolean(selected)}
size="sm"
className="ml-auto"
/>
) : selected ? (
<Check
className="ml-auto h-3.5 w-3.5 shrink-0 text-white"
aria-hidden
/>
) : null}
</button>
);
}
|