mirror of
https://github.com/pheralb/svgl.git
synced 2024-11-13 08:46:56 +08:00
⚒️ Add search component.
This commit is contained in:
parent
1c43264288
commit
1df49160d0
63
src/components/search.tsx
Normal file
63
src/components/search.tsx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Flex, Input, Text, Image } from "@chakra-ui/react";
|
||||||
|
import useSWR from "swr";
|
||||||
|
import useDebounce from "@/hooks/useDebounce";
|
||||||
|
import { SVGCardProps } from "@/interfaces/components";
|
||||||
|
import CustomLink from "@/common/link";
|
||||||
|
import Error from "@/components/error";
|
||||||
|
import { getSvgByQuery } from "@/services";
|
||||||
|
import CustomIconBtn from "@/common/iconBtn";
|
||||||
|
import { Trash } from "phosphor-react";
|
||||||
|
|
||||||
|
const Search = () => {
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const debouncedSearch = useDebounce(search, 500);
|
||||||
|
const { data, error } = useSWR(`${getSvgByQuery}${debouncedSearch}`);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
<Error title="Error" description="an error occurred with your search" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setSearch("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Input
|
||||||
|
width="full"
|
||||||
|
variant="flushed"
|
||||||
|
size="lg"
|
||||||
|
placeholder="Search"
|
||||||
|
value={search}
|
||||||
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
|
/>
|
||||||
|
{data && data.length > 0 && (
|
||||||
|
<Flex direction="column" mt={2} p="2" overflowY="hidden">
|
||||||
|
{data.map((item: SVGCardProps) => (
|
||||||
|
<CustomLink key={item.title} href={`/svg/${item.id}`}>
|
||||||
|
<Flex
|
||||||
|
direction="row"
|
||||||
|
mb="2"
|
||||||
|
shadow="sm"
|
||||||
|
p="3"
|
||||||
|
borderWidth="1px"
|
||||||
|
borderRadius="5px"
|
||||||
|
>
|
||||||
|
<Image width="20px" mr="2" src={item.href} alt={item.title} />
|
||||||
|
<Text>{item.title}</Text>
|
||||||
|
</Flex>
|
||||||
|
</CustomLink>
|
||||||
|
))}
|
||||||
|
<CustomIconBtn
|
||||||
|
title="clear"
|
||||||
|
icon={<Trash size={16} />}
|
||||||
|
onClick={handleClear}
|
||||||
|
/>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Search;
|
@ -7,20 +7,23 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Container,
|
Container,
|
||||||
Heading,
|
Heading,
|
||||||
Center,
|
|
||||||
Icon,
|
Icon,
|
||||||
Input,
|
useDisclosure,
|
||||||
|
Collapse,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { ArrowSquareOut, Sticker } from "phosphor-react";
|
import { ArrowSquareOut, MagnifyingGlass, Sticker, X } from "phosphor-react";
|
||||||
import Theme from "./theme";
|
import Theme from "./theme";
|
||||||
import Tap from "@/animations/tap";
|
import Tap from "@/animations/tap";
|
||||||
import Mobile from "./mobile";
|
import Mobile from "./mobile";
|
||||||
import { Links } from "./links";
|
import { Links } from "./links";
|
||||||
import CustomLink from "@/common/link";
|
import CustomLink from "@/common/link";
|
||||||
import Categories from "./categories";
|
import Categories from "./categories";
|
||||||
|
import Search from "@/components/search";
|
||||||
|
import CustomIconBtn from "@/common/iconBtn";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const bg = useColorModeValue("bg.light", "bg.dark");
|
const bg = useColorModeValue("bg.light", "bg.dark");
|
||||||
|
const { isOpen, onToggle } = useDisclosure();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
@ -30,6 +33,7 @@ const Header = () => {
|
|||||||
borderBottomWidth="1px"
|
borderBottomWidth="1px"
|
||||||
w="full"
|
w="full"
|
||||||
py={6}
|
py={6}
|
||||||
|
zIndex={1}
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
>
|
>
|
||||||
<Container maxW={{ base: "full", md: "70%" }}>
|
<Container maxW={{ base: "full", md: "70%" }}>
|
||||||
@ -54,7 +58,7 @@ const Header = () => {
|
|||||||
href={link.slug}
|
href={link.slug}
|
||||||
external={link.external}
|
external={link.external}
|
||||||
>
|
>
|
||||||
<Button variant="ghost" fontFamily="Inter-SemiBold">
|
<Button variant="ghost" fontFamily="Inter-Semibold">
|
||||||
{link.title}
|
{link.title}
|
||||||
{link.external ? (
|
{link.external ? (
|
||||||
<Icon as={ArrowSquareOut} ml="2" />
|
<Icon as={ArrowSquareOut} ml="2" />
|
||||||
@ -62,6 +66,11 @@ const Header = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</CustomLink>
|
</CustomLink>
|
||||||
))}
|
))}
|
||||||
|
<CustomIconBtn
|
||||||
|
title="Toggle Search bar"
|
||||||
|
icon={isOpen ? <X size={22} /> : <MagnifyingGlass size={22} />}
|
||||||
|
onClick={onToggle}
|
||||||
|
/>
|
||||||
<Theme />
|
<Theme />
|
||||||
</HStack>
|
</HStack>
|
||||||
<Box display={{ base: "inline-flex", md: "none" }}>
|
<Box display={{ base: "inline-flex", md: "none" }}>
|
||||||
@ -69,6 +78,11 @@ const Header = () => {
|
|||||||
</Box>
|
</Box>
|
||||||
</HStack>
|
</HStack>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Collapse in={isOpen} animateOpacity>
|
||||||
|
<Box mt="3">
|
||||||
|
<Search />
|
||||||
|
</Box>
|
||||||
|
</Collapse>
|
||||||
</Container>
|
</Container>
|
||||||
</Box>
|
</Box>
|
||||||
<HStack
|
<HStack
|
||||||
|
Loading…
Reference in New Issue
Block a user