Polymorphic Slot
Usage
API References
Combines and passing data with a render props onto its immediate child.
Support
- The
asChild
prop will pass all the props you created yourself even the Slotref
to its direct child. - Using
ref
,attributes
andevent handlers
according to theel=""
you use, - Freestyle variables are used without affecting the default style
Alternative
By default we use twMerge
to prioritize the tailwindcss style of PolymorphicSlot
over its immediate child style. You can customize it at any time if you are not using tailwindcss.
If you prefer to use Slot
from radix you can combine Polymorphic
with radix dependencies using the following command:
- Install @radix-ui/react-slot
- Import dependencies and Customize PolymorphicSlot:
import * as React from "react";
import { Slot as PolymorphicSlot } from "@radix-ui/react-slot";
const Slot = <T extends React.ElementType = "div">({ asChild = false, el, ...props }: ElementType<T>, ref: PolymorphicSlotRef<T>) => {
const Component = asChild ? PolymorphicSlot : ((el || "div") as React.ElementType);
return <Component ref={ref} {...props} />;
};
If you don't need the element to pass its props, you can simplify it in a nutshell as below:
import * as React from "react";
export type PolymorphicRef<T extends React.ElementType> = React.ComponentPropsWithRef<T>["ref"];
export type PolymorphicWithoutRef<T extends React.ElementType, Exclude extends string = never> = Omit<React.ComponentProps<T>, "ref" | "style" | Exclude> & {
el?: T;
style?: React.CSSProperties & {
[key: string]: any;
};
};
const Element = <T extends React.ElementType = "div">({ el, ...props }: PolymorphicWithoutRef<T>, ref: PolymorphicRef<T>) => {
const Component = (el || "div") as React.ElementType;
return <Component ref={ref} {...props} />;
};
export default React.forwardRef(Element) as <T extends React.ElementType = "div">(
props: PolymorphicWithoutRef<T> & { ref?: PolymorphicRef<T> }
) => React.ReactElement | null;
ref and all property default as div
function MyComponent() {
return <Polymorphic />;
}
function MyComponent() {
return <Polymorphic el="a" href="" />;
}
function MyComponent() {
return <Polymorphic el="img" src="" />;
}
function MyComponent() {
return (
<Polymorphic
el="nav"
style={{
width: "var(--sz)",
height: "var(--sz)",
"--sz": "0.75rem",
"--bg-open": "var(--background)"
}}
/>
);
}
Passing ref
and attributes
to element or component as a single child
function MyComponent() {
const containerRef = useRef < HTMLElement > null; // if usage with ref
return (
<Polymorphic
ref={containerRef}
asChild
style={{
width: "var(--sz)",
height: "var(--sz)",
"--sz": "0.75rem",
"--bg-open": "var(--background)"
}}
>
<aside>
<h6>Title</h6>
<section>Content</section>
<section>Content</section>
</aside>
</Polymorphic>
);
}