diff --git a/src/components/ui/ToggleSwitch.module.scss b/src/components/ui/ToggleSwitch.module.scss new file mode 100644 index 0000000..09045cb --- /dev/null +++ b/src/components/ui/ToggleSwitch.module.scss @@ -0,0 +1,58 @@ +.root { + position: relative; + display: inline-flex; + align-items: center; + gap: $spacing-sm; + cursor: pointer; +} + +.labelLeft { + .label { + order: -1; + } +} + +.disabled { + cursor: not-allowed; +} + +.root input { + width: 0; + height: 0; + opacity: 0; + position: absolute; +} + +.track { + width: 44px; + height: 24px; + background: var(--border-color); + border-radius: $radius-full; + position: relative; + transition: background $transition-fast; +} + +.thumb { + position: absolute; + top: 3px; + left: 3px; + width: 18px; + height: 18px; + background: #fff; + border-radius: $radius-full; + box-shadow: $shadow-sm; + transition: transform $transition-fast; +} + +.root input:checked + .track { + background: var(--primary-color); +} + +.root input:checked + .track .thumb { + transform: translateX(20px); +} + +.label { + color: var(--text-primary); + font-weight: 600; +} diff --git a/src/components/ui/ToggleSwitch.tsx b/src/components/ui/ToggleSwitch.tsx index 3fbaa62..7256c62 100644 --- a/src/components/ui/ToggleSwitch.tsx +++ b/src/components/ui/ToggleSwitch.tsx @@ -1,4 +1,5 @@ import type { ChangeEvent, ReactNode } from 'react'; +import styles from './ToggleSwitch.module.scss'; interface ToggleSwitchProps { checked: boolean; @@ -21,7 +22,11 @@ export function ToggleSwitch({ onChange(event.target.checked); }; - const className = ['switch', labelPosition === 'left' ? 'switch-label-left' : ''] + const className = [ + styles.root, + labelPosition === 'left' ? styles.labelLeft : '', + disabled ? styles.disabled : '', + ] .filter(Boolean) .join(' '); @@ -34,10 +39,10 @@ export function ToggleSwitch({ disabled={disabled} aria-label={ariaLabel} /> - - + + - {label && {label}} + {label && {label}} ); }