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>
  );
}