Panda CSSでPrimaryカラーにデフォルトのパレットの色を設定するコードの作成例です。

環境

1
- @pandacss/dev: ^0.13.1

Panda CSS - Build modern websites using build time and type-safe CSS-in-JS

目標

PandaCSSデフォルトのテーマに組み込まれているColorsトークンの値をPrimaryカラーに設定し、primary.${shade}という色合い(Shade)を持つトークンとして利用できるようにすること。

1
2
3
import { css } from "../styled-system/css";

const style = css({ color: "primary.600" });

方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import type { PropertyTypes } from "../styled-system/types/prop-type";

const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];

function definePalette(
  props: Record<string, PropertyTypes["colorPalette"]>,
) {
  return Object.entries(props).reduce<{
    [key: string]: {
      [key: string]: { value: string };
    };
  }>(
    (accum, [key, color]) => ({
      ...accum,
      [key]: shades.reduce<{
        [key: string]: { value: string };
      }>(
        (previousValue, curr) => ({
          ...previousValue,
          [curr]: { value: `{colors.${color}.${curr}}` },
        }),
        {},
      ),
    }),
    {},
  );
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export default defineConfig({
  theme: {
    extend: {
      semanticTokens: {
        colors: {
          ...definePalette({ primary: "sky", secondary: "orange" }),
        },
      },
    },
  },
});

留意点

この方法ではpanda.configはデフォルトのテーマを拡張(extend)することを前提としています。

広告

解説

  1. panda.configsemanticTokensを設定する
  2. ヘルパーとなるdefinePalette関数を作成する

(補) デザイントークンとは

デザイントークンはUIフレームワークで使用されている短縮記法です。デザイントークンを用いることで統一感のあるデザインが可能になります。Panda CSSのデフォルトのテーマにはColors, Spacing, Border Radiusなど豊富なトークンが組み込まれていています。

Tokens - Panda CSS

以下の例では、<p>要素にPanda CSSの文字サイズmd、文字色red.600を設定するReactのコードです。

1
2
3
4
5
import { css } from "../styled-system/css";

const App = () => {
	return <p className={css({ fontSize: "md", color: "red.600" })}>Hoge</p>;
}

上記のコードは以下のDOMに変換されます。

1
<p class="fs_md text_red\.600">hoge</p>

上記のDOMは以下のようなCSS変数とクラスの組み合わせによってスタイリングされます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
:where(:root, :host) {
  --font-sizes-md: 1rem;
  --colors-red-600: #dc2626;
}

.fs_md {
  font-size: var(--font-sizes-md);
}

.text_red\.600 {
  color: var(--colors-red-600);
}

Panda CSS Playground: https://play.panda-css.com/94nv8kumTM

1. panda.configsemanticTokensを設定する

panda.configで新たなトークンを設定する場合、値を直接指定するtokensと、既存のトークンの値を使用して新たなトークンを設定するsemanticTokensの2種類があります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { defineConfig } from "@pandacss/dev";

export default defineConfig({
  theme: {
    extend: {
      tokens: {
        colors: {
          success: { value: "#6f6" },
        },
      },
      semanticTokens: {
        colors: {
          danger: { value: "{colors.red.700}" },
        },
      },
    },
  },
});

上記の例ではtokensでsuccessカラーを設定し、semanticTokensでdangerカラーを設定しています。tokensでは色をカラーコードで指定したのに対して、semanticTokensではデフォルトのテーマに組み込まれているトークンの値を選択することができます。

ちなみにPanda CSSのデフォルトのパレットはTailwind CSSのパレットがベースになっているようです。Panda CSSと開発者が同じChakra UIのパレットとは同じトークン名であっても色が異なります。

Theme - Panda CSS

Customizing Colors - Tailwind CSS

PrimaryカラーにデフォルトColorsのSkyを指定するには以下のようにsemanticTokensを設定することで実現可能です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
export default defineConfig({
  theme: {
    extend: {
      semanticTokens: {
        colors: {
          primary: {
            50: { value: "{colors.sky.50}" },
            100: { value: "{colors.sky.100}" },
            200: { value: "{colors.sky.200}" },
            /* 略 */
            950: { value: "{colors.sky.950}" },
          },
        },
      },
    },
  },
});

しかし上記のように、デフォルトのColorsと同様50から950までの11種類の色合い(Shade)を一つ一つ手作業で設定するのは非常に面倒です。この例だとPrimaryカラーを変更するのも面倒です。さらにPrimaryカラーだけではなく、Secondaryカラーなど複数のパレットを設定する場合、コードは更に冗長になります。

そこでsemanticTokensにを出力するdefinePalette関数を作成します。

2. definePalette関数を作成する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import type { PropertyTypes } from "../styled-system/types/prop-type";

const shades = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950];

function definePalette(
  props: Record<string, PropertyTypes["colorPalette"]>,
) {
  return Object.entries(props).reduce<{
    [key: string]: {
      [key: string]: { value: string };
    };
  }>(
    (accum, [key, color]) => ({
      ...accum,
      [key]: shades.reduce<{
        [key: string]: { value: string };
      }>(
        (previousValue, curr) => ({
          ...previousValue,
          [curr]: { value: `{colors.${color}.${curr}}` },
        }),
        {},
      ),
    }),
    {},
  );
}

この関数の使い方は以下の通りです。semanticTokens.colorsにスプレッド構文でdefinePaletteを記述します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
export default defineConfig({
  theme: {
    extend: {
      semanticTokens: {
        colors: {
          ...definePalette({ primary: "sky", secondary: "orange" }),
        },
      },
    },
  },
});

これで色合いを持つPrimaryカラー、Secondaryカラーを利用することができます。

1
2
3
4
5
6
import { css } from "../styled-system/css";

const style = css({ 
	color: { base: "primary.700", _dark: "primary.100" },
	bg: { base: "secondary.50", _dark: "secondary: 950" },
});

リンク

Panda CSS - Build modern websites using build time and type-safe CSS-in-JS

Cumbia Algarrobera / Son Rompe Pera (2020)

広告