So you want to help us enable Skyscanner to create beautiful, coherent products at scale? That's awesome! ♥
This document describes how to go about it. If you have any questions, get in touch on Slack in #backpack or via [email protected].
- License
- Before you jump in
- Getting started
- Development tasks
- Adding a new component
- Design
- Tokens
- Sass mixins
- React component
- Documentation
- React Native
- Publishing packages (Backpack squad members only)
By contributing your code, you agree to license your contribution under the terms of the APLv2: <>
All files are released with the Apache 2.0 license.
If you are adding a new file it should have a header comment like this:
Backpack - Skyscanner's Design System
Copyright 2017 Skyscanner Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Is there something that you think should be in Backpack, but currently isn't? Before you dive in, please note that not everything that is a UI component belongs in Backpack.
Is this really going to be used by multiple products?
If you use it multiple times yourself, it might as well be a component, but maybe Backpack is the wrong place for it and it should instead stay in your own codebase. If in doubt, don’t hesitate to get in touch with us!
I’m sure this should be in Backpack!
Awesome! The rest of this file should give you a good picture of the process.
Backpack development takes places on Github. If you don't have a Github account, you can create one on github.com. You may want to get added to the Skyscanner team if you aren't already a member.
When you are ready to jump into code, use the following workflow to add new components or change any existing ones:
- Fork the repository
- Create a new branch
- Make your changes
- Commit and push your new branch
- Submit a pull request
- Notify someone in the Backpack Design System squad or drop a note in #backpack
Make sure to run at least npm 4, which ships with Node 7. You can get the latest Node version from this website, use a tool like nvm (
nvm use
will switch you to a supported version) or nave (nave auto
does the trick), or just upgrade npm usingnpm install -g npm@latest
.
To get started run:
npm install
The Backpack repository is a multi-package repository. This means that, instead of having one code repository for each npm module, we manage all of Backpack’s npm modules in a single code repository.
The tool we use for managing this multi-repo is Lerna.
Because we use Lerna to manage multiple packages in one repository, you'll also need to run
npm run bootstrap
anytime that you have changed the dependencies within a package. This is the equivalent to runningnpm install
inside each of the package folders.
You can find the individual modules / packages inside the packages/
folder.
ENABLE_CSS_MODULES=true npm start # Start development test harness complete with hot module reloading [HMR]
npm test # Lints .js & .scss files and runs unit tests
npm run build # Runs the build process for all packages
If you want to add a new component, we will need the following:
- Design (Sketch file)
- Associated tokens
- Sass mixin(s)
- React component
- Stories
- Tests
- Documentation (Including main
readme.md
)
Sketch is the preferred format for non-technical folks. We’d appreciate if you could provide an exact match of your component in Sketch format together with folders for each state e.g. disabled, expanded etc.
If you don’t have access to a designer, get in touch with us or post into #design-general.
Any visual CSS parameters of the component, such as color, margins, paddings etc. should not live as magic numbers in the component code, but as tokens in the bpk-tokens
package.
Tokens are defined in the src/base
directory (with the exception of product-specific tokens, which are in other subdirectories). Tokens come in two layers: In aliases.json
, all base tokens are defined with concrete values, such as colors, numbers and sizes. The other files then map those aliases to tokens for specific elements in our Atomic Design system.
You should probably not touch
aliases.json
, as our color palette or grid rarely changes.
Be aware that changing tokens will update all packages in the repository, as they all depend on bpk-tokens
. Changing an existing token is almost always worth a "major" release, whereas adding a new token is usually a "minor" release.
To build the tokens, run
npm run build:tokens
This will output different formats from the source JSON, for example Sass variables, a JavaScript module, Android and iOS resources.
### Sass mixins
Every atom-level component (buttons, form elements, icons, cf Atomic Design system) should not only come as a React component, but also as a set of Sass mixins for easy adoption.
All Sass mixins are defined in the bpk-mixins
package. The package also exposes the Sass variables from the bpk-tokens
package via the _bonds.scss
file.
If you add a new file of mixins, for example for a new atom, make sure you add the file to the imports in _index.scss
.
To lint the Sass, run
npm run lint:scss
Each React component has its own subdirectory packages/bpk-component-<component-name>
, where the npm module is stored. For it to be properly published, create a package.json
starting at version 0.0.0
and take inspiration from existing packages in terms of structure. We use CSS Modules along with BEM to prevent collisions and accidental overwrites in CSS.
We use Storybook to drive the development of Backpack's UI components. Start it using npm start
.
Create a stories.js
file and use it to list all the different possible states of your component. Check out Storybook's documentation for more details, and also check out the stories.js
files of existing components.
Make sure you import your new component's stories into Storybook by adding it to
.storybook/config.js
.
React components need to be properly unit tested. We use jest's snapshot testing, but depending on the complexity of your component, you may want to add additional tests.
Create a readme.md
file that shows how to install and use your component. It should also include a table of the component's props, PropTypes and their default values. Take inspiration from existing components.
Our documentation consists of two parts: Sassdoc, which is automatically generated from the bpk-mixin
sources, and the main documentation.
As mentioned, the Sassdoc are automatically generated from source and comments. If you want to double check, you can generate them using npm run sassdoc
and start a static server to browse the docs, but usually this is not necessary.
Take a look at some of the mixin source files to see how to annotate your Sass to generate proper Sassdoc.
The Backpack documentation is a standalone client-side app. Each package has its own “page”, which you can find and edit in the bpk-docs
package under src/pages
.
The “page” modules themselves contain introductory blurbs and examples for the respective component. They also import the component’s README, which you should have created according to the section further up in this document.
You can run the docs app locally using:
npm run docs
And loading http://localhost:8080/
If you need any help writing documentation, get in touch!
When adding documentation for a new component, add the new dependency in packages/bpk-docs/package.json
and run npm run bootstrap
to install it.
Backpack comes in two flavours: web and React Native. React Native (RN) components
live inside /native/packages
. The root of /native
contains things to assist
with running and testing RN components locally.
Before running RN components locally, you'll need a few things in place.
Available from the Mac App Store. Once installed, open it and accept the licence agreement. You're free to close it after that.
The following instructions heavily make use of Homebrew, which is available for macOS. Windows and Linux installation for these packages is also well-supported, but isn't currently documented here.
In future, we intend to automate more of this to reduce the number of steps required.
brew install watchman
brew cask install java
brew cask install android-studio
Open it once installed, and a setup wizard will guide you through installing lots of extra things like the Android SDK (choose Standard installation). You may be asked for your password during this. Once that's done, you're free to close Android Studio.
Add an environment variable pointing to the SDK location to your ~/.bash_profile
(or similarly used file):
echo "export ANDROID_HOME=\"$HOME/Library/Android/sdk\"" >> ~/.bash_profile && source ~/.bash_profile
Accept the SDK licences:
$ANDROID_HOME/tools/bin/sdkmanager --licenses
Download an Android system image. Note that you may get a warning about a .cfg
file not being present.
You're safe to ignore this.
$ANDROID_HOME/tools/bin/sdkmanager "system-images;android-24;google_apis;x86"
Create an Android Virtual Device (AVD):
$ANDROID_HOME/tools/bin/avdmanager create avd --name "bpk-avd" --package "system-images;android-24;google_apis;x86" --device "Nexus 5X"
You should now have a functioning Android development environment, including a
virtual device to run things on. You can run the AVD manually with $ANDROID_HOME/tools/emulator -avd bpk-avd -dpi-device 420 -skin 1080x1920
,
but npm run android
will handle this for you, so it's not required.
Just like with the web, Storybook is used to test RN components. Start it with npm run native
.
Once Storybook is running, use npm run ios
or npm run android
to run storybook
on a device.
- Update the changelog with every package that has changed, separating out breaking changes (major), additions (minor) and fixes (patch) changes (you should see examples of this in previous entries). Make sure to add
them at the top under a heading of “UNRELEASED"
- Some useful commands for determining "what's changed?":
npm run lerna updated
npm run lerna diff <package-name>
- Some useful commands for determining "what's changed?":
- Make sure you are an owner of the npm packages (speak to a member of the Backpack squad)
- Do not run
npm publish
. Instead, runnpm run publish
(this will runlerna publish
). - You’ll be asked to specify a new version for every package that has changed. Options are patch, minor or major. These should directly align to the entries you put in the changelog in step 1.
- You’ll be asked at the end to confirm. Note you can still exit without making these changes.
- Update the changelog with the package versions and update the title with today’s date and a brief summary of what has changed.
- Commit and push to master.
- Update the #backpack Slack channel and the BackpackNeedToKnow mailing list if necessary.