-
Notifications
You must be signed in to change notification settings - Fork 17
Description
Feature
The Link component must be able to support different renderers, i.e. React Router or NextJS Link.
Approaches
This functionality can be added in different ways. The following approaches are taken from other design systems that support it.
linkComponent prop in Provider
Braid design system provides a prop in the BraidProvider called linkComponent. This prop receives a function that wraps the custom link.
Example:
const CustomLink = makeLinkComponent(({ href, ...restProps }, ref) =>
href[0] === "/" ? (
<ReactRouterLink ref={ref} to={href} {...restProps} />
) : (
<a ref={ref} href={href} {...restProps} />
)
)
// Then pass it to BraidProvider:
export const App = () => (
<BraidProvider theme={wireframe} linkComponent={CustomLink}>
...
</BraidProvider>
)
In our case we can provide this new prop in the ThemeProvider. This approach facilitates the use of a single Link in the application.
New prop
Most design systems choose to provide a new prop in the component. Rainbow and Fluent (example) call it as and Spark as element. In all the cases it can receive a react element, a function or a primitive type name.
Rainbow example:
const Link = ({ as, href, children, ...rest }) => {
const tag =
!!as ||
(href && href.startsWith('mailto:')) ||
(href && href.startsWith('tel:'))
? as
: NaviLink;
return (
<RainbowLink as={tag} href={href} {...rest}>
{children}
</RainbowLink>
);
};
This approach forces this prop to be used in all links used in the application.
Link component as style, not as functionality
Spectrum design system uses the Link component as a wrapper that applies styles to children. It also supports cases where the children are text but manage the click through onPress prop.
Example:
<Link>
<RouterLink to="/next-page">Next Page</RouterLink>
</Link>
This case allow users to use any type of element as a link. I think this approach is dangerous and we should be more restrictive.