From d1d8def60216ec48dfbf1dae7640498764cff70e Mon Sep 17 00:00:00 2001 From: Vixalie Date: Sun, 9 Mar 2025 22:14:20 +0800 Subject: [PATCH] prepare switch component. --- src/components/Switch.module.css | 46 ++++++++++++++++++++++++++++++++ src/components/Switch.tsx | 38 ++++++++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 src/components/Switch.module.css create mode 100644 src/components/Switch.tsx diff --git a/src/components/Switch.module.css b/src/components/Switch.module.css new file mode 100644 index 0000000..b8103a5 --- /dev/null +++ b/src/components/Switch.module.css @@ -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); + } + } + } + } +} diff --git a/src/components/Switch.tsx b/src/components/Switch.tsx new file mode 100644 index 0000000..cf83535 --- /dev/null +++ b/src/components/Switch.tsx @@ -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 = ({ 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 ( +
+
+ {name !== undefined && ( + + )} +
+ ); +};