Skip to content

Instantly share code, notes, and snippets.

@yaboynoem
Last active July 6, 2022 23:12
Show Gist options
  • Save yaboynoem/4a8203e69a01912f623c94ce1f8ad3c1 to your computer and use it in GitHub Desktop.
Save yaboynoem/4a8203e69a01912f623c94ce1f8ad3c1 to your computer and use it in GitHub Desktop.
animated hamburger icon using react and framer motion
import styled from "styled-components"
export const SHamburgerContainer = styled.div`
position: relative;
`
export const SHamburgerBox = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 4px;
border-radius: 5px;
cursor: pointer;
height: 40px;
opacity: 1;
overflow: hidden;
width: 40px;
`
export const SHamburgerPatty = styled.div`
width: 22.5px;
height: 3px;
border-radius: 25px;
margin: 0;
`
import React, { ReactElement } from "react"
import { motion } from "framer-motion"
import { useSelector } from "react-redux"
//Constants
import { EColor } from "Constants/Colors"
//Stores
import { store } from "Stores"
import { setIsSideBarOpen } from "Stores/App/Creators"
//Styles
import { SHamburgerBox, SHamburgerContainer, SHamburgerPatty } from "./Hamburger.styles"
//Types
import { TRootState } from "Types/GlobalTypes"
const Hamburger: React.FC = (): ReactElement => {
//react-redux selector
const { darkMode, isSideBarOpen } = useSelector((state: TRootState) => state.app)
return (
<SHamburgerContainer>
<SHamburgerBox
as={motion.div}
animate={{
//Changes the color of the hamburger depending on the darkMode
backgroundColor: darkMode ? EColor.CONTAINER_DARK : EColor.CONTAINER,
border: `2px solid ${darkMode ? EColor.CONTAINER : EColor.CONTAINER_DARK}`,
}}
onClick={() => store.dispatch(setIsSideBarOpen(!isSideBarOpen))}
>
<SHamburgerPatty
as={motion.div}
style={{
//Sets the transform-origin of the patty to the center right of itself
originX: "right",
originY: "center",
}}
animate={{
//Changes the color of the patty depending on the darkMode
backgroundColor: darkMode ? EColor.CONTAINER : EColor.CONTAINER_DARK,
//The actual animation when clicking on the burger
y: isSideBarOpen ? 8 : 0,
width: isSideBarOpen ? 12 : 22.5,
marginLeft: isSideBarOpen ? 11.5 : 0,
rotate: isSideBarOpen ? 45 : 0,
//Transition delays based on isSideBarOpen value
transition: {
y: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0 : 0.25,
},
width: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
marginLeft: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
rotate: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
},
}}
/>
<SHamburgerPatty
as={motion.div}
animate={{
//Middle patty will only animate the color change
backgroundColor: darkMode ? EColor.CONTAINER : EColor.CONTAINER_DARK,
}}
/>
{/* Opposite animation of the top patty line */}
<SHamburgerPatty
as={motion.div}
style={{
originX: "right",
originY: "center",
}}
animate={{
backgroundColor: darkMode ? EColor.CONTAINER : EColor.CONTAINER_DARK,
y: isSideBarOpen ? -8 : 0,
width: isSideBarOpen ? 12 : 22.5,
marginLeft: isSideBarOpen ? 11.5 : 0,
rotate: isSideBarOpen ? -45 : 0,
transition: {
y: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0 : 0.25,
},
width: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
marginLeft: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
rotate: {
duration: 0.25,
type: "spring",
delay: isSideBarOpen ? 0.25 : 0,
},
},
}}
/>
</SHamburgerBox>
</SHamburgerContainer>
)
}
export default Hamburger
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment