mirror of
https://github.com/pheralb/svgl.git
synced 2025-02-06 06:58:04 +08:00
⚒️ Create sidebar
This commit is contained in:
parent
4b03d1868c
commit
1c82a91745
24
src/layout/sidebar/categories.tsx
Normal file
24
src/layout/sidebar/categories.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
import useSWR from "swr";
|
||||
import { getCategorySvgs } from "@/services";
|
||||
import CustomLink from "@/common/link";
|
||||
import { Text } from "@chakra-ui/react";
|
||||
|
||||
const Categories = () => {
|
||||
const { data, error } = useSWR(getCategorySvgs);
|
||||
|
||||
if (error) return <div>failed to load</div>;
|
||||
if (!data) return <div>loading...</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{data.map((category: string) => (
|
||||
<CustomLink key={category} href={`/category/${category}`}>
|
||||
<Text mb="2">{category}</Text>
|
||||
</CustomLink>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Categories;
|
53
src/layout/sidebar/content.tsx
Normal file
53
src/layout/sidebar/content.tsx
Normal file
@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { SidebarContentProps } from "@/interfaces/components";
|
||||
import {
|
||||
Box,
|
||||
Divider,
|
||||
Flex,
|
||||
Heading,
|
||||
useColorModeValue,
|
||||
} from "@chakra-ui/react";
|
||||
import { HandGrabbing } from "phosphor-react";
|
||||
import CustomLink from "@/common/link";
|
||||
import Categories from "./categories";
|
||||
|
||||
const Content = (props: SidebarContentProps) => {
|
||||
const bg = useColorModeValue("bg.light", "bg.dark");
|
||||
return (
|
||||
<Box
|
||||
as="nav"
|
||||
pos="fixed"
|
||||
left="0"
|
||||
zIndex="sticky"
|
||||
h="full"
|
||||
pb="10"
|
||||
overflowX="hidden"
|
||||
overflowY="auto"
|
||||
w="240px"
|
||||
bg={bg}
|
||||
{...props}
|
||||
>
|
||||
<Flex
|
||||
as="nav"
|
||||
mt="5"
|
||||
ml="7"
|
||||
mr="6"
|
||||
direction="column"
|
||||
aria-label="Main Sidenav"
|
||||
>
|
||||
<CustomLink href="/">
|
||||
<HandGrabbing size={50} />
|
||||
</CustomLink>
|
||||
<Box mt="6" ml="1">
|
||||
<Divider mb="4" />
|
||||
<Heading fontSize="16px" mt="3" mb="3">
|
||||
Categories
|
||||
</Heading>
|
||||
<Categories />
|
||||
</Box>
|
||||
</Flex>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Content;
|
59
src/layout/sidebar/index.tsx
Normal file
59
src/layout/sidebar/index.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { SidebarContentProps } from "@/interfaces/components";
|
||||
import {
|
||||
Box,
|
||||
Drawer,
|
||||
DrawerContent,
|
||||
DrawerOverlay,
|
||||
Flex,
|
||||
IconButton,
|
||||
useColorModeValue,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import React from "react";
|
||||
import { IoApps } from "react-icons/io5";
|
||||
import Content from "./content";
|
||||
|
||||
const Index = ({ children }: SidebarContentProps) => {
|
||||
const sidebar = useDisclosure();
|
||||
return (
|
||||
<Box as="section">
|
||||
<Content display={{ base: "none", md: "unset" }} />
|
||||
<Drawer
|
||||
isOpen={sidebar.isOpen}
|
||||
onClose={sidebar.onClose}
|
||||
placement="left"
|
||||
>
|
||||
<DrawerOverlay />
|
||||
<DrawerContent>
|
||||
<Content w="full" borderRight="none" />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
<Box ml={{ base: 0, md: "90px" }} transition=".3s ease">
|
||||
<Flex
|
||||
as="header"
|
||||
display={{ base: "inline-flex", md: "none" }}
|
||||
align="center"
|
||||
justify="space-between"
|
||||
w="full"
|
||||
px="4"
|
||||
borderBottomWidth="1px"
|
||||
borderColor="blackAlpha.300"
|
||||
h="14"
|
||||
>
|
||||
<IconButton
|
||||
aria-label="Menu"
|
||||
onClick={sidebar.onOpen}
|
||||
icon={<IoApps />}
|
||||
size="sm"
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
<Box as="main" p="4">
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
34
src/layout/sidebar/theme.tsx
Normal file
34
src/layout/sidebar/theme.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import React from "react";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { useColorMode, useColorModeValue } from "@chakra-ui/react";
|
||||
import CustomIconBtn from "@/common/iconBtn";
|
||||
import { IoMoonOutline, IoSunnyOutline } from "react-icons/io5";
|
||||
|
||||
const Theme = () => {
|
||||
const { toggleColorMode } = useColorMode();
|
||||
const key = useColorModeValue("light", "dark");
|
||||
const icon = useColorModeValue(
|
||||
<IoMoonOutline size={20} />,
|
||||
<IoSunnyOutline size={20} />
|
||||
);
|
||||
return (
|
||||
<AnimatePresence exitBeforeEnter initial={false}>
|
||||
<motion.div
|
||||
style={{ display: "inline-block" }}
|
||||
key={key}
|
||||
initial={{ y: -20, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
exit={{ y: 20, opacity: 0 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<CustomIconBtn
|
||||
title="Toggle theme"
|
||||
icon={icon}
|
||||
onClick={toggleColorMode}
|
||||
/>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
);
|
||||
};
|
||||
|
||||
export default Theme;
|
Loading…
x
Reference in New Issue
Block a user