primitives icon indicating copy to clipboard operation
primitives copied to clipboard

Allow more props in radix-slot (TypeScript)

Open Phoenixmatrix opened this issue 1 year ago • 3 comments

Feature request

Overview

radix-slot's props extend React.HTMLAttributes<HTMLElement>. That is fine most of the time, but for more specialized scenarios, one may want to pass down more props. For example, if building a wrapper for form elements, you may need to forward the "name" prop, which isn't part of HTMLAttributes.

Aside for the types, radix-slot fully works with this scenario. Just need to make TypeScript happy.

Examples in other libraries

Not public, but right now I used the nuclear approach, and reexported my own slot, using the following snippet. It's not great because now it allows any and all attributes, but it unblocked me. I wonder if it could be improved by allowing passing generic types directly, or a factory function that returns a custom component with the exact props one may want.

import { Slot as ReactSlot } from "@radix-ui/react-slot";

export interface SlotProps extends React.AllHTMLAttributes<HTMLElement> {
	children?: React.ReactNode;
}

const Slot = ReactSlot as React.ForwardRefExoticComponent<
	SlotProps & React.RefAttributes<HTMLElement>
>;

export { Slot };

I could see something like this:

const CustomSlot = createSlot<React.InputHTMLAttributes>();

<Custom slot ....></CustomSlot>

Who does this impact? Who is this for?

Specialized slot use cases. I hit it when trying to modify Shadcn/ui's Form component to work better with Remix. Shadcn normally uses react-hook-form, which is client side and doesn't always need name props. Or you can set the name prop on the child component yourself.

But I wanted the wrapper component to get the name prop and pass it down to the child automatically. The types are currently preventing that.

Additional context

The reexport example above works fine and is an okay workaround, but something upstream would be great.

Phoenixmatrix avatar Oct 20 '23 15:10 Phoenixmatrix

I used this variant image

Aleksandr-Karikov avatar Feb 21 '24 05:02 Aleksandr-Karikov

I think that making Slot a generic would be nice

type SlotPropsGeneric<Attr extends React.HTMLAttributes<HTMLElement> = React.HTMLAttributes<HTMLElement>> = Attr & {
    children?: React.ReactNode;
};

type ElementAttributes<El extends HTMLElement> = El extends HTMLInputElement
    ? React.InputHTMLAttributes<El>
    : React.HTMLAttributes<El>;

type SlotGeneric<T extends HTMLElement> = React.ForwardRefExoticComponent<
    SlotPropsGeneric<ElementAttributes<T>> & React.RefAttributes<T>
>;

const InputSlot = Slot as SlotGeneric<HTMLInputElement>;

alissawix avatar Feb 26 '24 06:02 alissawix

I came here to open an issue but found this one. Any updates regarding the generic props for Slot?

This is how we will use it:

function GenericSlot<P = React.HTMLAttributes<HTMLElement>>(props: SlotProps & P) {
	return <Slot {...props} />;
}

return (
	<GenericSlot<React.ComponentProps<"svg">>
		width={"100"}
		height={undefined}
		className="w-[50px] md:w-[100px]"
	>
		{children}
	</GenericSlot>
);

MuhammadSawalhy avatar Apr 08 '24 23:04 MuhammadSawalhy