({
onToggle,
offLabel,
onLabel,
isToggled = true,
})
| 75 | } |
| 76 | |
| 77 | const SlideToggle: React.FC<SlideToggleProps> = ({ |
| 78 | onToggle, |
| 79 | offLabel, |
| 80 | onLabel, |
| 81 | isToggled = true, |
| 82 | }) => { |
| 83 | const [toggled, setToggled] = useState(isToggled || false) |
| 84 | const handleToggle = () => { |
| 85 | const newState = !toggled |
| 86 | setToggled(newState) |
| 87 | onToggle?.(newState) |
| 88 | } |
| 89 | |
| 90 | return ( |
| 91 | <SlideToggleContext.Provider value={{ toggled }}> |
| 92 | <motion.button |
| 93 | className="relative flex h-[25px] min-w-[45px] cursor-pointer items-center overflow-hidden rounded-full bg-gray-600/50 outline-offset-2 duration-200 focus-within:outline-red-500/70" |
| 94 | onClick={handleToggle} |
| 95 | style={{ |
| 96 | justifyContent: toggled ? 'end' : 'start', |
| 97 | }} |
| 98 | whileTap="tap" |
| 99 | variants={{ |
| 100 | tap: { scale: 0.95, transition: { duration: 0, delay: 0 } }, |
| 101 | }} |
| 102 | > |
| 103 | <AnimatePresence initial={false}> |
| 104 | {toggled && ( |
| 105 | <motion.span |
| 106 | transition={{ type: 'spring', bounce: 0, duration: 0.6 }} |
| 107 | initial={{ x: '-100%', height: '200%' }} |
| 108 | animate={{ x: 0, height: '300%' }} |
| 109 | exit={{ x: '-100%', height: '200%' }} |
| 110 | className="absolute left-0 flex w-full items-center justify-center rounded-full bg-red-500" |
| 111 | /> |
| 112 | )} |
| 113 | </AnimatePresence> |
| 114 | <motion.span |
| 115 | variants={{ tap: { aspectRatio: '1/.75' } }} |
| 116 | className="absolute z-10 m-[3px] aspect-square h-[calc(100%-6px)] rounded-full bg-white shadow-lg" |
| 117 | layout |
| 118 | transition={{ type: 'spring', bounce: 0, duration: 0.6 }} |
| 119 | style={{ |
| 120 | left: toggled ? 'unset' : '0', |
| 121 | right: toggled ? '0' : 'unset', |
| 122 | }} |
| 123 | /> |
| 124 | {onLabel && offLabel && ( |
| 125 | <> |
| 126 | <Label isOn={false}>{offLabel}</Label> |
| 127 | <Label isOn={true}>{onLabel}</Label> |
| 128 | <div className="pointer-events-none select-none p-2 pr-[25px] opacity-0"> |
| 129 | <span className="text-nowrap">{onLabel}</span> |
| 130 | <br /> |
| 131 | <span className="text-nowrap text-transparent">{offLabel}</span> |
| 132 | </div> |
| 133 | </> |
| 134 | )} |
nothing calls this directly
no outgoing calls
no test coverage detected