Created
July 3, 2022 20:47
-
-
Save paulweezydesign/81913ba7272f0f5dee143af84344200b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { useRef } from "react"; | |
import { motion, useCycle } from "framer-motion"; | |
import { useDimensions } from "./use-dimensions"; | |
import { MenuToggle } from "./MenuToggle"; | |
import { Navigation } from "./Navigation"; | |
const sidebar = { | |
open: (height = 1000) => ({ | |
clipPath: `circle(${height * 2 + 200}px at 40px 40px)`, | |
transition: { | |
type: "spring", | |
stiffness: 20, | |
restDelta: 2 | |
} | |
}), | |
closed: { | |
clipPath: "circle(30px at 40px 40px)", | |
transition: { | |
delay: 0.5, | |
type: "spring", | |
stiffness: 400, | |
damping: 40 | |
} | |
} | |
}; | |
export const Example = () => { | |
const [isOpen, toggleOpen] = useCycle(false, true); | |
const containerRef = useRef(null); | |
const { height } = useDimensions(containerRef); | |
return ( | |
<motion.nav | |
initial={false} | |
animate={isOpen ? "open" : "closed"} | |
custom={height} | |
ref={containerRef} | |
> | |
<motion.div className="background" variants={sidebar} /> | |
<Navigation /> | |
<MenuToggle toggle={() => toggleOpen()} /> | |
</motion.nav> | |
); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { render } from "react-dom"; | |
import { Example } from "./Example"; | |
import "./styles.css"; | |
render(<Example />, document.getElementById("root")); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
width: 100vw; | |
height: 100vh; | |
background: linear-gradient(180deg, #0055ff 0%, rgb(0, 153, 255) 100%); | |
overflow: hidden; | |
padding: 0; | |
margin: 0; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
} | |
nav { | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
width: 300px; | |
} | |
.background { | |
position: absolute; | |
top: 0; | |
left: 0; | |
bottom: 0; | |
width: 300px; | |
background: #fff; | |
} | |
button { | |
outline: none; | |
border: none; | |
-webkit-user-select: none; | |
-moz-user-select: none; | |
-ms-user-select: none; | |
cursor: pointer; | |
position: absolute; | |
top: 18px; | |
left: 15px; | |
width: 50px; | |
height: 50px; | |
border-radius: 50%; | |
background: transparent; | |
} | |
ul, | |
li { | |
margin: 0; | |
padding: 0; | |
} | |
ul { | |
padding: 25px; | |
position: absolute; | |
top: 100px; | |
width: 230px; | |
} | |
li { | |
list-style: none; | |
margin-bottom: 20px; | |
display: flex; | |
align-items: center; | |
cursor: pointer; | |
} | |
.icon-placeholder { | |
width: 40px; | |
height: 40px; | |
border-radius: 50%; | |
flex: 40px 0; | |
margin-right: 20px; | |
} | |
.text-placeholder { | |
border-radius: 5px; | |
width: 200px; | |
height: 20px; | |
flex: 1; | |
} | |
.refresh { | |
padding: 10px; | |
position: absolute; | |
background: rgba(0, 0, 0, 0.4); | |
border-radius: 10px; | |
width: 20px; | |
height: 20px; | |
top: 10px; | |
right: 10px; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
cursor: pointer; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef } from "react"; | |
// Naive implementation - in reality would want to attach | |
// a window or resize listener. Also use state/layoutEffect instead of ref/effect | |
// if this is important to know on initial client render. | |
// It would be safer to return null for unmeasured states. | |
export const useDimensions = ref => { | |
const dimensions = useRef({ width: 0, height: 0 }); | |
useEffect(() => { | |
dimensions.current.width = ref.current.offsetWidth; | |
dimensions.current.height = ref.current.offsetHeight; | |
}, []); | |
return dimensions.current; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment