Dealing with UI Kit
A UI kit is a set of easily reusable visual components like buttons, drop-downs, calendars, etc. For developers using it, UI kit reduces low-level interaction with OS\Browser platform.
As a style guide, it also provides a unified language for communicating with designers and makes visual look of different parts of the product more consistent. This leads to faster development and provides an ability for developers to focus on more important part of their work.
Developing a UI Kit
Develop proper UI kit from the beginning is maybe not the best idea because it will consume a lot of time without any short term return. But you can start to follow one basic practice: put all low-level components with their styles into a separate folder. It will make it easier to extract it later into its own separate package.
When our product started growing up, the benefits from having UI Kit also increased. It is important to find a moment when time for building such a thing will save you more development time down the road. It’s also important that you only add simple and widely used components at the beginning, like buttons, dropdown, inputs, texts. Adding components used once or twice (and no plans to increase in number) in the product will not provide much benefit.
Yet another UI kit
Why companies still want to build their own UI kits when there are plenty of options out there, such as Material design, Semantic UI, Bootstrap amongst others? In my opinion, the main reasons are time and branding. Time spent on adopting (learning and changing) external UI kit could be significantly long in case the product has its own design, like in many b2c sites. The UI elements are like continuation of the brand, which is growing users retention.
Travix UI kit
At Travix we started using a CSS framework called Ink. Soon we realized its limitations and we decided to get rid of it. After we were done with Ink we created a separate folder and moved in all new components. As our platform was getting more stabilised, we open sourced it so it could be available for 3rd party developers and the web community world-wide.
The uniqueness of our platform
We have five different brands. They have their own color schemas, fonts, round radiuses, shadows, etc.
These brands support in total 30+ different languages, as so it happens, we have to deal with cases in which in a supported language more characters appear or words that are too long could break the layout and not conform to a container’s width.
We also have a catalog of widgets developed by 3rd party developers. These widgets are styled according to our own brand’s theme. At first we were extracting out SASS files and classes from the huge platform repo. It’d take a lot of time to deploy and wasn’t exactly secure, therefore we decided to change that.
Themes
We started with extracting themes for each brand. For us, a theme is a set of variables related to visual appearance, varying from brand to brand. The theme has 2 levels of inheritance: from the default theme, we inherit brand, and from the brand, we inherit the language-specific theme.
We used YAML as it’s more human readable, has references and hierarchy. We put in place our own script for merging YAML files. After merging another script translates YAML to javascript code (only javascript object) or CSS/SASS variables.
Themes are used in the platform code, in UI kit and in 3rd party widgets. The components themselves don’t include a default theme, only behavior.
To apply themes we consider few different approaches.
CSS modules
CSS Modules is an extended CSS which specifies how to load CSS rules into Javascript. You can find more information here. With CSS modules you can apply theme in two ways: using style provider or using PostCSS plugin for variables. We liked the second option more. To use this plugin for theming you need to generate a file like this: https://gist.github.com/79b99c8c0849be9e72e1cf7327076b12
And then import this file at runtime. Because CSS modules need building, you also need to add a build script to your runtime. It parses CSS and resolves variable names.
CSS modules is a great technology we decided to use to handle our generic styles, but not for themes, because it still needs a build step, and to solve this we need to add an extra step to build code in runtime which will decrease performance (paring and resolving) for all browsers.
Pros
- Familiar syntax
Cons
- Build step
- Not a standard
Styled components
Styled components is a brand new way to develop components. In general, it is a way to define only presentational React components with embedded CSS. This is how it looks like:
https://gist.github.com/2591de4640ffbc156f51997ee07440e8
For theming you need to add a theme provider on top of your components tree and use the theme as props object theme
(as it shown in the example above). We believe it’s a very promising technology, but for now, it doesn’t satisfy all our needs.
Pros
- Style and component tight together
Cons
- Custom CSS parser
- Javascript Performance decrease
- No pre-build styles
- Weird theming syntax
CSS Variables
So we decided to go with CSS variables. This is a relatively new specification for CSS, but it works in most browsers already.
Our current solution looks like this: we have themes, build them into 2 files: 1 with just CSS variables https://gist.github.com/32d82fedd9ef56655856d1f95eb1899d
and the second file is a flat JS object used in polyfill: https://gist.github.com/ded7c3939a9f66078587cfc717711c21
and then you use it everywhere in this way:
https://gist.github.com/f8d602f9a1c0a04c9abf6f6c7534c22d
We created a small polyfill for just theming.
Pros
- Standard
- Native
- Good performance
- No build step
Cons
- Weird syntax
- For old browsers needs polyfilling
- Doesn’t work as media queries values
UI Kit
When we were done with themes, we started to build our UI kit. We use React as main UI library, but this approach is applicable to any framework.
First of all, we decided to make components as simple as possible, and React stateless components are really good way to do it. It is much easier to test stateless components because they are just pure-like functions. So for testing, we chose Jest, as it provides snapshot testing out of the box — you render your component and compare resulting markup with previous test run. Those snapshots are human readable and it is easy to find the difference in git diff.
Not all components are stateless or pure functions, though. For more complex components (like calendars or carousel) we use normal approach to unit testing. Also, some of our components are just wrappers for 3rd party components, like react-select.
Styleguide
The second important thing is documentation. Our living style guide showcase all components in UI kit base on react-styleguidist project. This project will parse all react components and will find all props, their type and description in comments. It will also get all .md
files next to the component and use them as interactive examples.
This styleguide is also being used by our designers to understand how our platform looks like.
Overview
Our simplified architecture for styling our platform looks like this:
- We add themes variables to the website
- In the website, themes are consumed by UI kit and all widgets
- Widget and website consume components from UI kit
- Styleguide uses UI kit for showcase and a theme to style.
Conclusion
We learned a lot by creating this project. We discovered that maybe YAML is not the best language for our needs (we tried to use its reference system but it doesn’t support interpolation). Before we switched to CSS variables, we had a lot of problems with building process of the UI kit library. We learned a lot about Webpack, React, checked countless different UI kits out there. We created a few small open source tools and we really improved our way of doing it.
Hero image credits: https://unsplash.com/@wesson