Created
November 28, 2025 18:10
-
-
Save mustafadalga/85909f1d8315ff73e2239f996f9516fd to your computer and use it in GitHub Desktop.
Animated drawer component in React.js
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 Drawer from "./components/Drawer.tsx"; | |
| import { useAnimatedToggle } from "./hooks/useAnimatedToggle"; | |
| function App() { | |
| const { isOpen, shouldRender, onEnd,toggle } = useAnimatedToggle(); | |
| return ( | |
| <div className='m-4'> | |
| <button onClick={toggle}>toggle drawer {isOpen}</button> | |
| {shouldRender && <Drawer isOpen={isOpen} onEnd={onEnd} />} | |
| </div> | |
| ) | |
| } | |
| export default App |
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, useState } from "react"; | |
| export default function Drawer({ isOpen, onEnd }: { | |
| isOpen: boolean, | |
| onEnd: () => void | |
| }) { | |
| const [ mounted, setMounted ] = useState(false); | |
| useEffect(() => { | |
| setMounted(true); | |
| }, []) | |
| return ( | |
| <div | |
| onTransitionEnd={onEnd} | |
| className={`h-screen w-[22rem] fixed right-0 top-0 p-2 border-l bg-white transition-transform duration-300 data-[open=false]:translate-x-[22rem] data-[open=true]:translate-x-0`} | |
| data-open={isOpen && mounted}> | |
| {isOpen} | |
| content | |
| </div> | |
| ); | |
| } |
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 { useCallback, useState } from "react"; | |
| export enum DrawerState { | |
| Closed = 'closed', | |
| Opening = 'opening', | |
| Open = 'open', | |
| Closing = 'closing' | |
| } | |
| export function useAnimatedToggle() { | |
| const [state, setState] = useState<DrawerState>(DrawerState.Closed); | |
| const toggle = useCallback(() => { | |
| setState(s => | |
| s === DrawerState.Open ? DrawerState.Closing : DrawerState.Opening | |
| ); | |
| }, []); | |
| const onEnd = useCallback(() => { | |
| setState(s => | |
| s === DrawerState.Opening ? DrawerState.Open : DrawerState.Closed | |
| ); | |
| }, []); | |
| return { | |
| isOpen: state === DrawerState.Open || state === DrawerState.Opening, | |
| shouldRender: state !== DrawerState.Closed, | |
| toggle, | |
| onEnd | |
| }; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment