-
Notifications
You must be signed in to change notification settings - Fork 58
Open
Labels
Description
Is there an existing issue or pull request for this?
- I have searched the existing issues and pull requests
Feature description
Adding a tag is a very interesting feature. As an advanced abstraction layer, it can determine the type of element to render based on the passed-in tag. This is particularly useful in scenarios that require dynamic rendering. For example, we may need to render different elements based on various conditions and add animation effects.
Desired solution
import { AnimatePresence, motion } from 'motion/react';
import { If } from 'react-if';
function List({ loading, list }) {
const [tag, setTag] = useState('h1');
return (
<If condition={!loading} tag={AnimatePresence} initial={false}>
<Then
tag={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{/* ... */}
</Then>
<Else
tag={motion.div}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{/* ... */}
</Else>
</If>
);
}Corresponding implementation:
import type { JSX } from 'react'
import { createElement } from 'react'
export type WrapperTag = keyof JSX.IntrinsicElements | Function
export type WrapperProps<Kag extends keyof JSX.IntrinsicElements | React.FC | unknown> =
{ tag?: Kag } &
(Kag extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[Kag] : unknown) &
(Kag extends React.FC<infer P> ? P : unknown)
export function wrapper(tag: any, props: unknown, children?: React.ReactNode) {
return tag ? createElement(tag, props, children) : children
}
// if.tsx
export type IfProps<Kag> = WrapperProps<Kag> & {
condition?: BooleanLike
children?: ReactNode
}
export function If<K extends WrapperTag>(props: IfProps<K>) {
const { condition, children, tag, ...attrs } = props
// ...
return wrapper(tag, attrs, content)
}Alternatives considered
none
Additional context
No response