kripod / react-polymorphic-types

Zero-runtime polymorphic component definitions for React
MIT License
195 stars 8 forks source link

Allow the use of an IntrinsicElements Subset #10

Closed GianlucaGuarini closed 1 year ago

GianlucaGuarini commented 2 years ago

This PR allows the use of a subset of the JSX.IntrinsicElements.

The use case is for example:

import type { PolymorphicPropsWithoutRef } from "react-polymorphic-types";

// An HTML tag or a different React component can be rendered by default
export const HeadingDefaultElement = "h2";
// The list of the jsx nodes allowed
export type HeadingAllowedElements = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'

// Component-specific props should be specified separately
export type HeadingOwnProps = {
  color?: string;
};

// Extend own props with others inherited from the underlying element type
// Own props take precedence over the inherited ones
export type HeadingProps<
  T extends React.ElementType = typeof HeadingDefaultElement
> = PolymorphicPropsWithoutRef<HeadingOwnProps, T, HeadingAllowedElements>;

export function Heading<
  T extends React.ElementType = typeof HeadingDefaultElement
>({ as, color, style, ...restProps }: HeadingProps<T>) {
  const Element: React.ElementType = as || HeadingDefaultElement;
  return <Element style={{ color, ...style }} {...restProps} />;
}

@kripod Probably this PR needs a bit more work to make it backward compatible but let me know if you are interested into this feature.

GianlucaGuarini commented 2 years ago

And with https://github.com/kripod/react-polymorphic-types/pull/10/commits/0ac3bf14b18241395614083904724b698cfb499e it should be also backward compatible ;)

kripod commented 2 years ago

Hello,

Thank you for your PR. I’m not sure what the benefit of this change would be.

GianlucaGuarini commented 2 years ago

Hi @kripod according to the example provided above you get these results

// typecheck errors (allowed with the current implementation)
<Heading as='div'>Hello</Heading>
<Heading as='input'>Hello</Heading>

// allowed
<Heading as='h1'>Hello</Heading>
<Heading as='h2'>Hello</Heading>
<Heading as={FancyComponent}>Hello</Heading>

Restricting the type of JSX.IntrinsicElements allowed without relying on runtime checks is a big advantage in term of ergonomic of the Polymorphic components.

andersonba commented 2 years ago

Hi, I liked the proposal. Is there any chance of being integrated? Thank you!

donferi commented 2 years ago

Likewise, I have a use-case where I want to limit it to button | a

knoefel commented 1 year ago

@kripod Any thoughts if it will be integrated into the lib? I have the same use-case as @donferi and i think it would be a great addition. In any case thanks for this great TS lib!

GianlucaGuarini commented 1 year ago

I close this PR since probably it will never get merged. The Changed proposed here and many other improvements were implemented into this new package https://github.com/axa-ch/react-polymorphic-types. Kudos to @kripod for such a brilliant work tough ✌️