import { ColorPalette, ColorItem, Meta } from '@storybook/addon-docs';
import { color } from '@palmetto/palmetto-design-tokens/build/js/variables-color';
import { size } from '@palmetto/palmetto-design-tokens/build/js/variables-size';
import { asset } from '@palmetto/palmetto-design-tokens/build/js/variables-asset';
import { Canvas } from '@storybook/addon-docs';

<Meta title="Foundation/Design Tokens" />

# Design Tokens

Design tokens are an abstraction of design decisions made to construct and maintain an application design system. Spacing, color, typography, styles and animation are represented as data, in our case json. They’re used in place of hard-coded values in order to ensure flexibility and unity across all our product experiences.

Design tokens are directly integrated into our component library and cover properties like spacing, color and component state.

We use [Style Dictionary](https://amzn.github.io/style-dictionary/) to generate style definitions across all platforms from a single source - removing roadblocks, errors, and inefficiencies across our workflow.

## Source on Github

[Palmetto Design Tokens](https://github.com/palmetto/palmetto-design-tokens) are available as an [npm package](https://www.npmjs.com/package/@palmetto/palmetto-design-tokens) so that you can create a Palmetto unified product experience for your platform of choice.

## Border Radius

Use these tokens for `border-radius`. They are defined in `rem`, which means they will scale when adjusting the root font size. Pixel values are calculated with a root font size of `16px`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
      <th>px</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['border-radius']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-border-radius-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td>{name !== 'circle' ? entry.original.value * 16 : ''}</td>
      </tr>
    ))}
  </tbody>
</table>

## Border Width

Use these tokens for `border-width`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['border']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-border-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>

## Box Shadow

Used these tokens to set the outer shadow of an element.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['box-shadow']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-box-shadow-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>

## Breakpoints

Palmetto components follow a "mobile-first" approach, where styles are set with mobile devices considered first. Then styling adjustments are made as each minimum viewport width &mdash; the breakpoint &mdash; is reached.

The following breakpoints are used in utility classes, but you can use them to modify your application depending on the user's viewport size.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size.breakpoint).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-breakpoint-${name}`}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
    <tr>
      <td>
        <code>size-breakpoint-500</code>
      </td>
      <td>0px</td>
    </tr>
  </tbody>
</table>

## Color

Refer to the [Palmetto Design Tokens Figma](https://www.figma.com/design/abGRptpr7iPaMsXdEPVm6W/Design-Tokens?node-id=0-1&t=oY6gZSqBDdP10U54-1) for colors.

### Brand Palette

<ColorPalette>
  <ColorItem
    title="color-brand-primary"
    subtitle="Primary colors"
    colors={Object.keys(color.brand.primary).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.primary).map(
        g => color.brand.primary[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-secondary"
    subtitle="secondary colors"
    colors={Object.keys(color.brand.secondary).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.secondary).map(
        g => color.brand.secondary[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-tertiary"
    subtitle="tertiary colors"
    colors={Object.keys(color.brand.tertiary).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.tertiary).map(
        g => color.brand.tertiary[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-success"
    subtitle="success colors"
    colors={Object.keys(color.brand.success).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.success).map(
        g => color.brand.success[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-info"
    subtitle="info colors"
    colors={Object.keys(color.brand.info).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.info).map(
        g => color.brand.info[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-warning"
    subtitle="warning colors"
    colors={Object.keys(color.brand.warning).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.warning).map(
        g => color.brand.warning[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-orange"
    subtitle="orange colors"
    colors={Object.keys(color.brand.orange).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.orange).map(
        g => color.brand.orange[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-danger"
    subtitle="danger colors"
    colors={Object.keys(color.brand.danger).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.danger).map(
        g => color.brand.danger[g].value,
      )[i];
      return acc;
    }, {})}
  />
  <ColorItem
    title="color-brand-grey"
    subtitle="All greys"
    colors={Object.keys(color.brand.grey).reduce((acc, item, i) => {
      acc[item] = Object.keys(color.brand.grey).map(
        g => color.brand.grey[g].value,
      )[i];
      return acc;
    }, {})}
  />
</ColorPalette>

### Background Color Tokens

<table style={{ width: '100%' }}>
  <thead>
    <tr>
      <th>Token Name</th>
      <th>Prop Value</th>
      <th>Value</th>
      <th></th>
      <th>Dark Value</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(color.background).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`color-background-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td style={{ background: entry.value }}></td>
        <td>{entry.darkValue}</td>
        <td style={{ background: entry.darkValue }}></td>
      </tr>
    ))}
  </tbody>
</table>

### Border Color Tokens

<table style={{ width: '100%' }}>
  <thead>
    <tr>
      <th>Token Name</th>
      <th>Prop Value</th>
      <th>Value</th>
      <th></th>
      <th>Dark Value</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(color.border).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`color-border-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td style={{ background: entry.value }}></td>
        <td>{entry.darkValue}</td>
        <td style={{ background: entry.darkValue }}></td>
      </tr>
    ))}
  </tbody>
</table>

### Font Color Tokens

<table style={{ width: '100%' }}>
  <thead>
    <tr>
      <th>Token Name</th>
      <th>Prop Value</th>
      <th>Value</th>
      <th></th>
      <th>Dark Value</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(color.text).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`color-text-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td style={{ background: entry.value }}></td>
        <td>{entry.darkValue}</td>
        <td style={{ background: entry.darkValue }}></td>
      </tr>
    ))}
  </tbody>
</table>

## Font Family

Use these tokens for `font-family`.

<table>
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(asset.fonts).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`asset-fonts-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>

## Font Size

Use these tokens for `font-size`. They are defined in `rem`, which means they will scale when adjusting the root font size. Pixel values are calculated with a root font size of `16px`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
      <th>px</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size.font).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-font-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td>
          {name === 'base'
            ? '16'
            : name === 'inherit'
            ? ''
            : entry.original.value * 16}
        </td>
      </tr>
    ))}
  </tbody>
</table>

## Font Weight

Use these tokens for `font-weight`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['font-weight']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-font-weight-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>

## Line Height

Used these tokens to set the line-heights of elements.
Usually, the line-height is already set by the parent.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['line-height']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-line-height-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>

## Spacing

Spacing tokens are intended for use with `margin` and `padding` properties. They are defined in `rem`, which means they will scale when adjusting the root font size. Pixel values are calculated with a root font size of `16px`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
      <th>px</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size.spacing).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-spacing-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td>
          {name === 'base'
            ? '16'
            : ['inherit', 'auto'].includes(name)
            ? ''
            : entry.original.value * 16}
        </td>
      </tr>
    ))}
  </tbody>
</table>

## Height

Used for both height and maximum height, height tokens have been defined based on percentages or `rem`.

Rem based values will scale when adjusting the root font size. Pixel values are calculated with a root font size of `16px`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
      <th>px</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size.height).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-height-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td>
          {name === 'base'
            ? '16'
            : entry.value.includes('%') || ['inherit', 'auto'].includes(name)
            ? ''
            : entry.original.value * 16}
        </td>
      </tr>
    ))}
  </tbody>
</table>

## Width

Used for both width and maximum width, width tokens are defined based on a percentage or `rem`.

Rem based values will scale when adjusting the root font size. Pixel values are calculated with a root font size of `16px`.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>prop value</th>
      <th>value</th>
      <th>px</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size.width).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-width-${name}`}</code>
        </td>
        <td>
          <code>{name}</code>
        </td>
        <td>{entry.value}</td>
        <td>
          {name === 'base'
            ? '16'
            : entry.value.includes('%') || ['auto', 'inherit'].includes(name)
            ? ''
            : entry.original.value * 16}
        </td>
      </tr>
    ))}
  </tbody>
</table>

## Z-Index

Used these tokens to set the z-index order of layering elements.

<table width="100%">
  <thead>
    <tr>
      <th>token name</th>
      <th>value</th>
    </tr>
  </thead>
  <tbody>
    {Object.entries(size['z-index']).map(([name, entry], i) => (
      <tr key={i}>
        <td>
          <code>{`size-z-index-${name}`}</code>
        </td>
        <td>{entry.value}</td>
      </tr>
    ))}
  </tbody>
</table>
