Last active
June 12, 2023 08:04
-
-
Save gaurangrshah/80e0af801677354b007ad21f6f73df58 to your computer and use it in GitHub Desktop.
Chakra-UI hook for quick & easy css animations.
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 { keyframes, usePrefersReducedMotion } from '@chakra-ui/react'; | |
/* | |
* Types | |
*/ | |
type CSSAnimation = { | |
keyframes: string; | |
animation: string; | |
}; | |
export type CSSAnim = Record<string, CSSAnimation>; | |
export type UseCssAnimationesult = string | undefined; | |
/* | |
* cssAnimations: pre-defined object of animations, the key of each animation is used to access the animation. | |
*/ | |
export const cssAnimations: CSSAnim = { | |
'slide-in-top': { | |
keyframes: keyframes`from {transform: translateY(100);} | |
to {transform: translateY(-100px);}`, | |
animation: '0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both', | |
}, | |
'slide-in-bottom': { | |
keyframes: keyframes`from {transform: translateY(-100);} | |
to {transform: translateY(100px);}`, | |
animation: '0.5s cubic-bezier(0.250, 0.460, 0.450, 0.940) both', | |
}, | |
}; | |
/* | |
* animateCSS: helper fn that returns an css animation string given a matching key. | |
*/ | |
export const animateCSS: ( | |
prefersMotion: boolean, | |
anim: string | |
) => string | undefined = (prefersMotion = false, anim = 'slide-in-top') => { | |
const animation = cssAnimations[anim] as CSSAnimation; | |
return prefersMotion && !!animation | |
? undefined | |
: `${animation.keyframes && animation.keyframes} ${ | |
animation?.animation && animation?.animation | |
}`; | |
}; | |
/* | |
* useCssAnimation: takes in a key which is used to access the corresponding animation using the animateCSS fn above. | |
* The final animation string is then returned from the hook | |
*/ | |
export function useCssAnimation(key = 'slideInTop') { | |
const prefersReducedMotion = usePrefersReducedMotion(); | |
const animation = animateCSS(prefersReducedMotion, key); | |
return animation as UseCssAnimationesult; | |
} | |
/* | |
* USAGE: | |
*/ | |
const Home = () => { | |
const animation = useCssAnimation('slide-in-top'); | |
return ( | |
<Container pos="relative" mt={32} maxW="2xl"> | |
<Heading as="h1" animation={animation}> | |
Create{' '} | |
<Text as="span" color="brand.300"> | |
My | |
</Text>{' '} | |
App | |
</Heading> | |
</Container> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment