Skip to content

[Link] Customize rendered link #756

@marcialfps

Description

@marcialfps

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions