npm package: @plangrid/paint
Description: Color codes, classes, and variables
Latest version: 0.34.1

# [`paint`](https://www.npmjs.com/package/@plangrid/paint)

**:art: [formerly known as](https://github.com/plangrid/paint/tree/v0.29.2#readme) [`color`](https://www.npmjs.com/package/@plangrid/color)**

## Production

```css
@import "node_modules/@plangrid/paint/main";
```

- [`main.css`](main.css) is the production bundle
- [`live.css`](live.css) is the same bundle but with live CSS vars
- [`module.css`](module.css) shows the module content for both

## Low-level atomic API

Stateful atomic classes are made via [templates](templates) and provided for all swatches for use like `class="ccc-blue-500"` where the states are described in the legend below. States cascade as shown. Disabled has the highest precedence. State precedence has priority over color precendence. Hover overrides focus...and so on...regardless of color.

- <b>`.ccc-*` `color`</b>
  - `.fcc-*` `:focus`
  - `.hcc-*` `:hover`
  - `.acc-*` `:active`
  - `.dcc-*` `:any(:disabled, [aria-disabled=true])`
- <b>`.ggg-*` `background`</b>
  - `.fgg-*` `:focus`
  - `.hgg-*` `:hover`
  - `.agg-*` `:active`
  - `.dgg-*` `:any(:disabled, [aria-disabled=true])`
- <b>`.bbb-*` `border-color`</b>
  - `.fbb-*` `:focus`
  - `.hbb-*` `:hover`
  - `.abb-*` `:active`
  - `.dbb-*` `:any(:disabled, [aria-disabled=true])`

An earlier simpler less-capable atomic set exists in [`atomic.css`](atomic.css) but we plan to move away from those and instead to the ones above wrapped in a higher-level API via JavaScript. See [#sheen](#sheen)

## [Tone](tone.css)

- `.tone-validate` is designed for inputs using native [`[aria-invalid]`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-invalid_attribute) (Recommended)
- `.tone-validity` is designed for inputs using native [constraint validation](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation)
- `.tone-valid` is designed for forcing valid appearance
- `.tone-invalid` is designed for forcing invalid appearance
- `.tone-primary` is designed for primary actions (Save)
- `.tone-additive` is designed for additive actions (Create)
- `.tone-destructive` is designed for destructive actions (Delete)
- `.tone-pill` combines primary and destructive for deletable pills
- `.tone-secondary` is designed for secondary actions (Cancel)
- `.tone-icon` is designed for buttons represented by icons
- `.tone-link` is designed for links or buttons appearing as links
- `.tone-check` is designed for radios and checkboxes

## [Shadow](shadow.css)

### Floor-based shadow system

Naming for shadows is based on building floors and elevators. Higher numbers have greater size and greater precedence. [See #shadows demo.](https://plangrid.github.io/paint/#shadows) Open [shadow.css](shadow.css) to see all available classes

- `f` floor shadows are raised
  - `f30`
  - `f20`
  - `f10`
- `b` basement shadows are inset
  - `b10`
- `g` ground shadows are glow rings
  - `g10`

### **Deprecated** shadow classes

- `.shadow-raised` base static raised shadow
- `.shadow-ring` applies our standard ring on `:focus`
- `.shadow-halo` **experimental** static raised ring

## [Blending](blending.css)

Blending patterns are useful for routing colors in component designs. Blending classes themselves are for demoing the technique and are excluded from the main bundle.

| Classes | `color` | `background` | `border-color` |
|:--------|:--------|:-------------|:---------------|
| `.blend` `.blend-before` `.blend-after` | `inherit` | `transparent` |  `transparent` |
| `.dodge` `.dodge-before` `.dodge-after` | `transparent` | `transparent` |  `inherit` |
| `.burn` `.burn-before` `.burn-after` | `inherit` | `transparent ` | `currentColor` |
| `.coat` `.coat-before` `.coat-after` | `inherit` | `inherit` |  `inherit` |
| `.blot` `.blot-before` `.blot-after` | `inherit` | `currentColor` | `currentColor` |

## JavaScript API

### [`paint`](paint.js)

```js
const paint = require("@plangrid/paint")
```

[`paint`](paint.js) includes a superset of [`sheen`](#sheen) [`swatch`](#swatch) [`ink`](#ink). These modules are also each available for direct import.

```js
paint.vivid("blue") // atomic classes for vivid blue paint
paint.glaze("blue") // atomic classes for glaze blue paint
paint.matte("blue") // atomic classes for matte blue paint
paint.swatch("blue-500") // "#0085de"
paint.identify("#0085de") // "blue-500"
paint.nearest("#0085dd") // "blue-500"
paint.ideal("blue-base") // "blue-500"
paint.dyes() // ["red", "orange", ...]
/*...*/
```

`paint` classes are also available via the [`cader`](https://github.com/ryanve/cader/tree/v0.7.0#cader) interface

```js
paint.bond("VividRed") // paint.vivid("red")
paint.bond("VividBlue") // paint.vivid("blue")
paint.bond("VividAmber") // paint.vivid("amber")
paint.bond("VividGreen") // paint.vivid("green")
paint.bond("VividPurple") // paint.vivid("purple")

paint.bond("GlazeRed") // paint.glaze("red")
paint.bond("GlazeBlue") // paint.glaze("blue")
paint.bond("GlazeAmber") // paint.glaze("amber")
paint.bond("GlazeGreen") // paint.glaze("green")
paint.bond("GlazePurple") // paint.glaze("purple")

paint.bond("MatteRed") // paint.matte("red")
paint.bond("MatteBlue") // paint.matte("blue")
paint.bond("MatteAmber") // paint.matte("amber")
paint.bond("MatteGreen") // paint.matte("green")
paint.bond("MattePurple") // paint.matte("purple")
paint.bond("MatteMono") // paint.matte("mono")
```

```js
paint.bond("VivixRed") // paint.vivix("red")
paint.bond("VivixBlue") // paint.vivix("blue")
paint.bond("VivixAmber") // paint.vivix("amber")
paint.bond("VivixGreen") // paint.vivix("green")
paint.bond("VivixPurple") // paint.vivix("purple")

paint.bond("GlaxeRed") // paint.glaxe("red")
paint.bond("GlaxeBlue") // paint.glaxe("blue")
paint.bond("GlaxeAmber") // paint.glaxe("amber")
paint.bond("GlaxeGreen") // paint.glaxe("green")
paint.bond("GlaxePurple") // paint.glaxe("purple")

paint.bond("MaxxeRed") // paint.maxxe("red")
paint.bond("MaxxeBlue") // paint.maxxe("blue")
paint.bond("MaxxeAmber") // paint.maxxe("amber")
paint.bond("MaxxeGreen") // paint.maxxe("green")
paint.bond("MaxxePurple") // paint.maxxe("purple")
paint.bond("MaxxeMono") // paint.maxxe("mono")

```

### [`sheen`](sheen.js)

```js
const sheen = require("@plangrid/paint/sheen")
```

```js
sheen.vivid("blue") // atomic classes for vivid blue paint
sheen.glaze("blue") // atomic classes for glaze blue paint
sheen.matte("blue") // atomic classes for matte blue paint

// Like above but for states: checked | expanded | mixed | pressed | selected | ...
sheen.vivix("blue")
sheen.glaxe("blue")
sheen.maxxe("blue")
```

### [`ink`](ink.js)

```js
const ink = require("@plangrid/paint/ink")
```

- `ink` is special paint for annotations
- `dye` is the color used to make an ink
- `pen` types are `dry` `wet` `gel`
- strings are always returned lowercase
- errors `console.warn` and `return ""`

#### `ink.wet(dye)`

`wet` ink is available in any dye. Alias `ink.user(dye)`

```js
ink.wet("orange") // "#f38109"
ink.user("orange") // "#f38109"
```

#### `ink.dry(dye)`

`dry` ink is available in any dye. Alias `ink.master(dye)`

```js
ink.dry("orange") // "#e6400a"
ink.master("orange") // "#e6400a"
```

#### `ink.gel(dye)`

`gel` ink is only available in `"blue"`

```js
ink.gel("blue") // "#0000ff"
```

#### `ink.dye(hex)`

`hex` is case-insensitive, pen-agnostic, longhand

```js
ink.dye("#e6400a") // "orange"
ink.dye("#E6400A") // "orange"
ink.dye(ink.dry("cyan")) // "cyan"
ink.dye(ink.wet("cyan")) // "cyan"
ink.dye("#000000") // "black"
ink.dye("#000") // ""
```

```jsx
className={`wet-${ink.dye("#e6400a")}`}
```

#### `ink.dyes(start=0, end=undefined)`

Slice an array copy of available dyes

```js
ink.dyes() // ["red", "orange", ...]
```

`ink.dyes` is temporarily aliased as `ink.inks` for crossover support. Please update to `ink.dyes` =)

### [`swatch`](swatch.js)

```js
const swatch = require("@plangrid/paint/swatch")
```

<code>swatch(<var>name</var>)</code> is a custom JavaScript function for providing `color` by its name in our design system.

```js
swatch("black") // "#1f313d"
swatch("blue-500") // "#0085de"
```

`swatch` also works with identical interface in `postcss` via [`postcss-functions`](https://www.npmjs.com/package/postcss-functions) and `node-sass` via `--functions`

```css
box-shadow: 1em 1em swatch("black");
box-shadow: 1em 1em swatch("shade-50");
```

#### `swatch.identify(value)`

- `value` can be any valid color format
- Returns `id` of exact match or else throws error

```js
swatch.identify("#1f313d") // "black"
swatch.identify("rgba(31, 49, 61, 0.5)") // "dark-50"
```

#### `swatch.ideal(id)`

- Return ideal id for <var>id</var>
- <var>id</var> may be an alias but the return won't be

```js
swatch.ideal("blue-base") // "blue-500"
swatch.ideal("blue-dim") // "blue-700"
```

#### `swatch.ideals()`

- Return array of all ideals

```js
swatch.ideals() // ["blue-100", "blue-200" ,...]
```

#### `swatch.nearest(value)`

- `value` can be any valid color format
- [Returns `id` for nearest non-transparent match](https://github.com/plangrid/paint/pull/145)

```js
swatch.nearest("#444") // "steel"
swatch.nearest("rgb(1, 1, 1)") // "black"
swatch.nearest("rgba(1, 1, 1, .1)") // "black"
```

#### `swatch.pluck(key)`

- Pluck key from registry objects
- Return array of plucked values

## Development

```
git clone git@github.com:plangrid/color.git
cd color
npm install
npm test
npm start
open index.html
```

Right now the source of truth for the values is in [swatch.js](swatch.js) and [dev.js](dev.js). Running <b>`npm start`</b> updates the other files.

## History

- [Releases](https://github.com/plangrid/paint/releases) `<0.30` were as [`@plangrid/color`](https://www.npmjs.com/package/@plangrid/color)
- Repo was renamed from `color` to `paint` with the [`0.30.0` release](https://github.com/plangrid/paint/releases/tag/v0.30.0)