DEV Community

kris
kris

Posted on • Originally published at blog.bitsrc.io on

Create React Tab component and shareable with Bit

Build a Reusable React Tab Component with Bit

Create a tabs component your team can use in all your apps.

Play with the component and install it with Bit

Tabs allow to break down the complex content into multiple sections. For instance, users can go through each section, one at a time.

Let’s create a reusable react component to handle your tabs. The project structure will be pretty basic:

  • App
  • Tabs
  • Tab

Then, we’ll use Bit to make it reusable from other apps. Let’s get started.

App Component

App is the container to all Tabs, Tabs is rendered with any content in it. Each child is rendered as a tab in the final output. All immediate children need to have a label. Also, the label appears as the Tab name in the output.

import React from 'react';
import Tabs from './Tabs';
import './Tab.css'

const App = () => {
  return (
    <div>
      <h1>React Tabs</h1>
      <Tabs>
        <div label="Home">This is the First Tab</div>
        <div label="Another">Yet another Tab!</div>
        <div label="Yet Another">This one's third</div>
      </Tabs>
    </div>
  );
};

export default App;

Tabs contains there divs with a label. Home, Another and Yet Another will be tab items to click on.

The children could have been any other component with valid JSX, but let's keep it simple for now.

Tabs Component

Each Tab is a child of the Tabs component. This is a required property and will be in an array.

static propTypes = {
    children: PropTypes.instanceOf(Array).isRequired
  };

Firstly, we need a state to track the current item. Use this state to display the content for each tab as each gets activated and style the active item differently.

state = {
    activeTab: this.props.children[0].props.label
  };

Here, the initial state is set to the label of the first children. The label can be accessed as prop of the children

We also need a method that changes the active tab.

onClickTabItem = (tab) => {
    this.setState({ activeTab: tab });
  };

In the render method of Tabs, destructure the children, active tab and onclick method.

const {
      onClickTabItem,
      props: { children },
      state: { activeTab }
    } = this;

Also, define variable content, this will store the content of the currently active tab. Render the contents in a separate div.

let content;

It’ll return two things: tabs list and tab content.

Map through the children and pass individuals to the Tab component and create a list.

Now, Pass the required props to the Tab component.

render() {
    const {
      onClickTabItem,
      props: { children },
      state: { activeTab }
    } = this;
    let content;
    return (
      <div className="tabs">
        <ol className="tab-list">
          {children.map((child) => {
            const { label } = child.props;
            if (label === activeTab) content = child.props.children;
            return (
              <Tab
                activeTab={activeTab}
                key={label}
                label={label}
                onClick={onClickTabItem}
              />
            );
          })}
        </ol>
        <div className="tab-content">{content}</div>
      </div>
    );
  }

And in the same loop, check for the activeTab state in all labels. The label_same as _activeTab is the active one. Tab content area The content area displays the children as content.

If you’re eager to see the output, replace return by return label. Now you’ll still get some output. Of course, you can’t change the tabs.

Tab component

We rendered the Tab component in Tabs. However, there’s no Tab component yet.

The passed props were key, activeTab, label and onClick.

Required props: activeTab , label and onClick. Mark them as required with prop types.

static propTypes = {
    activeTab: PropTypes.string.isRequired,
    label: PropTypes.string.isRequired,
    onClick: PropTypes.func.isRequired,
  };

Tab renders the passed label.

The onClick Function gets a label and the passed onClick function. On clicking the tab, it calls an incoming onClick method with the label as an argument.

onClick = () => {
    const { label, onClick } = this.props;
    onClick(label);
  };

Tab component returns the component with the passed label.

It gets above onClick method, label and activeTab from passed prop. All items get a default class of ‘tab-list-item’. The ‘tab-list-active‘ is the class for an active item. Now, append it to the class list if the activeTab is the same as the label. Mind the space between class names.

render() {
    const {
      onClick,
      props: { activeTab, label }
    } = this;

    let className = 'tab-list-item';

    if (activeTab === label) {
      className += ' tab-list-active';
    }

    return (
      <li className={className} onClick={onClick}>
        {label}
      </li>
    );
  }

All CSS for the class names are in index.css, use the same class names if you’d like to make the output look like the one below.

Make the component reusable with Bit

Components with Bit: choose, play, use

Bit is a cloud-based platform for components.

It helps your team organize and share reusable components, which can be used to build new applications much faster.

Components can be shared with Bit from different projects and libraries, and become available to discover, play-with, and install in your code.

Simply put, you can think of Bit as your component “Lego box” to which you can share components from any project, and then find and use them to build new things. Useful, right? there’s much more, but we won’t get into it now.

First, log in to Bit and create your component collection.

Now our collection is ready; let’s use Bit to quickly share the component from the repository it’s in (Bit does the “magic”; it automatically isolates the component and shares it to the cloud, without a single code or file change!).

Let’s share the tab component.

Install Bit

If you don’t have Bit already, install it globally using

npm install -g bit-bin

Initialize Bit for the project

Initialize Bit workspace with:

bit init

This command adds bit.json and .bitmap files so Bit can start tracking and isolating components in the repository when told to do so.

following bit document we need an entry point for component

create index.js and move all code from App.js

import React from 'react';
import Tabs from './Tabs';
import './Tab.css'

const Tab = () => {
  return (
    <div>

      <Tabs>
        <div label="Home">This is the First Tab</div>
        <div label="Another">Yet another Tab!</div>
        <div label="Yet">This one's third</div>
      </Tabs>
    </div>
  );
};

export default Tab;

Now, ask Bit to track all the components you put in src/components directory.

bit add src/components/\*

Set a Bit compiler for the workspace (I’ll use react) :

bit import bit.envs/compilers/react --compiler

and you can build your own components.

bit build 

Now, declare this as the 1.0.0 version.

bit tag --all 1.0.1

Run bit status again to confirm this version is attached:

Push them to the Bit remote scope:

bit export kriss.reactcomponent

That’s it! The component you just exported will now show in your collection.

Any comment-block above the component definition is used as the component description, and if I were to add tests- Bit would run them too.

components/tabs - reactcomponent · Bit

Conclusion

You’ve created a good Tabbed component for yourself and shared it with Bit. Now, you and your team can use it in any app you like, to build faster. Hope you enjoyed, and please feel free to comment and ask anything! Cheers 😃

Learn more


Top comments (0)