Skip to content

Instantly share code, notes, and snippets.

@ryonakae
Last active April 8, 2022 02:25
Show Gist options
  • Save ryonakae/8dab4d3a33f03e862f19ad5995c8b9a3 to your computer and use it in GitHub Desktop.
Save ryonakae/8dab4d3a33f03e862f19ad5995c8b9a3 to your computer and use it in GitHub Desktop.
Custom Polymorphic Component by Framer Motion with TypeScript
import { HTMLMotionProps, motion } from 'framer-motion'
import { forwardRef, ReactNode } from 'react'
type HeadingTags = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
type HeadingProps = {
as: HeadingTags
children: ReactNode
}
const CustomTagComponent = forwardRef<HTMLHeadingElement, HeadingProps>(
({ as: CustomTag, children, ...props }, ref) => {
return (
<CustomTag ref={ref} {...props}>
{children}
</CustomTag>
)
}
)
CustomTagComponent.displayName = 'CustomTagComponent'
const MotionComponent = motion(CustomTagComponent)
const Heading: React.VFC<HTMLMotionProps<HeadingTags> & HeadingProps> = ({
as,
children,
...props
}) => {
return (
<MotionComponent
as={as}
// framer-motion settings example
transition={{ duration: 1 }}
variants={{
initial: {
opacity: 0
},
show: {
opacity: 1
}
}}
initial="initial"
whileInView="show"
{...props}
>
{children}
</MotionComponent>
)
}
export default Heading
import Heading from 'path/to/Heading'
const Index: React.VFC = () => {
return (
<div>
<Heading as="h1" transition={{ duration: 0.5 }}>
This is animated H1!
</Heading>
<p>You can pass any framer-motion props</p>
</div>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment