import React from 'react'; import styled from 'styled-components'; import useSound from '@'; import { useSpring, animated } from 'react-spring'; import popDown from '../sounds/pop-down.mp3'; import popUpOn from '../sounds/pop-up-on.mp3'; import popUpOff from '../sounds/pop-up-off.mp3'; import { PRIMARY } from '../helpers/constants'; const BORDER_WIDTH = 2; function CheckboxDemo() { const [isChecked, setIsChecked] = React.useState(false); const [playActive] = useSound(popDown, { id: 'active', volume: 0.25 }); const [playOn] = useSound(popUpOn, { id: 'on', volume: 0.25 }); const [playOff] = useSound(popUpOff, { id: 'off', volume: 0.25 }); return ( <Checkbox name="demo-checkbox" checked={isChecked} size={24} onChange={() => setIsChecked(!isChecked)} onMouseDown={playActive} onMouseUp={() => { isChecked ? playOff() : playOn(); }} /> ); } const Checkbox = ({ size = 18, name, checked, label, onChange, onMouseDown, onMouseUp, }) => { const [active, setActive] = React.useState(false); const springConfig = { tension: 400, friction: 22, clamp: !checked, }; const filledScale = checked ? (active ? 1.4 : 1) : 0; const filledSpring = useSpring({ transform: `scale(${filledScale})`, config: springConfig, }); const outlineScale = active ? 0.8 : 1; const outlineSpring = useSpring({ transform: `scale(${outlineScale})`, config: springConfig, }); return ( <Wrapper> <RealCheckbox onMouseDown={() => { setActive(true); onMouseDown(); }} onMouseUp={() => { setActive(false); onMouseUp(); }} onChange={onChange} onClick={onChange} /> <VisibleContents> <VisibleBox style={{ width: size, height: size, ...outlineSpring }}> <Filled style={filledSpring} /> </VisibleBox> <Text>{label}</Text> </VisibleContents> </Wrapper> ); }; const Wrapper = styled.div` position: relative; `; const RealCheckbox = styled.input.attrs({ type: 'checkbox' })` position: absolute; z-index: 2; top: 0; left: 0; right: 0; bottom: 0; width: 100%; height: 100%; opacity: 0; `; const VisibleContents = styled.div` position: relative; z-index: 1; display: flex; align-items: center; `; const VisibleBox = styled(animated.div)` position: relative; border: ${BORDER_WIDTH}px solid #555; border-radius: 4px; margin-right: 8px; ${RealCheckbox}:hover + ${VisibleContents} & { border-color: #111; } ${RealCheckbox}:focus.focus-visible + ${VisibleContents} & { outline: 2px auto ${PRIMARY}; outline-offset: 2px; } `; const Filled = styled(animated.div)` position: absolute; z-index: 1; top: 2px; left: 2px; right: 2px; bottom: 2px; background: ${PRIMARY}; border-radius: 2px; `; const Text = styled.span` font-size: 16px; font-family: var(--font-family); color: #555; `; export default CheckboxDemo;