Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Link component and component context #466

Closed
connor-baer opened this issue Sep 5, 2019 · 4 comments · Fixed by #490
Closed

Add Link component and component context #466

connor-baer opened this issue Sep 5, 2019 · 4 comments · Fixed by #490
Assignees
Labels
📝 RFC Request for comment
Milestone

Comments

@connor-baer
Copy link
Member

connor-baer commented Sep 5, 2019

Visual

The Link component would be mostly functional and would have no specific visual styles itself.

Context

The Link component would be used wherever an <a> element would normally be used, such as in the Button or Navigation components. It would be particularly useful for more complex components on the molecule or organism stage in the Atomic Design methodology.

In order for the Link component to remain application-agnostic, there needs to be a way to customize it. This is where the component context comes into play. It allows to override the Link component with a custom one, e.g. from react-router, reach-router or Next.js.

The Link component API should follow the APIs of common routing libraries.

Here's an example of how the pieces fit together:

// Navigation.js in Circuit UI

export default function Navigation({ links }) {
  const { Link } = useComponents();

  return (
    <nav>
      {links.map(({ url, label }, i) => (
        <Link key={i} to={url}>
          {label}
        </Link>
      ))}
    </nav>
  );
}
// CustomNavigation.js in application

import { ComponentContext, Navigation } from '@sumup/circuit-ui';
import { Link } from '@reach/router';

export default function CustomNavigation(props) {
  return (
    <ComponentContext.Provider value={{ Link }}>
      <Navigation {...props} />
    </ComponentContext.Provider>
  );
}

The component context could be used for other components as well, e.g. a Head component. I'm successfully using this approach in my personal component library Bamboo UI.

State

Does this component have state? No.

Progressive enhancement

By default, the Link component renders an <a> element with an href attribute so a user is still able to navigate when JavaScript is disabled or crashes.

⚠️ This would likely require a breaking change.

@connor-baer connor-baer added the 📝 RFC Request for comment label Sep 5, 2019
@connor-baer connor-baer added this to the v2.0 milestone Sep 5, 2019
@connor-baer connor-baer mentioned this issue Sep 13, 2019
16 tasks
@fernandofleury
Copy link
Contributor

But how different is this from a regular <a> then?

@connor-baer
Copy link
Member Author

Let's take the Sidebar as an example. The navigation links need to be styled but are also deep in the sidebar structure and not easily accessible/customizable from the outside.

You could just render an a element, but that would do a normal browser navigation and trigger a full reload. In a SPA, you want to intercept the click event and handle the navigation programmatically. This is usually done with a Link component.

Often, these Link components do more than just attaching an onClick handler, such as transforming a to prop for a route into a full href. So a Link component that can be customised is the more powerful solution.

Does that make it clearer?

@connor-baer connor-baer modified the milestones: v2.0, v1.x Oct 14, 2019
@connor-baer connor-baer self-assigned this Oct 14, 2019
connor-baer added a commit that referenced this issue Oct 14, 2019
connor-baer added a commit that referenced this issue Oct 15, 2019
* feat(components): add ComponentsContext

ISSUES CLOSED: #466

* feat(components): use Link from context in Sidebar

* feat(components): use Link from context in Buttons

* docs(components): write guidelines on how to override base components

* docs(components): explain how to use the components in an app
@ilyanoskov
Copy link
Contributor

🎉 This issue has been resolved in version 1.2.2-canary.5 🎉

The release is available on:

Your semantic-release bot 📦🚀

@ilyanoskov
Copy link
Contributor

🎉 This issue has been resolved in version 1.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📝 RFC Request for comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants