Replies: 3 comments 6 replies
-
The import { Slot, Slottable } from "@radix-ui/react-slot";
export interface ButtonProps {
Icon?: React.ComponentType;
children: JSX.Element;
variant?: "contained" | "outlined";
}
export default function Button({
Icon,
children,
variant = "contained",
}: ButtonSlotProps) {
return (
<Slot className={variant}>
<svg><!-- ... --></svg>
<Slottable>{children}</Slottable>
</Slot>
);
} The |
Beta Was this translation helpful? Give feedback.
-
I was able to achieve something similar, maybe this help someone that comes across this discussion. Here is how I use it: <Button asChild iconRight={<Calendar />}>
<a href='#'>Add to calendar</a>
</Button> We get this: <a class="root-classes" href="#">
<span>Add to calendar</span>
<svg class="right-icon-classes"><!-- ... --></svg>
</a> Here is the implementation: const Button = forwardRef(
function Button({ asChild, children, iconLeft, iconRight, ...rest }, forwardedRef) {
const BaseSlot = asChild ? Slot : 'button'
const IconSlot = Slot
return (
<BaseSlot
ref={forwardedRef}
{...rest}
className='root-classes'}
>
<IconSlot className='left-icon-classes'>{iconLeft}</IconSlot>
<span>{children}</span>
<IconSlot className='right-icon-classes'>{iconRight}</IconSlot>
)
},
) Note: I didn't test the above code and my ACTUAL implementation is a bit different, but the idea is there. All that took for my use case was to simply use another Slot component inside the main one. |
Beta Was this translation helpful? Give feedback.
-
in this... if you are using the button like this: <Button icon={Icon} variant="contained">
<button onClick={(evt) => { console.log(evt); }}>Download</button>
</Button> Then you are passing an icon property as The component you specified is asking for the icon property to begin with an upper case i. <Button Icon={Icon} variant="contained">
<button onClick={(evt) => { console.log(evt); }}>Download</button>
</Button> or imo the cleaner way, changing your component to look like this? import { Slot } from "@radix-ui/react-slot";
export interface ButtonProps {
icon?: React.ComponentType;
children: JSX.Element;
variant?: "contained" | "outlined";
}
export default function Button({
icon,
children,
variant = "contained",
}: ButtonSlotProps) {
return <Slot children={children} className={variant} />;
} |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm moving away from the
as
prop and trying to reimplement my design system's polymorphic components usingSlot
.I'm stuck on the
Button
one. It should be able to take in and render anIcon
component.I think the final API should look like:
It should produce the following HTML:
But I'm struggling with the implementation of the component itself. This is what it currently looks like:
It works but, of course, it's not injecting the icon. And I can't see how to do so in such a way that I get the desired result.
My intuition is that the
Slot
design won't allow me to do what I want. So, my question is, is that the case? And if it is, do you know any workaround?Beta Was this translation helpful? Give feedback.
All reactions