Designing React components is easier with Cosmos

React has become the king of Javascript UI frameworks, with a tremendous rise in users, and reaching no less than 50000 stars on Github. It’s easy to see why: it allows building truly reusable UI components more easily than other competitors. It is also fast, sturdy and reliable.

All of the benefits of React – when combined with a single-page web app – can, however, lead to complications. Specifically, in the process of building a new component, you might feel the need to get visual feedback on it, for either styling or debugging matters. For example, previewing a button. Nonetheless, building and starting your entire application just for previewing that button is a slow and unnecessary process. This becomes more and more complicated if you’re using many components that have intricate relationships between them.

Read on to find out how we managed to solve this kind of problem and also how we improved the overall design experience for React developers.

Meet React Cosmos

react cosmos

In Hootsuite’s Bucharest office our front-end developers use a great open source tool for designing React components called React Cosmos. This DX (developer experience) tool provides your project with a powerful environment, in which you can easily:

  1. Render any of your project’s components under any combination of props and state – so you can easily see the output for a given input
  2. Observe how it reacts to prop changes in real-time, in a 2-way manner:
    • Edit the props/state and see the component update
    • Interact with the component and see its props/state change
Cosmos is a great tool and it helps frontend developers like me every time we need to create a new component or tweak something to an existing one. Being an open source project, Cosmos aims to make it easy to integrate it in any other project. To do that you only need to write some fixtures for your components. A fixture is simply a snapshot of the component, a serialization of its state and props at a given moment. Then, point Cosmos at those fixtures and you’re ready to go.

When I stumbled upon the project, it looked like this:

Cosmos before

Improvements

I loved using Cosmos from the start but our front-end developers and I felt that it needed some new usability features. So we all gathered together and came up with a list of improvements that would make Cosmos more delightful to use. I implemented these during my co-op term here. Here’s the list of improvements, all of which are now live in the core product, ready to use:

Scroll to selected fixture on reload

Problem

If your project has a huge component list, and you’re editing a fixture, then need a refresh, it’s tedious to scroll back to the fixture you were previewing.

Solution

Automatically scroll to the selected component on page load, so you can quickly see the component and fixture you are working on.

You can notice how we’re searching for the selected fixture’s ref and using scrollIntoView on its DOM node to make it just visible.

Make editor panel resizable

Problem

Aside from the left navigation panel, the editor was occupying half of the available space, with the preview taking up the other half. As these were fixed sizes, you might sometimes feel restrained by this layout. For example, you might need to render your entire app, which is big, but has no props at all. In this situation, the preview panel could use more breathing space.

Solution

For this I used the React split-pane package, that features a component which is able to render two children side by side with a divider bar between them. Dragging this bar allows resizing the two components, improving space management. It does this by wrapping its children in Pane elements, which listen to the divider bar changes and modify their size accordingly.

Cosmos split panes

Filter fixture and component names

Problem

Most of the time when booting up Cosmos, you have a specific fixture in mind, so scrolling through the fixture list is unnecessary. Also, you might want to filter components or fixtures by some criteria, e.g. see all the buttons.

Solution

A search bar was one of the most straightforward solutions to this problem. I added a minimal input field to the left panel, and only showed components and fixtures that matched the search. That was cool, but why not go one step further? Make the search algorithm fuzzy, and match against both fixture and component names.

This algorithm is implemented in the fuzzaldrin-plus package, also used by the Atom editor. It has several improvements over a classic matching algorithm, such as better acronym detection. You can find out more on the npm page.

cosmos side panel

Enhance editor capabilities

Problem

The editor is good for updating component props and state in real time, but it didn’t have a great look, and you could easily get lost in it. Imagine a fixture containing an array of 1000 elements. Now that’s some scrolling!

Solution

To enhance both its look and functionality, I had to replace the basic text area with a more powerful tool. I ended up using Codemirror, which features, among others:

  • Syntax highlighting: Not that important for JSON, but it makes keys stand out from the values. It has numerous themes available, for different keyword colors.
  • Code folding: This is the where Codemirror shines for my use case, as it allows folding of both curly (objects) and square (arrays) brackets. Those are automatically detected, so you can instantly press the arrows to collapse/expand a certain part of the code.
  • Line numbers: Not the most important feature either, but it helps to not get lost in the noise.
  • Smart indentation: This is useful both when manually writing code, as it indents the cursor when beginning a new line, and when pasting code, as it “prettifies” it.
Cosmos enhanced editor capabilities

Supporting Redux

Another framework that’s rapidly gaining popularity is Redux. It helps centralize the state of your application in a single store. You can read more about it here. This was a problem for Cosmos, since it couldn’t inject component state from the fixture.

What I did to solve this was to wrap the component in a “ReduxProxy”, a component which simply makes a fake Redux store available to its children via context, a cool React feature. Thus the rendered component could locate the store it also needed in its original environment.

Here’s how this “ReduxProxy” code looks:

You can see how the proxy creates a Redux store on initialization, then attaches that store on the context to make it available to the rendered component.Notice how we need to call createElement on its child, so that the proxy becomes the component’s owner. That way, context works correctly in older versions of React, too. More on owner-based vs parent-based context here.

What’s Next

Cosmos will continue to evolve, with me being an active part of its development With the introduction of the Redux proxy, we are working on making the proxy infrastructure a universal add-on system, where you can modify the rendered component at will. This opens up a whole new world of possibilities:
  • Alter component props
  • Render another component beside the original one
  • Make the component resizable or draggable
  • And many moreā€¦
Keep an eye on the project repository if you’re interested at https://github.com/skidding/react-cosmos

Conclusion

To round it up, I encourage you to try Cosmos if you’re developing React apps, especially large ones. All the improvements have helped us create React Components more easily, and since the tool is open source, I hope it will help you too.
About the Author
Bogdan StefanBogdan Stefan is a co-op on the Analytics UI team. He’s usually programming or reading technology related stuff. He also enjoys playing all kinds of games, like darts, basketball, chess and video games. Follow him on Twitter @bogdanjsx and Github @bogdanjsx.