# Bulb Design

Welcome to the Bulb Design repository 👋

![Bulb logo](https://storage.googleapis.com/static.bulb.co.uk/design/images/Bulb-logo.png)

## Table of contents

- [Design library](#viewing-the-pattern-library)

- [Install](#consuming-the-patterns-package)

- [Working with components](#typescript-components)

- [Local development](#local-development)

- [Creating / Submitting new patterns](#creating-patterns)

- [Tracking changes](#tracking-changes)

- [Documenting new patterns](#pattern-documentation)

- [Using static variables and values](#static-variables-and-values)

- [Using global styles](#using-global-styles)

- [Testing](#testing)

  - [Snapshot testing](#testing)

  - [Visual regression testing](#visual-regression-tests)

- [Troubleshooting guide](#troubleshooting-guide)

## Viewing the pattern library

The latest version of the library is published at http://design.bulb.co.uk where you can browse the library and try new pattern arrangements in the playgrounds.

## Consuming the patterns package

To use the patterns in your project, first, add the `@bulb/design` package.

Note: this is a private package, and you will need to login to [npm](https://www.npmjs.com) and be added to the Bulb npm organisation.

```bash
yarn add @bulb/design
```

You can then simply import the components you wish to use, if you're using the full project.

## Working with components

```tsx
import { Dropdown } from '@bulb/design/modules/Dropdown';

<Dropdown {...props} />;
```

## Local Development

### Running the library locally

To run the library locally run the following command.

```sh
yarn run start
```

This will run it in a hot mode and will update any browser windows (on modern browsers) with any changes you make locally. For older browsers such as ie10 you will need to manually refresh the browser window following local changes.

### Creating Patterns

See the [Solar technical styleguide](http://design.bulb.co.uk/practices/building) for details about how to structure and write new patterns.

## Tracking changes

We use changelogs for patterns to help document the changes to components over time.

This helps us when consuming components that have been changed by one another to see why and how components have changed.

When updating components, we update the adjacent `CHANGELOG.md` file with an entry describing the change where appropriate.

New changes should be added under the `vNext` section at the top of the changelog file.

- For breaking component changes prefix the entry with [major] to communicate the new behaviour.
- For new feature prefix the entry with [minor] to communicate the new behaviour.
- For bug fixes prefix the entry with [patch] to communicate the new behaviour.

### example changelog structure

```md
# CHANGELOG

## vNext

- [major] short description of breaking change
- [minor] short description of new feature
- [patch] short description of bug fix
- short description of non breaking change

## v17.0.1

// ...previous changes
```

## Pattern Documentation

We utilise [docz](https://www.docz.site/) to create a visual reference to all the patterns we've built in here and [mdx](https://www.docz.site/) to write both JSX and component documentation.

When you add a new pattern to this repo, the `README.mdx` should be filled with details of this pattern.

It is generally the same Markdown as with Github, with the addition of Specimens - read about those [over here](https://docs.catalog.style/specimens) to make your documentation amazing.

If you need to do any styling or functional changes to specimens - docz theme solar is a [separate repository](https://github.com/BulbEnergy/docz-theme-solar)

## Static Variables and Values

Static values and CSS variables are in the `src/styles` directory.

In your components, you can import these,

```js
import { palette } from '../../styles/palette';
```

## Using global styles

At Bulb we use `styled-components` to enable styles to be developed at a component level.

However, not everything should be a component style in the first place, things like font-families, line-heights, and focus styles are better placed as global (base) styles because:

1.  We want to use them everywhere
2.  Aside from a few exceptions, we want to use them everywhere _the same way_
3.  They should be low specificity, and easy to override where needed anyway

With focus styles, it’s particularly helpful because

1.  In almost all cases, we want to use the same focus style
2.  Focus styles are mandatory for WCAG AA accessibility, so we don’t have to think about whether one is needed or not
3.  It’s difficult to test for focus styling, and few automated accessibility testing tools report them where they are missing

We commit to having focus styles written for each component but it is not systemically robust and dependable to rely on the development process to ensure these are always present and well setup.

### Usage

```code
import { createGlobalStyle } from 'styled-components';
import { global } from '@bulb/design/styles/Global'

// with default responsive behaviour
const GlobalStyle = createGlobalStyle`
  ${global()}
`

// with custom responsive behaviour
const GlobalStyle = createGlobalStyle`
  ${global({
    responsiveBehaviours: [
      { fontSize: '16px' },
      { minWidth: '731px', fontSize: '20px' },
      { minWidth: '1695px', fontSize: '26px' },
    ]
  })}
`
```

### Default viewports

```table
span: 3
rows:
  - Responsive Step: initial
    Font Size: 16px
  - Responsive Step: 667px
    Font Size: 20px
  - Responsive Step: 1695
    Font Size: 26px
```

### Two Column viewports

Used with two column layouts ie. magenta (bulb account)

```table
span: 3
rows:
  - Responsive Step: initial
    Font Size: 16px
  - Responsive Step: 1024px
    Font Size: 20px
  - Responsive Step: 1695px
    Font Size: 26px
```

## Testing

## Unit tests and snapshots

#### run non vr tests

The test command is simply

```bash
yarn test
```

You can add any of the
[Jest CLI options](https://facebook.github.io/jest/docs/en/cli.html) to test
specific files.

Your tests should cover any interactions your component may have.

#### update non vr snapshots

The command is

```bash
yarn test -u
```

## Visual regression tests

We use visual regression tests to give us confidence in our component's visual behaviour when making changes.

Visual regression tests should be setup for component's in adjacent `{ComponentName}.vr-test.tsx` files, and generate snapshots into an adjacent **image_snapshots** folder.

### Running visual regression tests locally

#### docker setup

This command only needs to be run once per development machine. Docker will save `browserless/chrome` locally for you to use any time in the future.

```sh
docker pull browserless/chrome:release-puppeteer-1.10.0
```

#### run the docker machine

In order to run the visual regression tests in development, you will need to be running the `browserless/chrome:release-puppeteer-1.10.0` docker image locally running on port `8080`.

To do so run the following command prior to running the visual regression tests. You can leave it running in the background for future test runs, or terminate and rerun before running tests again.

```sh
yarn run docker-vr
```

#### run the vr tests

The test command is simply

```bash
yarn vr-test
```

If there are any changes to the snapshots, a diff file is generated next to the existing snapshots.

#### Updating vr snapshots

Once you have confirmed that the snapshot diffs are expected, you can update the snapshots by running:

```sh
yarn vr-test -u
```

### Example Usage

```md
- /ElementName
  - /**image_snapshots**
    - elementname-vr-test-tsx-execution-one-large-1.snap.png
    - elementname-vr-test-tsx-execution-one-small-1.snap.png
    - elementname-vr-test-tsx-execution-two-large-1.snap.png
    - elementname-vr-test-tsx-execution-two-small-1.snap.png
  - index.tsx
  - styled.tsx
  - ElementName.test.tsx
  - ElementName.vr-test.tsx
```

```tsx
// ElementName.vr-test.tsx
import { snapshotComponent, largeViewport, smallViewport } from '../../../vr-test';

const screenshotOptions = {
  // by default we use the bounding box of the components container
  // this allows you to test for components that break out of this
  clip: {
    width: 250,
    height: 100,
    x: 0,
    y: 0,
  },
};

describe('execution-one', () => {
  const componentExecutionOne = <Component execution="one" />

  it('large', async () => {
    const snapshot = await snapshotComponent(componentExecutionOne, {
      viewport: 'large',
    });

    expect(snapshot).toMatchImageSnapshot();
  })
  it('narrow', async () => {
    const snapshot = await snapshotComponent(componentExecutionOne, {
      viewport: 'narrow',
      screenshotOptions,
    });

    expect(snapshot).toMatchImageSnapshot();
  })
}

describe('execution-two', () => {
  const componentExecutionTwo = <Component execution="two" />

  it('large', async () => {
    const snapshot = await snapshotComponent(componentExecutionTwo, {
      viewport: 'large',
    });

    expect(snapshot).toMatchImageSnapshot();
  })
  it('narrow', async () => {
    const snapshot = await snapshotComponent(componentExecutionTwo, {
      viewport: 'narrow',
      screenshotOptions,
    });

    expect(snapshot).toMatchImageSnapshot();
  })
}
```

## Troubleshooting guide

Use the [troubleshooting guide](./Troubleshooting-guide.md) for resolving any errors when updating the design library

The test command is simply

```bash
yarn vr-test
```
