demo)
react-easy-styleguide (This is a tool to easily get a styleguide integrated into your project. It works great with create-react-app
.
note: In the screenshots I used Bootstrap styles as a way of showing some basic components and styles, but of course you can use it with your own styles and components.
Although there are some really neat styleguide tools for React, they don't really work when you are not using CSS modules. If you rely on global css (for example because your components use styles from Bootstrap, or other CSS frameworks), it seems impossible to use those styles properly without styles conflicting.
Screencast
I've recorded a screencast showing how to integrate the tool into your project. View the screencast.
Installation
run npm install react-easy-styleguide
Requirements
The module relies on Webpack's require.context
, and therefore it needs webpack. I think that should be the only required thing, but let me know in the Issues if there's a problem.
Setup
To start, we need to tell the styleguide which components to load, it expects a component.info.js
file to be present for every component in your styleguide, so we use WebPack's requireContext to load them dynamically.
// Assuming you have a /components folder,
const styleguideContext = require.context('./components/', true, /.info.js$/)
Then require the create function from react-easy-styleguide
. This function takes a couple of setup parameters and will return a React component:
import { create as createStyleGuide } from 'react-easy-styleguide';
import PropTypes from 'prop-types';
const Styleguide = createStyleGuide(styleguideContext, {
name: 'My StyleGuide',
propTypes: PropTypes
path: '/styleguide' // this is the default
})
The second argument to styleguide's create
function is optional, but allows for passing a name
(title) and a propTypes
and path
property. Passing along a PropTypes property will allow the (limited) detection of PropTypes for your components.
The component returned by the create
function can receive two props: component
and variation
. This will tell the styleguide which component to load, and which variation of this component to highlight.
If you are using react-router, you can mount this component like this:
const Styleguide = createStyleGuide(styleguideContext, {
// pass `Link` or NavLink` to the styleguide to use react-router
// for navigating.
routerLink: require('react-router-dom').NavLink,
…
})
<Route
path="/styleguide/:component?/:variation?"
component={Styleguide}
/>
By default, react-easy-styleguide
expects to be mounted at /styleguide
, but by passing path
you can change this to anything else, for example when your entire app is mounted in a subfolder.
If you start your app now, and go to /styleguide
, you should be able to see the styleguide running.
Adding components to your styleguide
For each component you want to show in your styleguide, you need to call react-easy-styleguide
's register
function as shown below. I recommend you create a .info.js
file for each component. For example, if you have a file called Button.js, you can create a buttons.info.js
file:
// The component you want to add
import Button from './Button';
import { register } from 'react-easy-styleguide';
// Register takes 5 parameters:
register(
// 1. The component, or an object containing Component, propTypesComponent:
Button,
// 2. A component description (supports Markdown)
` How do you like this description? `,
// 3. A list of different variations for each component,
// optionally with description
[
{
name: 'Default',
description: 'How do you like _this_ description?',
props: {
label: "Hello!"
}
},
],
// 4. Optionally; a list of default props that will be applied to all variations
{
someProp: 'Hello'
}
// 5. Optionally, a Higher Order or wrapping component, in case you need to pass some extra props to it, like a Redux connected component.
reduxWrapper
)
If you intend to use react-easy-stylesheet
in a minified bundle on a server, your component names might get mangled and show up as one-letter items in the navigation. You can add a displayName
property to the component, or manually register the name:
Manual registration
In some cases, you might want to manually pass the name and proptypes to the register
function, for example the name or proptypes cannot be obtained from the component passed. This might happen when you've wrapped your components in another component.
register(
{
Component: ComponentToBeRendered,
propTypesComponent: ComponentToGetPropTypesFrom,
name: 'Input' // Optional, defaults to propTypesComponent's displayName or name.
},
…
)
Action helper
You can also use the action
helper function to easily log things that happen, for example in onClick Handlers:
import { register, action } from 'react-easy-styleguide';
…
{
name: 'Default',
description: 'How do you like _this_ description?',
props: {
label: "Hello!",
onClick: action('Basic button happenings!')
}
},
When the function is executed, it will print out a console message with the text you provided and the arguments passed, something similar to this:
[ACTION] Basic button happenings! ▶︎ [Proxy, Event]
Colors and Typography
Styleguides often have a list of colors and Typographic styles, react-easy-styleguide comes with ways of easily registering these for use in the styleguide: ColorList
and TypeList
, respectively.
Like with components, you can create a design.info.js
file and call the register()
from it. Instead of passing a Component class, use the ColorList
or TypeList
components, they each receive an object, the keys being the display name, and the value the CSS class that should be applied to the element to see the style.
import { register, ColorList, TypeList } from 'react-easy-styleguide';
register(
ColorList({
'Brand Red': 'color-brand',
'Brand Blue': 'color-blue',
'dark': 'color-dark',
'dark-mid': 'color-dark',
'light': 'color-light'
}),
`The colors of this app are very important!`
)
register(
TypeList({
'Main heading': 'type-h1',
'Smaller Heading': 'type-h2',
'Body text': 'type-body',
'Smaller': 'type-smaller',
}),
`The typography of this app is very important!`
)
A note on component order
Although *.info
files in the component folder should be picked up automatically, the order in which this happens can be arbitrary. Since you might want to have the colors and typography at the top of the component list, you might want to explicitly import/require this file before you create the styleguideContext:
require('./design.info.js');
const styleguideContext = require.context('./components/', true, /.info.js$/)
Higher Order Components / Redux
Sometimes you might want to wrap a styleguide component in another component to make sure the dataflow is correct. The fifth parameter in the register
function takes a wrapping component class, which will be passed a Component
and componentProps
prop. Here's an example component you might pass:
import { connect } from 'react-redux';
import React from 'react';
function StyleGuideWrapper(props) {
const {Component, componentProps, storeData, ...rest} = props;
return (
<Component {...componentProps} storeData={storeData} {...rest} />
);
);
export default connect(
storeData => ({ storeData: storeData.styleGuide }),
dispatch => ({
…
})
)(StyleGuideWrapper)