File size: 2,101 Bytes
5f40163
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import { cn } from "#/utils/utils";

export type ToggleSwitchSize = "md" | "sm";

interface ToggleSwitchVisualProps {
  enabled: boolean;
  /** `sm` is the compact menu-row pill; `md` is the settings/automation switch. */
  size?: ToggleSwitchSize;
  className?: string;
}

/** Shared toggle track + thumb used by settings labels and automation controls. */
export function ToggleSwitchVisual({
  enabled,
  size = "md",
  className,
}: ToggleSwitchVisualProps) {
  const compact = size === "sm";
  return (
    <span
      aria-hidden="true"
      className={cn(
        "relative inline-flex shrink-0 items-center rounded-full",
        "transition-colors duration-200 ease-in-out motion-reduce:transition-none",
        compact ? "h-3.5 w-6 p-[3px]" : "h-[22px] w-[40px] border",
        enabled
          ? compact
            ? "bg-white"
            : "border-white bg-white"
          : compact
            ? "bg-[var(--oh-border)]"
            : "border-[var(--oh-border)] bg-surface-raised",
        className,
      )}
    >
      <span
        className={cn(
          "inline-block rounded-full",
          "transition-transform duration-200 ease-in-out motion-reduce:transition-none",
          compact ? "size-2" : "size-4",
          enabled
            ? compact
              ? "translate-x-[10px] bg-base-secondary"
              : "translate-x-[21px] bg-base-secondary"
            : compact
              ? "translate-x-0 bg-[var(--oh-muted)]"
              : "translate-x-[2px] bg-[var(--oh-muted)]",
        )}
      />
    </span>
  );
}

interface ToggleSwitchProps {
  enabled: boolean;
  label: string;
  onToggle: () => void;
  className?: string;
}

export function ToggleSwitch({
  enabled,
  label,
  onToggle,
  className,
}: ToggleSwitchProps) {
  return (
    <button
      type="button"
      role="switch"
      aria-checked={enabled}
      aria-label={label}
      onClick={(e) => {
        e.stopPropagation();
        onToggle();
      }}
      className={cn("cursor-pointer", className)}
    >
      <ToggleSwitchVisual enabled={enabled} />
    </button>
  );
}