Although React and other Web frameworks make it easier to share components, sharing doesn’t happen by default. Challenges still exist, especially at an enterprise level, which demands extra efforts to coordinate among teams working on various products across organizations. In reality, even discovering components created by other teams is hard.
We would like to share how we reuse components at PayPal. While we are not readily sharing our solution codebase, we are eager to share our thoughts behind it. In particular, we try to address these problems:
- Enable discovery of components: Where can I find components?
- Ease sharing of components: How do I share my components?
- Enhance the quality of components: is the component compliant to PayPal design (e.g. accessibility, localization, mobile rendering, performance)?
- Enable collaboration in the Web community: How do we work collectively in UI development?
Why reusing components is critical
Creating a good quality UI demands thoroughness and accuracy in covering every possible use case. For example, this is a great article going through various use cases of an amount input field. As simple as a component looks, it requires strong attention to detail and takes iterative cycles for devs, designers, and products to make it right. If we are not reusing components, we are duplicating all these efforts behind it.
In reality, not every team can go through every design consideration. For example, developing an accessible website requires checking against an extensive accessibility checklist. It’s estimated that 20% of the population has a disability; that is, roughly 60 million of our customers could be impacted if we fail to be fully accessibility compliant. Similarly, developing localized UI is often an afterthought. Potential layout issues caused by translation and right to left languages are often overlooked. Ideally, a component would take care of these issues itself.
Finally, when teams are not reusing components, the UI and behavior across products may be inconsistent and confuse our customers. And it is simply a pain to do any brand UI update across all experiences.
Reusing components is crucial to solving these issues:
- It shortens time to market for products. A component “just works,” so developers can focus on high-level business logic. Research suggests that reusing components can save up to 40–81% of engineering time.
- It’s faster to resolve defects, as we will fix the shared component instead of dealing with dozens.
- UI experience will always be consistent across flows.
Why reusing components is challenging
Among many other challenges, the foremost challenge in reusing components is perhaps discoverability: Where do we find existing components? In particular, how do teams know if a component meets their needs? How do they ensure documentation of a component is up-to-date? And how can they be confident of the quality of a component? This is probably one of the most common asks in our Slack.
On the other hand, It is a big ask for a team to share components and the effort must be justified. Teams are pressured to release new features for their product. Compared to building components for their app only, sharing components takes extra effort to design and abstract. But what if the components end up not being reused at all? The pre-engineering that seems to be required for sharing components discourages people from publishing reusable components in the first place.
Several open-source solutions exist that attempt to address different facets of the challenge. We have evaluated these options based on ease of adoption, ease of maintenance, community, and features.
Bit does lots of cool things, including automatically turning code into an npm package and hosting it. In our experience, Bit
- is rich in features. It handles dependencies, builds configuration, and even allows changes back to source components from consuming apps;
- yet could be difficult to debug in case Bit fails to do the magic and thus could be a blocker in adoption as it requires developers to get a deep understanding of how Bit works;
- but the community size is still relatively small.
Component template such as electrode-explorer from Walmart creates components following a protocol, around which tools can be built to identify components and their usage. This approach
- makes tooling easier
- yet could be difficult to adopt as it asks (a big ask) teams to follow the new template and modify existing components.
Component playground such as Storybook renders an interactive playground for components. This approach:
- is easy to adopt because it adds on top of existing tech stack and plays well with current tech stacks.
- has a large community both outside and inside PayPal.
- yet usually only works for a single repository (Storybook v6 recently added a composition feature to include other storybooks)
Seeking for a balance between tech feasibility and convenience (automation vs. human involvement) while weighing against our goals has been a recurring exercise. We decide to leverage the component playground solution to build and render components. This approach avoids the challenge of building components and leaves component authors in control. Many component playground tools already take care of Webpack/Babel configuration, making it “zero configurable” with the flexibility of customization.
Among many similar tools, we chose Storybook because it has wide adoption in the open-source community as well as inside PayPal. Besides, Storybook comes with a powerful plugin system, which we can leverage to do quality auditing and other functions.
Component Explorer is our solution to sharing components by default at PayPal. On a high level, it enables component discovery by hosting and displaying components in a single place. It utilizes Storybook and
component cli to publish components, and
component bot to automate the workflow. In other words, components are created and documented with Storybook, and shared automatically in Component Explorer with
component cli and
component bot. Moreover, component quality is audited with a set of storybook addons included in our preconfigured
Enable component discovery
Component Explorer (Cx) hosts all components and serves as the single source of truth for component discovery. Some highlighted features include:
- Components are interactive. You can play with a component without installing it. Not only developers but also non-technical people such as designers and products can explore design in Cx.
- Components are documented. Documents are generated with Storybook docs, including how to use the component, the props the component accepts, and various rendering scenarios.
- Components are version tracked. Cx hosts all versions of a component since published. People can trace back when a breaking UI change was introduced or check the UI evolution.
- Usage of components is tracked. Cx displays what production apps are using a component. This metric suggests the quality of a component as well as helps component owners to track usage and get credit.
- Component quality is audited. Thanks to the powerful plugin system of Storybook, components can be audited for accessibility, localization, mobile rendering, performance, etc.
Ease component sharing
Component Explorer provides tooling to power a distributed approach to sharing components; that is, every product team can easily publish their components.
component-cliis a CLI tool we created to deploy Storybook and register components in Cx. It captures component metadata (name, version, snapshot, etc) and drops the deployed link.
component-botis a GitHub App that automates the publishing workflow. When a PR is opened, it deploys the components and drops a preview link, with which the team can preview UI changes during peer review. Besides, after the PR is merged, the bot will automatically publish the new components to Cx so that documentation is always update-to-date.
Share packaged and non-packaged components
Component Explorer allows for sharing both packaged components and components that are not npm published (yet). It is critical because the majority of components product teams build are non-packaged and live within their product apps. Being able to share non-packaged components invites broader contributions. Teams don’t have to go to any lengths to extract the component into a separate repo and publish it to npm. Instead, they can start sharing right from within their repo.
Further, sharing non-packaged components avoids the issue of pre-engineering discussed earlier. It enables a different model of collaboration: A component is shared by default; the team only needs to apply further efforts when other teams reach out for reusing the component. Even more excitingly, with module federation coming in Webpack5, components might be shared directly from Cx without being published to npm.
Finally, sharing non-packaged components makes it possible to share components that are not intended to reuse at all, but to share, e.g. pages as components, allowing for open, easy access to products.
Page as Component
Components can be more than a UI atom. Components can be put together to form a larger widget, which can be pieced together to form a whole page. Therefore in Cx, people can share a component as small as a button, to a widget like a credit card form, to a checkout page, and even flow.
Sharing product pages and flows encourages people to work more openly and efficiently. It also helps teams and higher leadership gain insights into the current product portfolio. Our vision is to have open, easy access to every PayPal product page in Cx.
The success of Component Explorer relies on the community: engineers, designers, and product managers. Building a community is not only about tooling, but also organization culture and people’s mindset. Component Explorer is a good start to change how teams develop UI (e.g. share components by default), and these shared components open up new opportunities of collaboration across teams. We see a shared value Component Explorer presents to the community; that is, we want teams to:
- work more openly and efficiently with each other and to speed up the pace of innovation;
- reduce the siloing, duplicated effort, and miscommunication between teams;
- produce functions that support the broader success of our community;
- be recognized for their contributions.
We are in an early stage and are still exploring/experimenting best practices of component sharing. In upcoming posts, we’ll share our thoughts on component auditing, community building, and component-driven development practices.
Thoughts? We would love to hear your team/organization’s practice of sharing/reusing components. You can either leave a comment below or DM me on twitter at @imdongchen!