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