This is my way to create Hamburger Menu
using Next.js
and Chakra UI
CSS framework. Check this out!
Setup
- Create a
Next.js
project setup with the following syntax.
$ npx create-next-app --example with-chakra-ui my-app
# or
$ yarn create-next-app --example with-chakra-ui my-app
- Then open the project we just created into your favorite
code editor
. - Then go to the
src/components
folder, and open theDarkModeSwitch.js
file.
Imports
- Next we will start by importing everything we need.
import React, { useState } from 'react'
import { useColorMode, Switch, Flex, Button, IconButton } from '@chakra-ui/react'
import { HamburgerIcon, CloseIcon } from '@chakra-ui/icons'
import Link from 'next/link'
Settings the Desktop Content and Mobile Content
- Next, wrap everything inside of a
Flex
element. Then, add the below code.
<Flex>
<Flex position="fixed" top="1rem" right="1rem" align="center">
{/* Desktop */}
<Flex>
<Link href="/" passHref>
<Button as="a" variant="ghost" aria-label="Home" my={5} w="100%">
Home
</Button>
</Link>
<Link href="/about" passHref>
<Button as="a" variant="ghost" aria-label="About" my={5} w="100%">
About
</Button>
</Link>
<Link href="/contact" passHref>
<Button as="a" variant="ghost" aria-label="Contact" my={5} w="100%">
Contact
</Button>
</Link>
</Flex>
{/* Mobile */}
<IconButton
aria-label="Open Menu"
size="lg"
mr={2}
icon={<HamburgerIcon />}
onClick={}
/>
<Switch color="green" isChecked={isDark} onChange={toggleColorMode} />
</Flex>
{/* Mobile Content */}
<Flex
bgColor="gray.50"
overflowY="auto"
flexDir="column"
>
<Flex justify="flex-end">
<IconButton
mt={2}
mr={2}
aria-label="Open Menu"
size="lg"
icon={<CloseIcon />}
onClick={}
/>
</Flex>
<Flex flexDir="column" align="center">
<Link href="/" passHref>
<Button as="a" variant="ghost" aria-label="Home" my={5} w="100%">
Home
</Button>
</Link>
<Link href="/about" passHref>
<Button as="a" variant="ghost" aria-label="About" my={5} w="100%">
About
</Button>
</Link>
<Link href="/contact" passHref>
<Button as="a" variant="ghost" aria-label="Contact" my={5} w="100%">
Contact
</Button>
</Link>
</Flex>
</Flex>
Using useState to Open and Close Navigation
- Now that we have content, we need a way to show it. We can use
useState
for this case. Before the return statement, add the following:
const [display, changeDisplay] = useState('none')
- Now we have a variable display set initially to none, and a method
changeDisplay
we can use to change it.
<IconButton
aria-label="Open Menu"
size="lg"
mr={2}
icon={
<HamburgerIcon />
}
onClick={() => changeDisplay('flex')} // added line
/>
<Flex
display={display} // added line
bgColor="gray.50"
overflowY="auto"
flexDir="column"
>
<IconButton
mt={2}
mr={2}
aria-label="Open Menu"
size="lg"
icon={
<CloseIcon />
}
onClick={() => changeDisplay('none')} // added line
/>
- Now we should be able to open and close the menu! Let's add styles to the
Flex
.
<Flex
w="100vw"
display={display}
bgColor="gray.50"
zIndex={20}
h="100vh"
pos="fixed"
top="0"
left="0"
overflowY="auto"
flexDir="column"
>
The important styles we added:
- Setting the height to 100vh
- Setting the width to 100vw
- Setting the position to fixed
- Making z-index 20 so it is above the page content
- Setting top and left to 0
- Setting the display to our dynamic display variable.
The Complete Code
Here's the complete code.
import { useState } from 'react'
import { useColorMode, Switch, Flex, Button, IconButton } from '@chakra-ui/react'
import { HamburgerIcon, CloseIcon } from '@chakra-ui/icons'
import NextLink from 'next/link'
export const DarkModeSwitch = () => {
const { colorMode, toggleColorMode } = useColorMode()
const isDark = colorMode === 'dark'
const [display, changeDisplay] = useState('none')
return (
<Flex>
<Flex
position="fixed"
top="1rem"
right="1rem"
align="center"
>
{/* Desktop */}
<Flex
display={['none', 'none', 'flex','flex']}
>
<NextLink href="/" passHref>
<Button
as="a"
variant="ghost"
aria-label="Home"
my={5}
w="100%"
>
Home
</Button>
</NextLink>
<NextLink href="/about" passHref>
<Button
as="a"
variant="ghost"
aria-label="About"
my={5}
w="100%"
>
About
</Button>
</NextLink>
<NextLink href="/contact" passHref>
<Button
as="a"
variant="ghost"
aria-label="Contact"
my={5}
w="100%"
>
Contact
</Button>
</NextLink>
</Flex>
{/* Mobile */}
<IconButton
aria-label="Open Menu"
size="lg"
mr={2}
icon={
<HamburgerIcon />
}
onClick={() => changeDisplay('flex')}
display={['flex', 'flex', 'none', 'none']}
/>
<Switch
color="green"
isChecked={isDark}
onChange={toggleColorMode}
/>
</Flex>
{/* Mobile Content */}
<Flex
w='100vw'
display={display}
bgColor="gray.50"
zIndex={20}
h="100vh"
pos="fixed"
top="0"
left="0"
zIndex={20}
overflowY="auto"
flexDir="column"
>
<Flex justify="flex-end">
<IconButton
mt={2}
mr={2}
aria-label="Open Menu"
size="lg"
icon={
<CloseIcon />
}
onClick={() => changeDisplay('none')}
/>
</Flex>
<Flex
flexDir="column"
align="center"
>
<NextLink href="/" passHref>
<Button
as="a"
variant="ghost"
aria-label="Home"
my={5}
w="100%"
>
Home
</Button>
</NextLink>
<NextLink href="/about" passHref>
<Button
as="a"
variant="ghost"
aria-label="About"
my={5}
w="100%"
>
About
</Button>
</NextLink>
<NextLink href="/contact" passHref>
<Button
as="a"
variant="ghost"
aria-label="Contact"
my={5}
w="100%"
>
Contact
</Button>
</NextLink>
</Flex>
</Flex>
</Flex>
)
}