"use client"; import { memo, useCallback, useId, forwardRef } from "react"; import { SwitchView } from "./Switch.view"; import type { SwitchProps } from "./Switch.types"; /** * Figma: "Control / Switch" (TODO(figma)). Animated on/off toggle switch, * optionally paired with a trailing text label. */ const SwitchContainer = memo( forwardRef((props, ref) => { const { propSwitch = false, onChange, onFocus, onBlur, state: stateProp = "default", text, className = "", ...rest } = props; const state = stateProp; const switchId = useId(); const handleClick = useCallback( (e: React.MouseEvent) => { if (onChange) { onChange(e); } }, [onChange], ); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); if (onChange) { onChange(e); } } }, [onChange], ); const handleFocus = useCallback( (e: React.FocusEvent) => { if (onFocus) { onFocus(e); } }, [onFocus], ); const handleBlur = useCallback( (e: React.FocusEvent) => { if (onBlur) { onBlur(e); } }, [onBlur], ); // Switch track styles based on propSwitch state const getTrackStyles = useCallback(() => { return propSwitch ? "bg-[var(--color-surface-inverse-tertiary)]" : "bg-[var(--color-surface-default-tertiary)]"; }, [propSwitch]); // Switch thumb styles based on propSwitch state const getThumbStyles = useCallback(() => { return "bg-[var(--color-gray-000)]"; }, []); // Focus styles const getFocusStyles = useCallback(() => { if (state === "focus") { return "shadow-[0_0_5px_3px_#3281F8] rounded-full"; } return ""; }, [state]); const trackStyles = getTrackStyles(); const thumbStyles = getThumbStyles(); const focusStyles = getFocusStyles(); const switchClasses = ` relative inline-flex items-center cursor-pointer transition-all duration-200 focus:outline-none focus-visible:shadow-[0_0_5px_3px_#3281F8] focus-visible:rounded-full ${focusStyles} ${className} ` .trim() .replace(/\s+/g, " "); const trackClasses = ` ${trackStyles} w-[40px] h-[24px] rounded-full transition-all duration-200 flex items-center ${propSwitch ? "justify-end" : "justify-start"} p-[2px] ` .trim() .replace(/\s+/g, " "); const thumbClasses = ` ${thumbStyles} w-[var(--measures-sizing-020)] h-[var(--measures-sizing-020)] rounded-[var(--measures-radius-xlarge)] transition-all duration-200 shadow-sm ` .trim() .replace(/\s+/g, " "); const labelClasses = ` ml-[var(--measures-spacing-008)] font-inter font-normal text-[14px] leading-[20px] text-[var(--color-content-default-primary)] ` .trim() .replace(/\s+/g, " "); return ( ); }), ); SwitchContainer.displayName = "Switch"; export default SwitchContainer;