Skip to content

Instantly share code, notes, and snippets.

@gaurangrshah
Last active June 12, 2023 08:04
Show Gist options
  • Save gaurangrshah/80e0af801677354b007ad21f6f73df58 to your computer and use it in GitHub Desktop.
Save gaurangrshah/80e0af801677354b007ad21f6f73df58 to your computer and use it in GitHub Desktop.
Chakra-UI hook for quick & easy css animations.
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