"use client"; import * as React from "react"; import * as SwitchPrimitives from "@radix-ui/react-switch"; import { cn } from "~/utils/cn"; import { type ShortcutDefinition, useShortcutKeys } from "~/hooks/useShortcutKeys"; const small = { container: "flex items-center h-6 gap-x-1.5 rounded hover:bg-tertiary pr-1 py-[0.1rem] pl-1.5 hover:disabled:bg-background-raised transition focus-custom disabled:opacity-50 text-text-dimmed hover:text-text-bright disabled:hover:cursor-not-allowed hover:cursor-pointer disabled:hover:text-rose-500", root: "h-3 w-6", thumb: "size-2.5 data-[state=checked]:translate-x-2.5 data-[state=unchecked]:translate-x-0", text: "text-xs text-text-dimmed", }; const variations = { large: { container: "flex items-center gap-x-2 rounded-md hover:bg-tertiary p-2 transition focus-custom", root: "h-6 w-11", thumb: "size-5 data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0", text: "text-sm text-text-dimmed", }, small, "tertiary/small": { container: small.container, root: cn( small.root, "group-data-[state=unchecked]:bg-surface-control group-hover:group-data-[state=unchecked]:bg-surface-control-active/50" ), thumb: small.thumb, text: cn( small.text, "transition group-hover:text-text-bright group-hover:group-disabled:text-text-dimmed" ), }, "secondary/small": { container: cn( small.container, "border border-border-bright hover:border-border-brighter bg-secondary hover:bg-surface-control" ), root: cn( small.root, "group-data-[state=unchecked]:bg-surface-control-hover group-hover:group-data-[state=unchecked]:bg-surface-control-active" ), thumb: small.thumb, text: cn(small.text, "transition text-text-bright group-hover:group-disabled:text-text-dimmed"), }, medium: { container: "flex items-center gap-x-2 rounded-md hover:bg-tertiary py-1.5 px-2 transition focus-custom", root: "h-4 w-8", thumb: "size-3.5 data-[state=checked]:translate-x-3.5 data-[state=unchecked]:translate-x-0", text: "text-sm text-text-dimmed", }, }; type SwitchProps = React.ComponentPropsWithoutRef & { label?: React.ReactNode; variant: keyof typeof variations; shortcut?: ShortcutDefinition; labelPosition?: "left" | "right"; }; export const Switch = React.forwardRef, SwitchProps>( ({ className, variant, label, labelPosition = "left", ...props }, ref) => { const innerRef = React.useRef(null); React.useImperativeHandle(ref, () => innerRef.current as HTMLButtonElement); const { container, root, thumb, text } = variations[variant]; if (props.shortcut) { useShortcutKeys({ shortcut: props.shortcut, action: () => { if (innerRef.current) { innerRef.current.click(); } }, disabled: props.disabled, }); } const labelElement = label ? ( ) : null; const switchElement = (
); return ( {labelPosition === "left" ? labelElement : null} {switchElement} {labelPosition === "right" ? labelElement : null} ); } );