Files
honey-fe/src/components/form/SwitchInput/SwitchInput.tsx

59 lines
1.8 KiB
TypeScript
Raw Normal View History

2026-03-12 00:42:41 +02:00
import clsx, { type ClassValue } from "clsx";
2026-03-22 04:08:56 +02:00
import { useTranslation } from "react-i18next";
2026-03-12 00:42:41 +02:00
import ContentSurface from "@components/surface/ContentSurface";
import LightSurface from "@components/surface/LightSurface";
import { motion, type HTMLMotionProps } from "motion/react";
import classes from "./SwitchInput.module.css";
2026-03-22 04:08:56 +02:00
import tg from "@/tg";
2026-03-22 16:39:48 +02:00
import { useRef } from "react";
2026-03-12 00:42:41 +02:00
type Props = Omit<HTMLMotionProps<"div">, "className" | "onChange"> & {
value?: boolean | null;
onChange?: (value: boolean) => void;
className?: ClassValue;
};
export default function SwitchInput({ value, onChange, className, ...props }: Props) {
2026-03-22 04:08:56 +02:00
const { t } = useTranslation();
2026-03-22 16:39:48 +02:00
const selectedIndex = value != null ? (value ? 0 : 1) : 0;
const selectedIndexRef = useRef(selectedIndex);
2026-03-12 00:42:41 +02:00
return (
<ContentSurface
{...props}
className={clsx(classes.container, className)}
whileTap={{ scale: 1.1 }}
2026-03-22 04:08:56 +02:00
onClick={() => {
tg.hapticFeedback.click();
onChange?.(!value);
}}
2026-03-12 00:42:41 +02:00
>
<div className={classes.optionsContainer}>
<div className={classes.options}>
<motion.button
type="button"
className={clsx(classes.option, value === true && classes.selected)}
>
2026-03-22 04:08:56 +02:00
{t("common.on")}
2026-03-12 00:42:41 +02:00
</motion.button>
<motion.button
type="button"
className={clsx(classes.option, value === false && classes.selected)}
>
2026-03-22 04:08:56 +02:00
{t("common.off")}
2026-03-12 00:42:41 +02:00
</motion.button>
</div>
{selectedIndex >= 0 && (
<LightSurface
className={classes.thumb}
2026-03-22 16:39:48 +02:00
initial={{ left: `${selectedIndexRef.current * 50}%` }}
animate={{ left: `${selectedIndex * 50}%` }}
2026-03-12 00:42:41 +02:00
transition={{ type: "spring", stiffness: 500, damping: 35 }}
/>
)}
</div>
</ContentSurface>
);
}