Component Libraries

This section is to detail how other React Component Libraries operate and if they can offer new coding patterns for Flexera to adopt.

I have selected 3 of some of the most widely used React Component Libraries that are used by developers, with the aim of dissecting their component usage, syntax styles and so on.

For this comparison section I will be reviewing how each library handles their respective Button components. These are two of the most used components we use at Flexera, and each also needs to handle different variations, colors and handlers.

Let's get started!

Material UI

Button

To kick us off, to render a basic button component in Material UI you would need to use a combination of two props. "variant" is to tell us what style of button we want to use, such as contained or outlined. "color" is also required to change the theme of the button, such as primary, secondary etc.


  import { Button } from '@material-ui/core';

  function App() {
    return (
      <Button variant={'contained'} color={'primary'}>
        Hello World!
      </Button>
    );
  }

  export default App;
  

Compared to our own library, Flexera's Button component would only require one prop to get up and running as we default the appearance of the button to be that of a standard, fully background colored button, whereas Material UI wants us to declare this explicitly for each use of Button.

Semantic UI

Button

Semantic UI takes a different approach, instead preferring to use singular props to determine what a buttons "theme" or "color" should be. So instead of having a prop to set the color to "primary", instead you just add a prop called primary.


  import 'semantic-ui-css/semantic.min.css';
  import { Button } from 'semantic-ui-react';

  function App() {
    return <Button primary>Hello World!</Button>;
  }

  export default App;
  

I personally dislike this approach as it forces the consumer of the library to remember various prop names which all relate to the same subject, instead of having one prop which handles this like we currently do.

The other miss of Semantic UI is that it forces you to append their minified stylesheet to the root of your app as a singular import, which defeats the purpose of componentization.

Card

This analysis mostly covers each libraries Button component, but I wanted to highlight some syntax differences that Semantic UI takes when using "child" components.


  import React from 'react'
  import { Card, Icon, Image } from 'semantic-ui-react'

  const CardExampleCard = () => (
    <Card>
      <Image src='/images/avatar/large/matthew.png' wrapped ui={false} />
      <Card.Content>
        <Card.Header>Matthew</Card.Header>
        <Card.Meta>
          <span className='date'>Joined in 2015</span>
        </Card.Meta>
        <Card.Description>
          Matthew is a musician living in Nashville.
        </Card.Description>
      </Card.Content>
      <Card.Content extra>
        <a>
          <Icon name='user' />
          22 Friends
        </a>
      </Card.Content>
    </Card>
  )

  export default CardExampleCard
  

Semantic takes a different approach again when defining child components. Instead of having separate imports for every component, in their Card example the component exports Card Content, Card Header and Card Description to the default export of Card.

This allows consumers of the library to use syntax such as <Card.Content>...</Card.Content> without the need of having to add additional imports per component.

Ant Design

Button

Lastly, Ant Design. We only need to use a singular prop called "type" here to tell our button component how it should look color wise. This is good, but the problem here is their choice of prop naming.


  import { Button } from 'antd';
  import 'antd/dist/antd.css';

  function App() {
    return <Button type="primary">Hello World!</Button>;
  }

  export default App;
  

"type" is a native HTML attribute which can be attached to a button element to determine if it should be of type "submit", "button" or "reset". So already, the most widely used prop that consumers of the libraries will use is changing native HTML terminology. The way Ant design gets around this is by having a separate prop called "htmlType"

Ant Design also requires a manual import of their minified css file to the root of your app.

Theming

When building a component library it is important to offer customization options where relevant, to suit other teams or companies needs. The main extension to consider should be theming, which would allow a user of the library to customize a themes default values to their own needs.

Material UI provides some good documentation regarding theming which you can find here: https://material-ui.com/customization/theming/

The coding convention they use for this follows much the same pattern as modern state management libraries such as Redux, where we wrap a provider around our main entry component as you can see below:


  import { createMuiTheme } from '@material-ui/core/styles';

  const theme = createMuiTheme({
    palette: {
      primary: {
        main: '#ff4400',
      },
      secondary: {
        main: '#0044ff',
      },
    },
  });

  function App() {
    return (
      <React.StrictMode>
        <ThemeProvider theme={theme}>
          <App />
        </ThemeProvider>
      </React.StrictMode>,
    );
  }
  

Think of the above code to how we have created our BaseTheme object in the Component Library. The "theme" object referenced in the code snippet would essentially be our BaseTheme, and we are overwriting default values with custom ones to suit another design system.