summaryrefslogtreecommitdiff
path: root/apps/web/src/components/ui/input-with-back.tsx
blob: 392ab3c3f4954005a8f46f77b2451662d6c6c98d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
"use client";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { ArrowLeft, Search } from "lucide-react";
import { motion } from "motion/react";
import { useState, useEffect } from "react";

interface InputWithBackProps {
	isExpanded: boolean;
	setIsExpanded: (isExpanded: boolean) => void;
	placeholder?: string;
	value?: string;
	onChange?: (value: string) => void;
	disableAnimation?: boolean;
}

export function InputWithBack({
	isExpanded,
	setIsExpanded,
	placeholder = "Search anything",
	value,
	onChange,
	disableAnimation = false,
}: InputWithBackProps) {
	const [containerRef, setContainerRef] = useState<HTMLDivElement | null>(null);
	const [buttonOffset, setButtonOffset] = useState(-60);

	const smoothTransition = {
		duration: disableAnimation ? 0 : 0.35,
		ease: [0.25, 0.1, 0.25, 1] as const,
	};

	useEffect(() => {
		if (containerRef) {
			const rect = containerRef.getBoundingClientRect();
			setButtonOffset(-rect.left - 48);
		}
	}, [containerRef]);

	return (
		<div ref={setContainerRef} className="relative w-full">
			<motion.div
				className="absolute top-1/2 left-0 z-10 -translate-y-1/2 cursor-pointer hover:opacity-75"
				initial={{
					x: isExpanded ? 0 : buttonOffset,
					opacity: isExpanded ? 1 : 0.5,
				}}
				animate={{
					x: isExpanded ? 0 : buttonOffset,
					opacity: isExpanded ? 1 : 0.5,
				}}
				transition={smoothTransition}
				onClick={() => setIsExpanded(!isExpanded)}
			>
				<Button
					variant="outline"
					className="bg-panel-accent !size-9 rounded-full"
				>
					<ArrowLeft />
				</Button>
			</motion.div>
			<div
				className="relative flex-1"
				style={{ marginLeft: "0px", paddingLeft: "0px" }}
			>
				<motion.div
					className="relative"
					initial={{
						marginLeft: isExpanded ? 50 : 0,
					}}
					animate={{
						marginLeft: isExpanded ? 50 : 0,
					}}
					transition={smoothTransition}
				>
					<Search className="text-muted-foreground absolute top-1/2 left-3 size-4 -translate-y-1/2" />
					<Input
						placeholder={placeholder}
						className="bg-panel-accent w-full pl-9"
						value={value}
						onChange={(e) => onChange?.(e.target.value)}
					/>
				</motion.div>
			</div>
		</div>
	);
}