Skip to content

Set up

1. Bash

As a prerequisite, you need a decent bash system. For example: Git Bash, Linux Bash, Ubuntu Bash through Windows WSL.

2. Project setup

Follow the Project Setup documentation.

3. Clone the repository

Go here: https://dev.azure.com/if-it/If%20Design%20Hub/\_git/if-design-system and press "Clone". We recommend that you choose the SSH way.

If you have an SSH key, but not added it, press "Manage SSH keys" and add the key. This is the contents of your `.ssh/id_rsa.pub`-file.
If you haven't set up SSH keys already, go here: https://docs.microsoft.com/en-us/azure/devops/repos/git/use-ssh-keys-to-authenticate?view=azure-devops and follow the instructions on how to create your SSH keys.
Press "Clone" and copy the SSH repo url to clone

Go to your prefered folder where your code or projects are, preferably not a network station, and git clone:

$ mkdir if-design-system
$ cd if-design-system
$ git clone if-it@vs-ssh.visualstudio.com:v3/if-it/If%20Design%20Hub/guybrush .
4. Install dependencies
We recommend that you install node@>=8.14.0 and npm@>=6. You can check this with `node -v` and `npm -v`.

First we install the global npm packages required:

$ npm i -g gulp-cli@latest lerna

Then we install the root package dependencies:

$ npm i

Then we bootstrap, installing all the dependencies for the packages:

$ lerna bootstrap

As a general workflow, discard any changes to the package-lock.json-files at this stage:

$ git checkout -- packages package-lock.json

This to make sure that when you want to create a new component/package, that you have a clean slate.

Congratulations, you have now set up a developing environment for the Design System!

Edit this section

Dev server

You can start your own local component development server with this command at root:

$ npm run start:dev -- <component-folder-name>

For example:

$ npm run start:dev -- hero

This will:

  • Start a local webserver for the hero component
  • Watch for changes in the src, docs and demo-folder
  • Build the bundle
  • Build the styleguide
  • Live reload the dev index.html file
Edit this section

Creating a component

1. Checkout master

$ git checkout master

2. Install dependencies

$ npm i

Then we bootstrap, installing all the dependencies for the packages:

$ lerna bootstrap

As a general workflow, discard any changes to the package-lock.json-files at this stage:

$ git checkout -- packages package-lock.json

This to make sure that when you want to create a new component/package, that you have a clean slate.

3. Dev branch

Checkout a developing branch for the fix or new component, and push it.

$ git checkout -b <name of branch>
$ git push -u origin <name of branch>

4. Copy

Copy the required files listed below as a scaffold.

Copy the files from packages/button, copy ONLY the files listed below:

|-dev
| |-*.html
|-demo
| |-*.html
|-docs
| |-button.md
|-CHANGELOG.md
|-gulpfile.js
|-src
| |-button.styl
|-test
| |-diff.js
|-package.json
|-README.md
|-.stylintrc

5. Rename

Rename the files to fit the new component name

$ mv docs/button.md docs/<new-component-name>.md
$ mv demo/button.html demo/<new-component-name>.html
$ mv src/button.styl src/<new-component-name>.styl
$ mv src/button.scss src/<new-component-name>.scss
$ mv src/button.less src/<new-component-name>.less

6. Reset

Reset and update names in the files below:

  • Remove all content in CHANGELOG.md
  • Rename references of button to <new-component-name> in package.json
  • Rename references of button to <new-component-name> in demo/<new-component-name>.html
  • Rename references of button to <new-component-name> in dev/index.html
  • Rename references of button to <new-component-name> in test/diff.js
  • Remove documentation and rename references of button to <new-component-name> in docs/<new-component-name>.md
  • Remove all styling in src/<new-component-name>.styl
  • Rename references of button to in the commented section of src/<new-component-name>.styl
`docs/.md` should look something like this
`src/.styl` should look something like this:

package.json-should look something like this:

{
  "name": "@if-design-system/<new-component-name>",
  "version": "5.0.2",
  "description": "",
  "main": "./dist/<new-component-name>.css",
  "scripts": {
    "build": "npm test && rimraf ./dist ./*.zip && gulp -L",
    "test": "gulp pretest -L && mocha test/diff.js"
  },
  "author": {
    "name": "If P&C Insurance"
  },
  "license": "SEE LICENSE IN LICENSE",
  "devDependencies": {
    "colors": "^1.4.0",
    "cssnano": "^4.1.10",
    "diff": "^4.0.2",
    "eslint": "^4.19.1",
    "eslint-config-prettier": "^2.9.0",
    "gulp": "^4.0.0",
    "mocha": "^7.0.1",
    "prettier": "^1.13.7",
    "rimraf": "^2.6.2",
    "stylint-stylish": "^2.0.0"
  },
  "dependencies": {
    "@if-design-system/breakpoint": "5.0.2",
    "@if-design-system/color": "5.0.2",
    "@if-design-system/core": "5.0.2",
    "@if-design-system/typography": "5.0.2",
    "@if-design-system/util": "5.0.2"
  }
}

7. Add to build

Add the new component to the build.

Open config/module-dirs.js and add your component:

module.exports = [
  './src/',
  './node_modules/',
  './node_modules/@if-design-system/core/src/',
  './node_modules/@if-design-system/color/src/',
  './node_modules/@if-design-system/breakpoint/src/',
  './node_modules/@if-design-system/typography/src/',
  './node_modules/@if-design-system/grid/src/',
  './node_modules/@if-design-system/icons/src/',
  './node_modules/@if-design-system/util/src/',
  './node_modules/@if-design-system/input-fields/src/',
  './node_modules/@if-design-system/logo/src/',
  './node_modules/@if-design-system/consent-banner/src/',
  './node_modules/@if-design-system/button/src/',
  './node_modules/@if-design-system/<new-component-name>/src/'
];

Then add your component to packages/bundle/src/bundle.styl:

@require '@if-design-system/core/src/core.styl'
@require '@if-design-system/color/src/color.styl'
@require '@if-design-system/breakpoint/src/breakpoint.styl'
@require '@if-design-system/typography/src/typography.styl'
@require '@if-design-system/grid/src/grid.styl'
@require '@if-design-system/util/src/util.styl'
@require '@if-design-system/icons/src/icons.styl'
@require '@if-design-system/logo/src/logo.styl'
@require '@if-design-system/<new-component-name>/src/<new-component-name>.styl'

Then add your component to packages/bundle/src/bundle.less:

@import '@if-design-system/core/src/core.less';
@import '@if-design-system/color/src/color.less';
@import '@if-design-system/breakpoint/src/breakpoint.less';
@import '@if-design-system/typography/src/typography.less';
@import '@if-design-system/grid/src/grid.less';
@import '@if-design-system/util/src/util.less';
@import '@if-design-system/icons/src/icons.less';
@import '@if-design-system/logo/src/logo.less';
@import '@if-design-system/<new-component-name>/src/<new-component-name>.less';

Then add your component to packages/bundle/src/bundle.scss:

@import '@if-design-system/core/src/core.scss';
@import '@if-design-system/color/src/color.scss';
@import '@if-design-system/breakpoint/src/breakpoint.scss';
@import '@if-design-system/typography/src/typography.scss';
@import '@if-design-system/grid/src/grid.scss';
@import '@if-design-system/util/src/util.scss';
@import '@if-design-system/icons/src/icons.scss';
@import '@if-design-system/logo/src/logo.scss';
@import '@if-design-system/<new-component-name>/src/<new-component-name>.scss';

Then make sure the bundle - package.json file has the new component as a dependency:

"dependencies": {
  "@if-design-system/breakpoint": "5.0.2",
  "@if-design-system/color": "5.0.2",
  "@if-design-system/core": "5.0.2",
  "@if-design-system/grid": "5.0.2",
  "@if-design-system/logo": "5.0.2",
  "@if-design-system/icons": "5.0.2",
  "@if-design-system/typography": "5.0.2",
  "@if-design-system/util": "5.0.2",
  "@if-design-system/<new-component-name>": "5.0.2",
  "what-input": "^5.1.0"
}

And then in the root project folder, run:

$ lerna bootstrap

To symlink and install dependencies.

8. Add to documentation

Add the new component to the documentation generation.

Open up gulpfile.babel.js and add your component:

gulp.src([
  './packages/core/dist/core.css',
  './packages/color/dist/color.css',
  './packages/breakpoint/dist/breakpoint.css',
  './packages/typography/dist/typography.css',
  './packages/grid/dist/grid.css',
  './packages/util/dist/util.css',
  './packages/icons/dist/icons.css',
  './packages/logo/dist/logo.css',
  './packages/consent-banner/dist/consent-banner.css',
  './packages/button/dist/button.css',
  './packages/input-fields/dist/input-fields.css',
  './packages/<new-component-name>/dist/<new-component-name>.css'
]);

And remember to add the demo:

const copyDemoFiles = () =>
  gulp
    .src([
      './packages/typography/demo/*.html',
      './packages/hero/demo/*.html',
      './packages/grid/demo/*.html',
      './packages/notification/demo/*.html',
      './packages/bundle/demo/*.html',
      './packages/expandable/demo/*.html',
      './packages/breadcrumbs/demo/*.html',
      './packages/core/demo/*.html',
      './packages/modal/demo/*.html',
      './packages/footer/demo/*.html',
      './packages/datepicker/demo/*.html',
      './packages/navigational-card/demo/*.html',
      './packages/shortcuts/demo/*.html',
      './packages/product-matrix-table/demo/*.html',
      './packages/quick-facts/demo/*.html',
      './packages/<new-component-name>/demo/*.html'
    ])
    .pipe(gulp.dest('./public/demos'));

9. Code

And now you are ready to start developing a new component!

Add your styling to the component and make a pull request!

10. Result

To see your component in the documentation, run:

$ npm run build

This will build all packages and the documentation. This might take a lot of time, you might shorten the time by just doing:

$ npm run bundle
$ gulp

If you only have updated the documentation files, or the styling for the documentation, you can just run:

$ gulp

And to start the dev server for the documentation, so that you can view the changes, run:

$ npm start

This server can be run in separate window while you build and code!

Dev server

You can start your own local component development server with this command at root:

$ npm run start:dev -- <component-folder-name>

For example:

$ npm run start:dev -- hero

This will:

  • Start a local webserver for the hero component
  • Watch for changes in the src, docs and demo-folder
  • Build the bundle
  • Build the styleguide
  • Live reload the dev index.html file

11. Script

If you feel that the guide was a bit long and tedious, you can use a script to set up the scaffolding for a new component for you:

$ npm run create:component New-component-name
$ lerna bootstrap

This script will copy and rename all the files and references for you, set up scaffolding documentation files and update references to bundle. It will also build the files and documentation one time!

Edit this section

Add icon

NOTE! Any new icon needs to be approved before adding it to the Design System. Please contact the Design System team :)

Aquire the SVG icon to add

We will use this as an example:

Prune the markup

As you can see, there is quite a lot of markup for this icon:

<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
  <defs>
    <style>
      .cls-1,
      .cls-2,
      .cls-3 {
        fill: none;
        stroke: #111;
        stroke-width: 1.5px;
      }
      .cls-1 {
        stroke-miterlimit: 10;
      }
      .cls-2,
      .cls-3 {
        stroke-miterlimit: 10;
      }
      .cls-3 {
        stroke-linecap: square;
      }
      .cls-4 {
        fill: #111;
      }
    </style>
  </defs>
  <polyline class="cls-1" points="28.4 15.33 26.38 13.17 22.19 17 19.98 13.94 17.86 18.28" />
  <path
    id="Path_870"
    data-name="Path 870"
    class="cls-2"
    d="M32.51,20.07,31,11.53A3,3,0,0,0,28,9.07H13a3,3,0,0,0-2.95,2.46L8.51,20.07"
  />
  <path id="Path_871" data-name="Path 871" class="cls-3" d="M13.51,30.06v5h-6v-5" />
  <path id="Path_872" data-name="Path 872" class="cls-3" d="M33.51,30.06v5h-6v-5" />
  <path
    id="Path_874"
    data-name="Path 874"
    class="cls-3"
    d="M35.51,30.06h-30V24.31a3,3,0,0,1,.87-2.12l2.13-2.12h24l2.11,2.12a3,3,0,0,1,.88,2.12Z"
  />
  <path
    id="Path_875"
    data-name="Path 875"
    class="cls-4"
    d="M12.43,25.56A1.43,1.43,0,1,1,11,24.13a1.49,1.49,0,0,1,.72.19A1.44,1.44,0,0,1,12.43,25.56Z"
  />
  <path
    id="Path_876"
    data-name="Path 876"
    class="cls-4"
    d="M31.43,25.56A1.43,1.43,0,1,1,30,24.13a1.48,1.48,0,0,1,.71.19A1.44,1.44,0,0,1,31.43,25.56Z"
  />
</svg>

Open your editor and copy the markup. Then use the "Paste Markup" feature in the SVGOMG app.

Use the "Paste markup" feature
Result

Then copy the SVG as text (bottom right corner).

Paste into your editor and format/beautify it (easier to work with), and it should look like this:

<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
  <defs>
    <style>
      .cls-3 {
        fill: none;
        stroke: #111;
        stroke-width: 1.5px;
        stroke-miterlimit: 10;
        stroke-linecap: square;
      }
      .cls-4 {
        fill: #111;
      }
    </style>
  </defs>
  <path
    stroke-miterlimit="10"
    fill="none"
    stroke="#111"
    stroke-width="1.5"
    d="M28.4 15.33l-2.02-2.16L22.19 17l-2.21-3.06-2.12 4.34"
  />
  <path
    id="Path_870"
    data-name="Path 870"
    class="cls-3"
    d="M32.51 20.07L31 11.53a3 3 0 00-3-2.46H13a3 3 0 00-2.95 2.46l-1.54 8.54M13.51 30.06v5h-6v-5M33.51 30.06v5h-6v-5" />
  <path
    id="Path_874"
    data-name="Path 874"
    class="cls-3"
    d="M35.51 30.06h-30v-5.75a3 3 0 01.87-2.12l2.13-2.12h24l2.11 2.12a3 3 0 01.88 2.12z"
  />
  <path
    id="Path_875"
    data-name="Path 875"
    class="cls-4"
    d="M12.43 25.56A1.43 1.43 0 1111 24.13a1.49 1.49 0 01.72.19 1.44 1.44 0 01.71 1.24zM31.43 25.56A1.43 1.43 0 1130 24.13a1.48 1.48 0 01.71.19 1.44 1.44 0 01.72 1.24z"
  />
</svg>

It doesn't look like much has changed, but we will make more changes.

Remove all of these:

  • style definition
  • defs
  • ALL id and data-name - attributes

But make sure that the relevant styling is kept directly as an attribute for the relevant paths! So:

All of the paths for .cls-3 will receive these attributes:

<path  fill="none" stroke="#111" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="square" />

And .cls-4 will receive this attribute

<path  fill="#111" />

It should look like this now:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
  <path
    stroke-miterlimit="10"
    fill="none"
    stroke="#111"
    stroke-width="1.5"
    d="M28.4 15.33l-2.02-2.16L22.19 17l-2.21-3.06-2.12 4.34"
  />
  <path
    fill="none"
    stroke="#111"
    stroke-width="1.5"
    stroke-miterlimit="10"
    stroke-linecap="square"
    d="M32.51 20.07L31 11.53a3 3 0 00-3-2.46H13a3 3 0 00-2.95 2.46l-1.54 8.54M13.51 30.06v5h-6v-5M33.51 30.06v5h-6v-5"
  />
  <path
    fill="none"
    stroke="#111"
    stroke-width="1.5"
    stroke-miterlimit="10"
    stroke-linecap="square"
    d="M35.51 30.06h-30v-5.75a3 3 0 01.87-2.12l2.13-2.12h24l2.11 2.12a3 3 0 01.88 2.12z"
  />
  <path
    fill="#111"
    d="M12.43 25.56A1.43 1.43 0 1111 24.13a1.49 1.49 0 01.72.19 1.44 1.44 0 01.71 1.24zM31.43 25.56A1.43 1.43 0 1130 24.13a1.48 1.48 0 01.71.19 1.44 1.44 0 01.72 1.24z"
  />
</svg>

But, we can do more, since there is a lot of similar attributes, we can group the paths in a <g>-tag (group), and only apply the fill-attribute where it's needed:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
  <g stroke-miterlimit="10" fill="none" stroke="#111" stroke-width="1.5" stroke-linecap="square">
    <path d="M28.4 15.33l-2.02-2.16L22.19 17l-2.21-3.06-2.12 4.34" />
    <path
      d="M32.51 20.07L31 11.53a3 3 0 00-3-2.46H13a3 3 0 00-2.95 2.46l-1.54 8.54M13.51 30.06v5h-6v-5M33.51 30.06v5h-6v-5"
    />
    <path d="M35.51 30.06h-30v-5.75a3 3 0 01.87-2.12l2.13-2.12h24l2.11 2.12a3 3 0 01.88 2.12z" />
    <path
      fill="#111"
      d="M12.43 25.56A1.43 1.43 0 1111 24.13a1.49 1.49 0 01.72.19 1.44 1.44 0 01.71 1.24zM31.43 25.56A1.43 1.43 0 1130 24.13a1.48 1.48 0 01.71.19 1.44 1.44 0 01.72 1.24z"
    />
  </g>
</svg>

Then replace the color #111 with #331e11:

  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
-    <g stroke-miterlimit="10" fill="none" stroke="#111" stroke-width="1.5" stroke-linecap="square">
+    <g stroke-miterlimit="10" fill="none" stroke="#331e11" stroke-width="1.5" stroke-linecap="square">
      <path d="M28.4 15.33l-2.02-2.16L22.19 17l-2.21-3.06-2.12 4.34" />
      <path
        d="M32.51 20.07L31 11.53a3 3 0 00-3-2.46H13a3 3 0 00-2.95 2.46l-1.54 8.54M13.51 30.06v5h-6v-5M33.51 30.06v5h-6v-5"
      />
      <path d="M35.51 30.06h-30v-5.75a3 3 0 01.87-2.12l2.13-2.12h24l2.11 2.12a3 3 0 01.88 2.12z" />
      <path
-        fill="#111"
+        fill="#331e11"
        d="M12.43 25.56A1.43 1.43 0 1111 24.13a1.49 1.49 0 01.72.19 1.44 1.44 0 01.71 1.24zM31.43 25.56A1.43 1.43 0 1130 24.13a1.48 1.48 0 01.71.19 1.44 1.44 0 01.72 1.24z"
      />
    </g>
  </svg>

The markup should be like this (but minified):

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 40 40">
  <g fill="none" stroke="#331e11" stroke-linecap="square" stroke-miterlimit="10" stroke-width="1.5">
    <path d="M28.4 15.33l-2.02-2.16L22.19 17l-2.21-3.06-2.12 4.34" />
    <path d="M32.51 20.07L31 11.53a3 3 0 00-3-2.46H13a3 3 0 00-2.95 2.46l-1.54 8.54m5 9.99v5h-6v-5m26 0v5h-6v-5" />
    <path d="M35.51 30.06h-30v-5.75a3 3 0 01.87-2.12l2.13-2.12h24l2.11 2.12a3 3 0 01.88 2.12z" />
    <path
      fill="#331e11"
      d="M12.43 25.56A1.43 1.43 0 1111 24.13a1.49 1.49 0 01.72.19 1.44 1.44 0 01.71 1.24zm19 0A1.43 1.43 0 1130 24.13a1.48 1.48 0 01.71.19 1.44 1.44 0 01.72 1.24z"
    />
  </g>
</svg>

Now, save the file under the relevant icon category folder, for example packages/icons/coverages/windshield-damage.svg.

Build icons package

Then you have to build the icon package, to make sure to generate the correct preprocessor files, mixins etc:

$ cd packages/icons
$ npm run build:prod

git status should looke something like this:

$ git status .

git status

Then test the package to check if we have the preprocessor files in order:

$ npm test

npm test

Commit and create a PR

# Root project folder
$ cd ...
$ git add .
$ npm run commit
$ git push -u origin <branch-name>

Resources

Edit this section

Documenting

To generate and create documentation, we use LivingCSS. This guide will not cover exactly how that works, but how we create our documentation.

Frontmatter

To make sure the markdown files are read and sourced correctly by Gatsby, you need to add frontmatter in the top of your markdown files:

---
title: 'Typography'
order: 1
category: 'components'

customPath: '/components/typography'
---
Prop Value Type Required Notes
title The title of the page String
order The order that it should have on a page Number
subCategoryOrder The order to sort subcategories with Number no
componentName The name of the component, lowercase String no For components only
category The category of the page, lowercase String
subCategory The subcategory of the page, lowercase String no
customPath The desired path, used to group files and for navigation, lowercase String
topLevel To indicate if this page should be at the top level Bool no
globalNav Should this page/link be a part of the global navigation? Bool

Basics

Documentation is key to understand and to use the design system. We aim for clarity and consistency. After all, the documentation is read by humans. Developers, UX-designers, graphical designers and others.

The documentation should be guiding, not too direct. It should allow for further development of the design. However, the documentation should be so concise that there are no misconceptions.

Decorators

We use different type of decorators for our examples:

  • .sg.figure.types - Mainly for types, but can also be used for stances
  • .sg.stances - To visualize do's and do not's
Types
  1. Filled, primary button
  2. Filled, primary CTA button
  3. Outlined, secondary button
  4. Outlined, text button
  5. Filled, info button
<figure class="sg figure types">
  <ol class="sg types list">
    <li class="sg types list item">
      <div class="sg types type">
        <div class="sg example if"><button class="if button primary">Primary button</button></div>
      </div>
    </li>
    <li class="sg types list item">
      <div class="sg types type">
        <div class="sg example if"><button class="if button primary large">CTA button</button></div>
      </div>
    </li>
    <li class="sg types list item">
      <div class="sg types type">
        <div class="sg example if"><button class="if button secondary">Secondary button</button></div>
      </div>
    </li>
    <li class="sg types list item">
      <div class="sg types type">
        <div class="sg example if"><button class="if button text">Tertiary button</button></div>
      </div>
    </li>
    <li class="sg types list item">
      <div class="sg types type">
        <div class="sg example if"><button class="if button info">Info button</button></div>
      </div>
    </li>
  </ol>
  <figcaption class="sg figure caption">
    <ol class="sg figure caption list">
      <li class="sg figure caption list item">Filled, primary button</li>
      <li class="sg figure caption list item">Filled, primary CTA button</li>
      <li class="sg figure caption list item">Outlined, secondary button</li>
      <li class="sg figure caption list item">Outlined, text button</li>
      <li class="sg figure caption list item">Filled, info button</li>
    </ol>
  </figcaption>
</figure>
Stances
Do not use two or more primary buttons together
Only use one primary button per view
<div class="sg stances">
  <figure style="height: 20rem;" class="sg stance bad">
    <div>
      <div class="sg example if">
        <button type="button" class="if button primary">No</button>
        <button type="button" class="if button primary">Yes</button>
      </div>
    </div>
    <figcaption>Do not use two or more primary buttons together</figcaption>
  </figure>
  <figure style="height: 20rem;" class="sg stance good">
    <div>
      <div class="sg example if">
        <button type="button" class="if button secondary">No</button>
        <button type="button" class="if button primary">Yes</button>
      </div>
    </div>
    <figcaption>Only use one primary button per view</figcaption>
  </figure>
</div>

Helper classes

Badges

  1. .sg.tryme - Used to indicate that user can interact with the examples
  2. .sg.spec-missing - Used to indicate that we do not have the specification for this component or type or state
<figure class="sg figure types">
  <ol class="sg types list">
    <li class="sg types list item tryme">
      <div class="sg types type">
        <div class="sg example if"><button class="if button">Button</button></div>
      </div>
    </li>
    <li class="sg types list item spec-missing">
      <div class="sg types type">
        <div class="sg example if"><button class="if button">Button</button></div>
      </div>
    </li>
  </ol>
  <figcaption class="sg figure caption">
    <ol class="sg figure caption list">
      <li class="sg figure caption list item">
        <code>.sg.tryme</code> - Used to indicate that user can interact with the examples
      </li>
      <li class="sg figure caption list item">
        <code>.sg.spec-missing</code> - Used to indicate that we do not have the specification for this component or
        type or state
      </li>
    </ol>
  </figcaption>
</figure>

Examples

Examples are crucial to the documentation. It gives us the possibility to communicate how a component should look like, how it should behave and what it can and cannot do.

To create an example with styling only and not the implementation code as mentioned earlier, add this to a documentation file, for example docs/button.md:

<div class="sg example if">
  <button type="button" class="if button">A button</button>
</div>

Which will result in this:

Responsive

If you want, you can add responsive examples, how your component would look like in certain viewports (devices). We use @phun-ky/responsive-documentation-examples for this.

Write a section like this in a documentation file, for example docs/responsive.md:

First, create a template holder in docs/responsive.md. This will contain the example you want to display:

# Responsive examples

<div data-responsive data-responsive-id="button" class="sg hidden">
  <button class="if button">A button</button>
</div>

Then add the required iframe for this to work:

<iframe id="button-responsive-mobile" class="sg responsive"></iframe>

Or

<iframe id="button-responsive-tablet-portrait" class="sg responsive"></iframe>

Or

<iframe id="button-responsive-tablet-landscape" class="sg responsive"></iframe>

Or

<iframe id="button-responsive-desktop" class="sg responsive"></iframe>

And you're done! The documentation site includes a script that will automatically generate the responsive example in the iframe.

The file docs/responsive.md should look somewhat similar to this:

# Responsive examples

<div data-responsive data-responsive-id="button" class="sg hidden">
  <button class="if button">A button</button>
</div>

<iframe id="button-responsive-tablet-landscape" class="sg responsive"></iframe>

If you want, you can use a decorator (styling) for the responsive example to appear like a device, here is an example using ResponsiveDevices.css:

<div class="sg device-iphone device-portrait">
  <div class="iphone white portrait">
    <div class="caseBorder"></div>
    <div class="case"></div>
    <div class="reflection"></div>
    <div class="screen"></div>
    <div class="camera"></div>
    <div class="speaker"></div>
    <div class="homeButtonBorder"></div>
    <div class="homeButton"></div>
    <div class="content"><iframe id="footer-responsive-mobile" class="sg responsive"></iframe></div>
  </div>
</div>

Types

Use the type decorator to indicate and communicate that there are different types of a component.

States

Use the state decorator to indicate and communicate that there are different states of a component.

Annotation

To clarify which element inside a component is what, and to pin point important parts of a component, we use @phun-ky/speccer.

Write a section like this in a documentation file, for example: docs/anatomy.md:

# Anatomy

<figure class="sg figure types">
  <ol class="sg types list">
    <li class="sg types list item" data-anatomy-section>
      <div class="sg types type">
        <div class="sg example if">
        <button class="if button">Secondary button</button>
      </div>
      </div>
    </li>
    <li class="sg types list item" data-anatomy-section>
      <div class="sg types type">
        <div class="sg example if">
        <button class="if button"><span class="if icon ui edit blue"></span>Secondary button</button>
      </div>
      </div>
    </li>
  </ol>
  <figcaption class="sg figure caption">
    <ol class="sg figure caption list">
      <li class="sg figure caption list item">
        Secondary button
        <ol>
          <li>Text label, Box is inverse filled and with outline</li>
        </ol>
      </li>
      <li class="sg figure caption list item">
        Secondary button
        <ol>
          <li>Text label, Box is inverse filled and with outline</li>
          <li>With icon</li>
        </ol>
      </li>
    </ol>
  </figcaption>
</figure>

And add data-anatomy attributes to the button tags, like so:

-<button class="if button">Secondary button</button>
+<button data-anatomy="outline top" class="if button">Secondary button</button>
-<button class="if button">
-  <span class="if icon ui edit blue"></span>
-  Secondary button
-</button>
+<button data-anatomy="outline top" class="if button">
+  <span data-anatomy="outline bottom" class="if icon ui edit blue"></span>
+  Secondary button
+</button>

The result will look something like this:

  1. Secondary button
    1. Text label, Box is inverse filled and with outline
  2. Secondary button
    1. Text label, Box is inverse filled and with outline
    2. With icon

For full documentation on how to use @phun-ky/speccer, see the README.md.

Specifications

Sometimes it is needed to be very clear on what margins and paddings a component have. It is not easy to communicate what this is visually, so we use @phun-ky/speccer for this.

Write a section like this in a documentation file, for example: docs/specs.md:

# Specs

<div class="sg mesh embed" style="grid-template-columns: repeat(auto-fill, minmax(100%, 1fr));">
  <div class="sg box alpha figure specs">
    <strong class="if">Button</strong>
    <div class="sg figure sample">
      <div class="sg example if">
        <button type="button" class="if button primary">Button</button>
        <button style="margin-left: 1rem;" type="button" class="if button primary">Button</button>
        <button style="margin-left: 1rem;" type="button" class="if button primary">Button</button>
      </div>
    </div>
  </div>
</div>

Then update it with the tags you want to use to display specs. In this example, we want to show margin and padding for the first button, then the width of the second, and then the height with the third. The tags used, in order are: data-speccer, data-speccer-measure="width bottom" and data-speccer-measure="height right":

# Specs

<div class="sg mesh embed" style="grid-template-columns: repeat(auto-fill, minmax(100%, 1fr));">
  <div class="sg box alpha figure specs">
    <strong class="if">Button</strong>
    <div class="sg figure sample">
      <div class="sg example if">
        <button type="button" class="if button primary" data-speccer>Button</button>
        <button style="margin-left: 1rem;" type="button" class="if button primary" data-speccer-measure="width bottom">Button</button>
        <button style="margin-left: 1rem;" type="button" class="if button primary" data-speccer-measure="height right">Button</button>
      </div>
    </div>
  </div>
</div>

Result

The result should be something like this:

Button

For full documentation on how to use @phun-ky/speccer, see the README.md.

Implementation

Always document how the user can implement this component. Write a section like this in a documentation file, for example docs/implementation.md:

#### Implementation

```html
<button class="if button [primary|secondary|info]">A button</button>
```

The above code will look something like this:

ImplementationEdit this section

<button class="if button [primary|secondary|info]">A button</button>
Edit this section

Styling a component

When you have set up the folders etc for a new component, you are now ready to style it! This section will not cover how to use Stylus or CSS, but will have some key pointers on how to structure your file.

Basics

For this guide, we assume that you are making a card component, so the main file is card.styl

The main Stylus file for your component, card.styl should look like this:

@require 'core.styl'
/**
 * @doc ../docs/card.md
 * @package {package} card - Card
 * @section
 * @sectionof Components
 */

.if.card{}

Now, does your component have states? Are there different types of the component?

Code style

If you have a component, for examples, a card, the main class name should look like this:

.if.card{}

Types should look like this:

.if.card.type1{}

.if.card.type2{}

Got several states for the component? Like disabled, active, hover etc?

.if.card:hover,
.if.card.is-hovered{}

.if.card:active,
.if.card.is-active{}

.if.card.is-flagged{}

The first to rule definitions has helper classes for :hover and active. This is done so we can add those class names for the component in the documentation, when documenting states.

Using variables

Variables

There are some variables you might want to use from the existing packages, rather than creating your own variables. Here is an example of using a secondary color for our card component.

For every component, `core.styl` is always required, and it contains the required core styling. With this, you will always have access to these packages: `color-variables`, `typography` and `util`.
@require 'core.styl'
/**
 * @doc ../docs/card.md
 * @package {package} card - Card
 * @section
 * @sectionof Components
 */

.if.card{
  background-color $color-background-lighter-beige
}

Extending classes

You can extend classes for reuse, for example, fonts:

@require 'core.styl'
/**
 * @doc ../docs/card.md
 * @package {package} card - Card
 * @section
 * @sectionof Components
 */

.if.card{
  background-color $color-background-lighter-beige
  @extend .if.font.family.sans
}

This will add:

  font-family $font-family sans
  font-weight normal
  font-style normal

To your card class definition.

Breakpoints

If you want to use breakpoints, you can use breakpoint.styl like this:

Add @if-design-system/breakpoint to your card component package.json as a dependency:

{
  "dependencies": {
    "@if-design-system/breakpoint": "5.0.2"
  }
}

Then run:

$ lerna bootstrap

To link and install dependencies. Then update your card.styl like so:

@require 'core.styl'
@require 'breakpoint.styl'
/**
 * @doc ../docs/card.md
 * @package {package} card - Card
 * @section
 * @sectionof Components
 */

.if.card{
  background-color $color-background-lighter-beige
  margin 0
  @extend .if.font.family.sans
  +IDS_BREAKPOINT_MQ_Medium_Min()
    margin 2rem
}

This will make the card component have 0 margin up until the medium breakpoint that is 960px.

Edit this section

Troubleshooting

I have merged the PR but the documentation is not updated

There could be several things due to this, but here are a few pointers.

Build error

Check the build status for your build here: https://dev.azure.com/if-it/If%20Design%20Hub/_build?definitionId=852.

Press the build in error
Click the task that has an error
Identify the error and react to it.

The error displayed here is what happens if you forget to include the package-lock.json in your component. A similar error is because your package-lock.json is out of sync. To fix that, submit a new PR with a fresh lerna bootstrap.

Release error

Click release status here: https://dev.azure.com/if-it/If%20Design%20Hub/_release?_a=releases&view=mine&definitionId=4.

Press the release in error
Click the task that has an error
Identify the error and react to it.

The error displayed here is because of an expired principle secret. Your dev ops team can resolve this.

I have merge the PR but the packages are not published

First, it will take between 5-20 minutes for a build to complete, so be patient. You can check if your package is published by checking the latest version of the bundle (when there are changes, bundle is always updated): https://dev.azure.com/if-it/If%20Design%20Hub/_packaging?_a=package&feed=if-design-system&protocolType=Npm&package=%40if-design-system%2Fbundle. You can also search for the particular package itself to see if that package also have the correct version.

Build error

Check the status of your build here: https://dev.azure.com/if-it/If%20Design%20Hub/_build?definitionId=851.

Press the build in error
Click the task that has an error
Identify the error and react to it.

The error displayed here is what happens if you forget to include the package-lock.json in your component. A similar error is because your package-lock.json is out of sync. To fix that, submit a new PR with a fresh lerna bootstrap.

Publish error

Sometimes, the publish package job builds perfectly, but no new package is added. This could be that either the build found no new changes to publish, or that there is something wrong with the network or other disruptive error.

That means you most likely, have to trigger a manual publish in your CLI.

Publish manually
  1. Open bash and cd into if-design-system
$ cd if-design-system
  1. Make sure that you are on the master-branch, and pull latest changes (the changes that did not get a published package)
$ git checkout master
$ git pull
  1. Identify the latest version in lerna.json, for example: 5.0.1
$ cat lerna.json | grep version
  1. Manually version the packages, you need to bump patch for this. Answer "yes" at the prompt
$ lerna version 5.0.2-alpha.0 --force-publish
  1. Then publish the versions, answer "yes" at the prompt
$ lerna publish from-package

If this succeeds, you will now have a published package at https://dev.azure.com/if-it/If%20Design%20Hub/_packaging?_a=feed&feed=if-design-system.

Failed to require .styl

Make sure that config/module-dirs.js is updated with your component name, and that the complaining component's package.json is updated with the dependency and that you have run lerna bootstrap.

I have created a PR, but the required build fails

Check your build status here: https://dev.azure.com/if-it/If%20Design%20Hub/_build?definitionId=853.

In most cases, you can just try to queue the build again.

If not, follow these steps:

Press the build in error
Click the task that has an error
Identify the error and react to it.
Edit this section
Contact us