mirror of
https://github.com/pheralb/svgl.git
synced 2025-02-06 06:58:04 +08:00
feat: add autofocus when open search box
This commit is contained in:
parent
b42afebd9d
commit
422af78d44
@ -1,18 +1,27 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Input, Text, Image, HStack, Box, Center, Spinner } from "@chakra-ui/react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
Input,
|
||||
Text,
|
||||
Image,
|
||||
HStack,
|
||||
Box,
|
||||
Center,
|
||||
Spinner,
|
||||
} from "@chakra-ui/react";
|
||||
import useDebounce from "@/hooks/useDebounce";
|
||||
import { SVGCardProps } from "@/interfaces/components";
|
||||
import { SearchProps, SVGCardProps } from "@/interfaces/components";
|
||||
import CustomLink from "@/common/link";
|
||||
import { getSvgByQuery } from "@/services";
|
||||
import CustomIconBtn from "@/common/iconBtn";
|
||||
import { Trash } from "phosphor-react";
|
||||
import Tap from "@/animations/tap";
|
||||
|
||||
const Search = () => {
|
||||
const Search = ({ availableFocus = false }: SearchProps) => {
|
||||
const [search, setSearch] = useState("");
|
||||
const [empty, setEmpty] = useState(false);
|
||||
const [results, setResults] = useState<SVGCardProps[]>([]);
|
||||
const debouncedSearch = useDebounce(search, 500);
|
||||
const searchRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch) {
|
||||
@ -27,6 +36,18 @@ const Search = () => {
|
||||
}
|
||||
}, [debouncedSearch]);
|
||||
|
||||
useEffect(() => {
|
||||
const isFocusAvailable = availableFocus && searchRef.current;
|
||||
|
||||
if (!isFocusAvailable) return;
|
||||
|
||||
const timeoutId = setTimeout(() => {
|
||||
searchRef.current?.focus();
|
||||
}, 100);
|
||||
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [availableFocus]);
|
||||
|
||||
const handleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setEmpty(false);
|
||||
setSearch(e.target.value);
|
||||
@ -46,12 +67,23 @@ const Search = () => {
|
||||
placeholder="Search svgs..."
|
||||
value={search}
|
||||
onChange={handleFilter}
|
||||
ref={searchRef}
|
||||
/>
|
||||
{search && !empty && results.length === 0 && (<Box pt="4"><Spinner /></Box>)}
|
||||
{search && empty && (<Box pt="3">No results found!</Box>)}
|
||||
{search && !empty && results.length === 0 && (
|
||||
<Box pt="4">
|
||||
<Spinner />
|
||||
</Box>
|
||||
)}
|
||||
{search && empty && <Box pt="3">No results found!</Box>}
|
||||
{results && results.length > 0 && (
|
||||
<>
|
||||
<HStack spacing={4} mt={4} overflowX="auto" overflowY="hidden" alignItems="start">
|
||||
<HStack
|
||||
spacing={4}
|
||||
mt={4}
|
||||
overflowX="auto"
|
||||
overflowY="hidden"
|
||||
alignItems="start"
|
||||
>
|
||||
{results.map((item: SVGCardProps) => (
|
||||
<Tap key={item.title}>
|
||||
<CustomLink href={`/svg/${item.id}`}>
|
||||
|
@ -42,3 +42,7 @@ export interface ErrorProps {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
export interface SearchProps {
|
||||
availableFocus?: boolean;
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ const Header = () => {
|
||||
</Flex>
|
||||
<Collapse in={isOpen} animateOpacity>
|
||||
<Box mt='3' display={{ base: 'none', md: 'block' }}>
|
||||
<Search />
|
||||
<Search availableFocus={isOpen} />
|
||||
</Box>
|
||||
</Collapse>
|
||||
<Box mt='2' display={{ base: 'block', md: 'none' }}>
|
||||
|
Loading…
x
Reference in New Issue
Block a user