Skip to main content
  1. All Posts/

react-toolbox

Tools JavaScript




React Toolbox is a set of React components that implement Google’s Material Design specification. It’s powered by CSS Modules and harmoniously integrates with your webpack workflow, although you can use any other module bundler. You can take a tour through our documentation website and try the components live!
Note: ⚠️ This source code refers to the future version. To check the source for 1.x go to master branch. There is a migration guide so you can start working with 2.0-beta.x now!

Installation

React Toolbox can be installed as an npm package:

$ npm install --save react-toolbox

Prerequisites

React Toolbox uses CSS Modules by default to import stylesheets written using PostCSS & postcss-preset-env features. In case you want to import the components already bundled with CSS, your module bundler should be able to require these PostCSS modules.
Although we recommend webpack, you are free to use whatever module bundler you want as long as it can compile and require PostCSS files located in your node_modules. If you are experiencing require errors, make sure your configuration satisfies this requirement.
Of course this is a set of React components so you should be familiar with React. If want to customize your components via themes, you may want to take a look to react-css-themr which is used by React Toolbox to make components easily themeable.

Usage in Create React App Projects

Create React App does not allow to change the default configuration, so you need an additional build step to configure react-toolbox in its project.
Follow these instructions to add react-toolbox to a project created with Create React App.

Usage in Webpack Projects (Not Create React App)

npm install postcss-loader --save-dev
npm install postcss postcss-preset-env postcss-calc --save

Configure webpack 1.x loader for .css files to use postcss:

{
        test: /.css$/,
        loaders: [
          'style-loader',
          'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss?sourceMap&sourceComments',
        ],
      },

Declare plugins to be used by postcss (as part of webpack’s config object):

// webpack.config.js
  postcss: () => {
    return [
      /* eslint-disable global-require */
      require('postcss-preset-env')({
        stage: 0, // required to get all features that were from cssnext without enabling them one by one
        features: {
          'custom-properties': {
            preserve: false, // required to output values instead of variables
          },
          'color-mod-function': true, // required to use color-mod()
        }
      }),
      require('postcss-calc'), // required as postcss-preset-env doesn't have a reduce calc() funtion that cssnext did
      /* eslint-enable global-require */
    ];
  },

Configure webpack 2.x or 3.x loader for .css files to use postcss:

// webpack.config.js
  {
    test: /.css$/,
    use: [
      "style-loader",
      {
        loader: "css-loader",
        options: {
          modules: true, // default is false
          sourceMap: true,
          importLoaders: 1,
          localIdentName: "[name]--[local]--[hash:base64:8]"
        }
      },
      "postcss-loader"
    ]
  }

Basic usage

In this minimal example, we import a Button with styles already bundled:

import React from 'react';
import ReactDOM from 'react-dom';
import { Button } from 'react-toolbox/lib/button';

ReactDOM.render(
  <Button label="Hello World!" />,
  document.getElementById('app')
);

Note: if you use it with Create React App, you need to make this additional change:

- import {Button} from 'react-toolbox/lib/button';
  • import Button from ‘react-toolbox/lib/button/Button’;

Take into account that any required style will be included in the final CSS so your final CSS would include Button styles in this case. It’s more efficient to import components this way (from 'react-toolbox/lib/button') (or with raw imports) because if you require from the project root (i.e. from 'react-toolbox'), every stylesheet of React Toolbox will be included, even if you don’t use it.

Importing components

First let’s take a look on how the components are structured in the project. The components folder contains a folder for each component or set of related components. For example, the app_bar:

 |- /app_bar
 |---- AppBar.js
 |---- config.css
 |---- index.js
 |---- readme.md
 |---- theme.css

As you can see in the previous block, each folder includes: a Javascript file for each component/subcomponent; a README with documentation, an index Javascript file that imports and injects styles and dependencies for you, a default theme PostCSS/preset-env stylesheet and a config.css with configuration variables (CSS Custom Properties). Depending on whether you want the styles to be directly bundled or not, you can import components in two different ways.

Bundled component

If you import from the index file, the imported component comes with all dependencies and themes already required and injected for you. This means that the CSS for each dependency will be bundled in your final CSS automatically and the component markup includes the classnames to be styled. For example:

import { AppBar } from 'react-toolbox/lib/app_bar';

Raw component

If you import from the component definition, the imported component is bundled with its dependencies, but it does not include any styles. This means no CSS will be bundled, and the component markup will not include any classname. It’s your responsibility to provide a theme to the component to be properly styled. You can do so via properties or context. For example:

import { AppBar } from 'react-toolbox/lib/app_bar/AppBar.js';

Customizing components

Every component accepts a theme property intended to provide a CSS Module import object that will be used by the component to assign local classnames to its DOM nodes. Therefore, each one implements a documented classname API. So if you want to customize a component, you just need to provide a theme object with the appropriate classname mapping.
If the component already has a theme injected, the properties you pass will be merged with the injected theme. In this way, you can add classnames to the nodes of a specific component and use them to add or to override styles. For example, if you want to customize the AppBar to be purple:

import React from 'react';
import { AppBar } from 'react-toolbox/lib/app_bar';
import theme from './PurpleAppBar.css';

const PurpleAppBar = (props) => (
  <AppBar {...props} theme={theme} />
);

export default PurpleAppBar;
.appBar {
  background-color: #800080;
}

In this case we are adding styles to a specific instance of an AppBar component that already has its default styles injected. It works because the component background by default has the same priority as the one we added. There will be cases where the original rule is more restrictive. For those cases you would need to boost priority using the same restrictions as in the original stylesheet. Feel free to take a look into the default theme.css files or just check the selectors you want to override in DevTools.
If the component has no styles injected, you should provide a theme object implementing the full API. You are free to require the CSS Module you want but take into account that every classname is there for a reason. You can either provide a theme via prop or via context as described in the next section.

Customizing all instances of a component type

Install react-css-themr with npm install react-css-themr --save
Create a CSS Module theme style file for each component type, for example for Button:

# /css/button.css

.button {
  text-transform: uppercase;
}

Create a theme file that imports each component’s custom theme style under the special theme key listed in that widgets’s documentation, i.e.:

# theme.js

import RTButton from './css/button.css';
import RTDatePicker from './css/datepicker.css';

export default {
  RTButton, RTDatePicker,
};

Wrap your component tree with ThemeProvider at the desired level in your component hierarchy. You can maintain different themes, each importing differently styled css files (i.e. import RTButton from './css/adminAreaButton.css') and can provide each one at different points in the tree.

import React from 'react';
import { ThemeProvider } from 'react-css-themr';
import theme from './theme';

class App extends React.Component {
  render() {
    return (
      <ThemeProvider theme={theme}>
        <div>
          ...
        </div>
      </ThemeProvider>
    );
  }
}
export default App;

Theming (configuration variables)

You can apply theming in multiple ways. First of all, you have to understand that React Toolbox stylesheets are written using PostCSS with postcss-preset-env features and use CSS Custom Properties from the config files we saw earlier. In addition, there are some global CSS Properties imported by each component: colors and variables. You can override both the global and component-specific variables to get the results you want using one of the methods below.

Settings configuration variables in JavaScript

You can override both the global and component-specific CSS Custom Properties at build-time by supplying an object with these variable names and your desired values to the PostCSS custom-properties plugin. i.e. if using postcss-preset-env in webpack:

// This can also be stored in a separate file:
const reactToolboxVariables = { 
  'color-text': '#444548',
  /* Note that you can use global colors and variables */
  'color-primary': 'var(--palette-blue-500)',
  'button-height': '30px',
};

// webpack's config object: (webpack.config.js)
const config = {
...
    postcss: () => {
    return [
      /* eslint-disable global-require */
      require('postcss-preset-env')({
        stage: 0, // required to get all features that were from cssnext without enabling them one by one
        features: {
          'custom-properties': {
            preserve: false,...