Files
desktop/app/components/InputCustomPlaceholder/InputCustomPlaceholder.tsx
rosetta 83f38dc63f 'init'
2026-01-30 05:01:05 +02:00

78 lines
2.8 KiB
TypeScript

import { useRosettaColors } from "@/app/hooks/useRosettaColors";
import { Flex, Input, Text } from "@mantine/core";
import { IconSearch } from "@tabler/icons-react";
import { forwardRef, useState } from "react";
interface InputCustomPlaceholderProps {
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
onBlur?: () => void;
}
const InputCustomPlaceholder = forwardRef<HTMLDivElement, InputCustomPlaceholderProps>((props: InputCustomPlaceholderProps, ref) => {
const colors = useRosettaColors();
const [isFocused, setIsFocused] = useState(false);
const [value, setValue] = useState("");
const handleFocus = () => setIsFocused(true);
const handleBlur = () => {
setIsFocused(false);
setValue("");
if (props.onBlur) props.onBlur();
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.currentTarget.value);
if (props.onChange) props.onChange(e);
}
return (
<div ref={ref} style={{ width: '100%', position: 'relative' }}>
<div
style={{
position: 'absolute',
inset: 0,
pointerEvents: 'none',
}}
>
<div
style={{
position: 'absolute',
top: '50%',
transform: isFocused ? 'translateY(-50%) translateX(0)' : 'translateY(-50%) translateX(-50%)',
left: isFocused ? 8 : '50%',
transition: 'left 180ms ease, transform 180ms ease, opacity 180ms ease',
width: 'auto',
opacity: isFocused ? 0.85 : 1,
}}
>
<Input.Placeholder>
<Flex align={'center'} gap={5}>
<IconSearch stroke={1.3} size={16} />
<Text style={{
transition: 'opacity 180ms ease',
opacity: isFocused ? 0 : 1,
userSelect: 'none'
}} size="xs" c="dimmed">
Search
</Text>
</Flex>
</Input.Placeholder>
</div>
</div>
<Input
size="xs"
variant="unstyled"
w={'100%'}
pl={'xl'}
style={{ caretColor: colors.chevrons.active }}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={handleChange}
value={value}
/>
</div>
);
});
export default InputCustomPlaceholder;