prepare switch component.
This commit is contained in:
		
							
								
								
									
										46
									
								
								src/components/Switch.module.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/components/Switch.module.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| @layer components { | ||||
|   .switch { | ||||
|     display: inline-flex; | ||||
|     align-items: center; | ||||
|     gap: 1em; | ||||
|     cursor: pointer; | ||||
|     &[aria-disabled] { | ||||
|       cursor: not-allowed; | ||||
|     } | ||||
|   } | ||||
|   .switch_handle { | ||||
|     position: relative; | ||||
|     width: calc(var(--spacing) * 9); | ||||
|     height: calc(var(--spacing) * 5); | ||||
|     border: 1px solid var(--color-primary); | ||||
|     border-radius: calc(var(--border-radius) * 2); | ||||
|     background-color: var(--color-surface-container-high); | ||||
|     &::before { | ||||
|       content: ''; | ||||
|       position: absolute; | ||||
|       transform: translate(1px, 2px); | ||||
|       width: calc(var(--spacing) * 3); | ||||
|       height: calc(var(--spacing) * 3); | ||||
|       border-radius: calc(var(--border-radius) * 2); | ||||
|       background-color: var(--color-primary); | ||||
|       transition: transform 0.2s ease-in-out; | ||||
|     } | ||||
|     &.checked { | ||||
|       background-color: var(--color-primary); | ||||
|       &::before { | ||||
|         transform: translate(calc(var(--spacing) * 5 - 1px), 2px); | ||||
|       } | ||||
|       [aria-disabled] & { | ||||
|         --disabled-color: color-mix(in oklch, var(--color-on-surface) 38%, transparent); | ||||
|         background-color: var(--disabled-color); | ||||
|         border-color: var(--disabled-color); | ||||
|         &.checked { | ||||
|           background-color: var(--disabled-color); | ||||
|         } | ||||
|         &::before { | ||||
|           background-color: color-mix(in oklch, var(--color-on-surface) 45%, transparent); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/components/Switch.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/components/Switch.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| import cx from 'clsx'; | ||||
| import { FC, useCallback, useEffect, useState } from 'react'; | ||||
| import styles from './Switch.module.css'; | ||||
|  | ||||
| type SwitchProps = { | ||||
|   name?: string; | ||||
|   checked?: boolean; | ||||
|   disabled?: boolean; | ||||
|   onChange?: (checked: boolean) => void; | ||||
| }; | ||||
|  | ||||
| const Switch: FC<SwitchProps> = ({ name, checked = false, disabled = false, onChange }) => { | ||||
|   const [isChecked, setChecked] = useState(checked); | ||||
|   const handleChange = useCallback(() => { | ||||
|     if (!disabled) { | ||||
|       setChecked((prev) => !prev); | ||||
|       onChange?.(!isChecked); | ||||
|     } | ||||
|   }, [disabled, onChange, isChecked]); | ||||
|  | ||||
|   useEffect(() => { | ||||
|     if (checked !== isChecked) { | ||||
|       setChecked(checked); | ||||
|     } | ||||
|   }, [checked]); | ||||
|  | ||||
|   return ( | ||||
|     <div aria-disabled={disabled} className={styles.switch}> | ||||
|       <div | ||||
|         className={cx(styles.switch_handle, isChecked && styles.checked)} | ||||
|         onClick={handleChange} | ||||
|       /> | ||||
|       {name !== undefined && ( | ||||
|         <input type="hidden" name={name} value={isChecked ? 'true' : 'false'} /> | ||||
|       )} | ||||
|     </div> | ||||
|   ); | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user