<img src="http://i.imgur.com/J5hKDEP.png">

[![CircleCI](https://circleci.com/gh/dollarshaveclub/ui/tree/master.svg?style=svg&circle-token=3ed53bb262ab4c466a49bc3c481726a098fa2765)](https://circleci.com/gh/dollarshaveclub/ui/tree/master)
[![Greenkeeper badge](https://badges.greenkeeper.io/dollarshaveclub/ui.svg?token=63c17a2d5274b6b4341b3141e95f8fc28f589f67389ce313e0607c5438fa788f&ts=1515714276236)](https://greenkeeper.io/)
[![NSP Status](https://nodesecurity.io/orgs/dsc/projects/2d7e1d62-3732-4958-a8aa-c7451886f1c9/badge)](https://nodesecurity.io/orgs/dsc/projects/2d7e1d62-3732-4958-a8aa-c7451886f1c9)
[![npm (scoped)](https://img.shields.io/npm/v/@dollarshaveclub/ui.svg?style=flat-square)](https://www.npmjs.com/package/@dollarshaveclub/ui)

UI is a CSS framework for interfaces commonly built at Dollar Shave Club. [View the Storybook here](http://dollarshaveclub.github.io/ui/).

- [Guide](http://dollarshaveclub.github.io/ui/)
- [Features](#features)
- [Usage](#usage)
- [Developing](#developing)
- [TypeScript or JSX with PropTypes](#typexcript-or-jsx-with-proptypes)
- [Linting](#linting)
- [Publishing](#publishing)
- [CLI](#cli)
- [FAQ](#faq)
- [Contributing](#contributing)

---

## Features

- Uses CSS, SCSS, ES6, or JS. Flexible and easy to install.
- Create composable interfaces that are easy to make your own.
- Technology/Framework Agnostic, but still developer friendly.
- Generous documentation and examples.
- Source of truth for DSCs current standards in design.

## Usage

UI can be used in many ways. You can import the `scss` directly into your project, you may include the `css` file in your HTML, and you can even import React components.

#### HTML

Get started with a base template

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <link
      rel="stylesheet"
      href="https://unpkg.com/@dollarshaveclub/ui/dist/ui.css"
    />
    <title>UI</title>
  </head>
  <body>
    <h1 class="ui-text__h1">Hello, World!</h1>
    <button class="ui-btn ui-btn--lg">Get Started</button>
  </body>
</html>
```

#### NPM

Install UI via NPM

```bash
npm i --save-dev @dollarshaveclub/ui
```

You are free to include `node_modules/ui/dist/ui.css` in your project however you see fit.

If you wish to import it via SASS, you must first specify the `ui` scss `src` folder as an `includePath` in your sass build configuration

```js
// Your sass build may be different. Reference SASS includePaths for more information
const sassOptions = {
  includePaths: ['./node_modules'],
}
```

Then you may import variables or mixins via `sass`

#### SCSS

```scss
// Import UI Config or Mixins
@import '@dollarshaveclub/ui/scss/config/colors';
@import '@dollarshaveclub/ui/scss/mixins/breakpoints';
```

#### React Components

If you are using a webpack loader to transpile es6:

```js
import BreadcrumbsLarge from '@dollarshaveclub/ui/components/breadcrumbs/large'
```

If you're looking to import transpiled components:

```js
import BreadcrumbsLarge from '@dollarshaveclub/ui/dist/components/breadcrumbs/large'
```

## Developing

Developing with `ui` locally is easy.

```sh
nvm use # Ensure you're on the correct version of node
npm i # Install node dependencies
npm run build # Compile CSS and transpile react components
npm start # Start Storybook
```

## TypeScript or JSX with PropTypes

UI accepts JS or TSX files for writing components. If DSC standards are used for inheriting repositories (like Face-landing in example), TypeScript (TSX) components can be imported as expected. Specifying TSX may be required to successful import components but that is it!

```typescript
import foo from 'bar' // or
import foo from 'bar.tsx'
```

If Typescript is being used, an `interface` is defined to describe the "type" of code that is written. If JSX is used, Prop-types creates similar functionality. It is recommended that Typescript is used because Typescript offers fully featured Type checking without post Transpilation side affects. Prop-types helps describe a code interface but does not define it. Plus, Prop-types can leave artifacts in built code.

```typescript
type Crumb = {
  active?: boolean
  empty?: boolean
  label: string
  link?: string
}
```

```javascript
Crumb.propTypes = {
  active: PropTypes.boolean,
  empty: PropTypes.boolean,
  label: PropTypes.string,
  isRequired,
  link: PropTypes.string,
}
```

## Linking

Link UI to your application like you would any other package

```sh
cd ~/code/ui
npm link
cd <my-repo>
npm link @dollarshaveclub/ui
```

## Linting

Linting is required to merge any branch to `master`. They not only dictate any style guides we'd like to adhere to, but help enforce various rules such as nesting depth and use of hex colors.

The linting rules are still a work in progress. Please read the [contributing section](#contributing) if you want to add or modify any rules.

```sh
apm install linter-stylelint # Install the StyleLint for Atom
npm run lint # Run all linters
npm run eslint # Lint JavaScript
npm run stylelint # Lint SCSS
```

## Dependents

UI is used across several repos. Use this command to see what version everyone is using

```sh
npm run dependents
```

## Publishing

Update your version number in `package.json` before you merge your feature branch into `master`. Circle will publish the updated version on `npm` and rebuild our documentation in `gh-pages`

## CLI

UI comes with a CLI with useful scripts to help you implement and develop with it.

```sh
$ ui validate -f my-styles.css # Checks to see that your CSS is using valid UI classes
& ui validate --reverse -f my-styles.css # Checks to see that UI contains the classes in your styles, useful for catching custom UI styles in your app that need to be migrated
```

## FAQ

**How do I use this?**

- _Include the CSS file into your application in any way you see fit, or refer to the install section for more information. Then just use the class names and DOM structures provided in the documentation_.

**Why does this exist?**

- _Core visual components should be standardized. This means that there is a right way and a wrong way to style certain things, which makes it much easier to get right than it does to get wrong. CSS is hard, and this set of styles aims to provide consistency and harmony to compensate for that._

**Why SCSS?**

- _SCSS was chosen because it is lexicographically easier to parse. This means that more libraries can interpret our styles and provide constructive feedback on things such as specificity, redundancy, and common predetermined conventions. SCSS = Acorn as ES6 = Babel. AST FTW._

**I am on a different platform than the web and cannot adhere to these standards. What should I do?**

- _The styles demonstrated in the kitchen sink are exemplary of designs current standards. While each platform's requirements may differ, it is worthwhile to consider the holistic intentions design has set forth. If you feel some things are strangely out of place, [consider opening a pull request](https://github.com/dollarshaveclub/ui/issues/new) to share your needs._

**BEM is love. BEM is life. Right?**

- _The core difficulties most of us face with CSS are the same things that makes it so powerful; that is largely the cascade. BEM is not meant to be a dogmatic solution to all of our issues. It provides a set of rules that enable us to develop interfaces in equally powerful ways while still managing the cascade._

- _Not every classname will follow BEM conventions, but that is ok. Most classes tend to do so where applicable. Considerate code review helps thwart oddly specific rules, but also allow strategic advantages in the code._

**I want access to the variables and mixins UI provides, not the CSS**

- _Not a problem. Simply install `ui` with npm. Then simply build the `src/index.scss` file or build your own `scss` file that imports the desired `ui` files._

**Using TypeScript or JavaScript**

- _Using TypeScript or JavaScript is possible in UI. There are minor changes that are made to ensure that TypeScript works in UI: within Storybooks the `.tsx` extension must be added, within the `package.json` Jest configuration changes might be required._

**Importing Icons**

- _Sometimes you may want to import an SVG Icon from a Sketch or Adobe Illustrator file. In this case, you need to follow the following requirements for SVG Icons:_

1. Make sure the icon is 15x15 from design. Make sure shapes are converted to paths.
2. Remove all `fills`
3. Import SVG into `resources/images/elements/icons/`
4. Download [SVGO](https://github.com/svg/svgo) (`npm i -g SVGO`) and run `svgo /path/to/your/svg --pretty` to compress your SVG.
5. Add icon class to `icons.stories.js`.
6. Finally, run `npm run build` to build the icon font and view changes in storybook.

## Contributing

Branch off of `master`. Create your modifications and open a Pull Request back into `master`. Ensure that your `scss` and Javascript are appropriately linted, and that you've written tests for any additional components. After code and visual review, merge into `master` to kick off the deploy/publish work.
