![Introducing Enhanced Alert Actions and Triage Functionality](https://cdn.sanity.io/images/cgdhsj6q/production/fe71306d515f85de6139b46745ea7180362324f0-2530x946.png?w=800&fit=max&auto=format)
Product
Introducing Enhanced Alert Actions and Triage Functionality
Socket now supports four distinct alert actions instead of the previous two, and alert triaging allows users to override the actions taken for all individual alerts.
@leafygreen-ui/polymorphic
Advanced tools
Readme
pol·y·morph (noun)
- an organism, inorganic object or material which takes various forms.
pol·y·mor·phic (adjective)
- occurring in several different forms, in particular with reference to species or genetic variation.
- (of a feature of a programming language) allowing routines to use variables of different types at different times.
Polymorphic
is a suite of types, hooks, components and factories that allows users to create components that can render as any HTML element or React component.
There are two main ways to use Polymorphic
, depending on whether the as
prop is defined internally by your component, or passed in as an external prop.
If the logic defining the as
prop is defined internally within your component, use the standalone Polymorph
component.
A simple example of this may be rendering an element as a header or paragraph text depending on certain props passed in.
interface MyProps {
someProp: string;
}
const MyComponent = (props: MyProps) => {
const shouldRenderAs = props.isHeader ? 'h1' : 'p';
return <Polymorph as={shouldRenderAs} {...props} />;
};
If you want to expose as
as a prop of your component, use the Polymorphic
factory function and related hooks.
This is likely the more common use case, since it allows you to create new polymorphic components (such as a Button
component that can render as a link, etc.)
Note that any inherited props will be indeterminate in the factory function, since the value as
is not known. (i.e. the attributes of rest
in the following example are unknown).
interface MyProps {
someProp: string;
}
const MyComponent = Polymorphic<MyProps>(({ as, ...rest }) => {
const { Component, ref } = usePolymorphic(as);
return <Component ref={ref} {...rest} />;
});
Accepting a forwarded ref to a Polymorphic component is as simple as passing in a ref into the render function (same as React.forwardRef
).
interface MyProps {
someProp: string;
}
const MyComponent = Polymorphic<MyProps>(({ as, ...rest }, forwardedRef) => {
const { Component } = usePolymorphic(as);
return <Component ref={forwardedRef} {...rest} />;
});
React Server Components do not support React Client Component APIs, such as React.useRef
. To avoid React Client APIs, use the usePolymorphicComponent
and useInferredPolymorphicComponent
hooks instead.
Note that forwardedRef
is still allowed.
interface MyProps {
someProp: string;
}
const MyComponent = Polymorphic<MyProps>(({ as, ...rest }, forwardedRef) => {
const Component = usePolymorphicComponent(as);
return <Component ref={forwardedRef} {...rest} />;
});
as
propComponents extended using the Polymorphic
factory function can be made to infer the as
prop value based on the href
passed in.
Ensure the custom props are wrapped in InferredPolymorphicProps
, and use the useInferredPolymorphic
hook.
Make sure to pass both as
and a rest
object (that may contain href
) into the hook.
export const MyInferredComponent = InferredPolymorphic<
InferredPolymorphicProps<MyProps>
>(({ as, ...rest }) => {
const { Component, ref } = useInferredPolymorphic(as, rest);
return (
<Component ref={ref} {...rest}>
{title}
</Component>
);
});
//
<MyInferredComponent href="mongodb.design" />; // renders as <a>
as
with a default valueSometimes, when developing a component that uses Polymorphic, you'll want to set a default value for the as
prop.
For example, when creating a Button component, you may want to have the as
prop default to the HTML button
element.
To set a default value for the inferred as value, you'll need to provide the default value both to TypeScript and React:
export const MyInferredComponentWithDefault = InferredPolymorphic<
ExampleProps,
'button'
>(({ as = 'button', title, ...rest }) => {
const { Component, ref } = useInferredPolymorphic(as, rest);
return (
<Component ref={ref} {...rest}>
{title}
</Component>
);
});
Note: When a component is InferredPolymorphic
, the href
will force the component to render as an anchor, and will override any default value.
<MyInferredComponentWithDefault />; // as <button>
<MyInferredComponentWithDefault href="mongodb.design" />; // as <button>
styled
APIPolymorphic
also supports usage with Emotions styled
API. To get TypeScript to accept the Polymorphic props you'll need to explicitly type your styled component as PolymorphicComponentType
.
const StyledPolymorph = styled(Polymorph)`
color: hotpink;
` as PolymorphicComponentType;
// or
const MyStyledComponent = styled(MyComponent)`
color: hotpink;
` as typeof MyComponent;
This also works with InferredPolymorphic components
const StyledInferred = styled(MyInferredComponent)`
color: hotpink;
` as typeof MyInferredComponent;
Since Polymorphic components are strictly typed, to use styled props with Typescript you will need to define the additional props you expect to use within styled, and pass these into styled as generic type.
interface StyledProps {
color: string;
}
const MyStyledComponent = styled(MyComponent)<StyledProps>`
color: ${props => props.color};
` as StyledComponent<
StyledProps & PolymorphicProps<PolymorphicAs, ExampleProps>
// or StyledProps & InferredProps<PolymorphicAs, ExampleProps>
>;
Note: TSDocs will not compile for styled polymorphs. This can be remedied by creating a wrapper around the styled function that explicitly returns a PolymorphicComponentType
While it is possible to use the Polymorph
component to extend polymorphic behavior, it can be much more verbose and error prone than using the Polymorphic
factory function. For completeness, an example of how to do this is provided below:
type MyProps<T extends PolymorphicAs> = PolymorphicPropsWithRef<
T,
{
someProp: string;
}
>;
export const MyComponent = <T extends PolymorphicAs = 'div'>(
{ as, title, ...rest }: MyProps<T>,
forwardedRef: PolymorphicRef<T>,
) => {
return (
<Polymorph as={as as PolymorphicAs} ref={forwardedRef} {...rest}>
{title}
</Polymorph>
);
};
FAQs
LeafyGreen UI Kit Polymorphic
We found that @leafygreen-ui/polymorphic demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports four distinct alert actions instead of the previous two, and alert triaging allows users to override the actions taken for all individual alerts.
Security News
Polyfill.io has been serving malware for months via its CDN, after the project's open source maintainer sold the service to a company based in China.
Security News
OpenSSF is warning open source maintainers to stay vigilant against reputation farming on GitHub, where users artificially inflate their status by manipulating interactions on closed issues and PRs.