mirror of
https://github.com/pheralb/svgl.git
synced 2024-11-10 14:46:54 +08:00
⚒️ Create header & layout config.
This commit is contained in:
parent
457a6c64f7
commit
4d366f8c25
24
src/animations/show.tsx
Normal file
24
src/animations/show.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React, { FC } from "react";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
type ShowProps = {
|
||||
children: React.ReactNode;
|
||||
delay?: number;
|
||||
};
|
||||
|
||||
const Show = ({ children, delay }: ShowProps) => {
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ y: 10, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
||||
transition={{
|
||||
duration: 0.4,
|
||||
delay: delay,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</motion.div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Show;
|
@ -2,7 +2,7 @@ import React from "react";
|
||||
import useSWR from "swr";
|
||||
import { getCategorySvgs } from "@/services";
|
||||
import CustomLink from "@/common/link";
|
||||
import { Text } from "@chakra-ui/react";
|
||||
import { Box, Text } from "@chakra-ui/react";
|
||||
|
||||
const Categories = () => {
|
||||
const { data, error } = useSWR(getCategorySvgs);
|
||||
@ -11,13 +11,13 @@ const Categories = () => {
|
||||
if (!data) return <div>loading...</div>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<>
|
||||
{data.map((category: string) => (
|
||||
<CustomLink key={category} href={`/category/${category}`}>
|
||||
<Text mb="2">{category}</Text>
|
||||
</CustomLink>
|
||||
<Box key={category} p="4" borderRadius="5px" borderWidth="1px">
|
||||
<CustomLink href={`/category/${category}`}>{category}</CustomLink>
|
||||
</Box>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
73
src/layout/header/index.tsx
Normal file
73
src/layout/header/index.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import React from "react";
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
useColorModeValue,
|
||||
HStack,
|
||||
Button,
|
||||
Container,
|
||||
Heading,
|
||||
} from "@chakra-ui/react";
|
||||
import { Sticker } from "phosphor-react";
|
||||
import Theme from "./theme";
|
||||
import Tap from "@/animations/tap";
|
||||
import Mobile from "./mobile";
|
||||
import { Links } from "./links";
|
||||
import CustomLink from "@/common/link";
|
||||
import Categories from "./categories";
|
||||
|
||||
const Header = () => {
|
||||
const bg = useColorModeValue("bg.light", "bg.dark");
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
position="sticky"
|
||||
top="0"
|
||||
bg={bg}
|
||||
borderBottomWidth="1px"
|
||||
w="full"
|
||||
py={6}
|
||||
shadow="sm"
|
||||
>
|
||||
<Container maxW={{ base: "full", md: "70%" }}>
|
||||
<Flex alignItems="center" justifyContent="space-between" mx="auto">
|
||||
<CustomLink href="/">
|
||||
<Tap>
|
||||
<HStack spacing={3} cursor="pointer">
|
||||
<Sticker size={32} color="#4343e5" weight="bold" />
|
||||
<Heading fontSize="19px">svgl</Heading>
|
||||
</HStack>
|
||||
</Tap>
|
||||
</CustomLink>
|
||||
<HStack display="flex" alignItems="center" spacing={1}>
|
||||
<HStack
|
||||
spacing={1}
|
||||
mr={1}
|
||||
display={{ base: "none", md: "inline-flex" }}
|
||||
>
|
||||
{Links.map((link) => (
|
||||
<CustomLink
|
||||
key={link.title}
|
||||
href={link.slug}
|
||||
external={link.external}
|
||||
>
|
||||
<Button variant="ghost">{link.title}</Button>
|
||||
</CustomLink>
|
||||
))}
|
||||
<Theme />
|
||||
</HStack>
|
||||
<Box display={{ base: "inline-flex", md: "none" }}>
|
||||
<Mobile />
|
||||
</Box>
|
||||
</HStack>
|
||||
</Flex>
|
||||
</Container>
|
||||
</Box>
|
||||
<HStack p="4" spacing={4} overflowY="hidden" bg={bg} borderBottomWidth="1px">
|
||||
<Categories />
|
||||
</HStack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
12
src/layout/header/links.ts
Normal file
12
src/layout/header/links.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export const Links = [
|
||||
{
|
||||
title: "Github",
|
||||
slug: "https://github.com/pheralb/svgl",
|
||||
external: true,
|
||||
},
|
||||
{
|
||||
title: "Twitter",
|
||||
slug: "https://twitter.com/pheralb_",
|
||||
external: true,
|
||||
},
|
||||
];
|
56
src/layout/header/mobile.tsx
Normal file
56
src/layout/header/mobile.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import CustomLink from "@/common/link";
|
||||
import {
|
||||
Button,
|
||||
CloseButton,
|
||||
IconButton,
|
||||
useColorModeValue,
|
||||
useDisclosure,
|
||||
VStack,
|
||||
} from "@chakra-ui/react";
|
||||
import { List } from "phosphor-react";
|
||||
import { Links } from "./links";
|
||||
|
||||
const Mobile = () => {
|
||||
const bg = useColorModeValue("bg.light", "bg.dark");
|
||||
const mobileNav = useDisclosure();
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
display={{ base: "flex", md: "none" }}
|
||||
aria-label="Open menu navbar"
|
||||
variant="ghost"
|
||||
icon={<List size={22} />}
|
||||
onClick={mobileNav.onOpen}
|
||||
/>
|
||||
|
||||
<VStack
|
||||
pos="absolute"
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
display={mobileNav.isOpen ? "flex" : "none"}
|
||||
flexDirection="column"
|
||||
p={2}
|
||||
pb={4}
|
||||
m={2}
|
||||
bg={bg}
|
||||
spacing={3}
|
||||
rounded="sm"
|
||||
shadow="sm"
|
||||
>
|
||||
<CloseButton aria-label="Close menu" onClick={mobileNav.onClose} />
|
||||
{Links.map((link) => (
|
||||
<CustomLink
|
||||
key={link.title}
|
||||
href={link.slug}
|
||||
external={link.external}
|
||||
>
|
||||
<Button variant="ghost">{link.title}</Button>
|
||||
</CustomLink>
|
||||
))}
|
||||
</VStack>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Mobile;
|
@ -2,19 +2,18 @@ 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";
|
||||
import { Moon, Sun } from "phosphor-react";
|
||||
|
||||
const Theme = () => {
|
||||
const { toggleColorMode } = useColorMode();
|
||||
const key = useColorModeValue("light", "dark");
|
||||
const icon = useColorModeValue(
|
||||
<IoMoonOutline size={20} />,
|
||||
<IoSunnyOutline size={20} />
|
||||
<Moon size={22} />,
|
||||
<Sun size={22} />
|
||||
);
|
||||
return (
|
||||
<AnimatePresence exitBeforeEnter initial={false}>
|
||||
<motion.div
|
||||
style={{ display: "inline-block" }}
|
||||
key={key}
|
||||
initial={{ y: -20, opacity: 0 }}
|
||||
animate={{ y: 0, opacity: 1 }}
|
@ -1,9 +1,15 @@
|
||||
import React from "react";
|
||||
import { LayoutProps } from "@/interfaces/components";
|
||||
import Sidebar from "@/layout/sidebar";
|
||||
import { Container } from "@chakra-ui/react";
|
||||
import Header from "./header";
|
||||
|
||||
const Index = ({ children }: LayoutProps) => {
|
||||
return <Sidebar>{children}</Sidebar>;
|
||||
return (
|
||||
<>
|
||||
<Header />
|
||||
<Container maxW="70%">{children}</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
|
@ -1,53 +0,0 @@
|
||||
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;
|
@ -1,59 +0,0 @@
|
||||
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;
|
@ -1,5 +1,5 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import db from "data/svgs";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { SvgData } from "@/interfaces/svgData";
|
||||
|
||||
export default function handler(
|
||||
|
@ -13,18 +13,11 @@ const Home: NextPage = () => {
|
||||
if (!data) return <div>loading...</div>;
|
||||
|
||||
return (
|
||||
<Container maxW="85%">
|
||||
<Grid>
|
||||
{data.map((svg: SvgData) => (
|
||||
<SVGCard
|
||||
key={svg.id}
|
||||
title={svg.title}
|
||||
url={svg.href}
|
||||
svg={svg.href}
|
||||
/>
|
||||
<SVGCard key={svg.id} title={svg.title} url={svg.href} svg={svg.href} />
|
||||
))}
|
||||
</Grid>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user