水戸地図(β)

2023年09月10日

Panda CSSでPrimaryカラーにデフォルトのパレットの色を設定する

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

環境

- @pandacss/dev: ^0.13.1
Panda CSS
panda-css.com

目標

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

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

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

方法

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}}` },
        }),
        {},
      ),
    }),
    {},
  );
}
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.com

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

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

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

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

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

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

: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
play.panda-css.com

1. panda.configsemanticTokensを設定する

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

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を設定することで実現可能です。

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関数を作成する

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を記述します。

export default defineConfig({
  theme: {
    extend: {
      semanticTokens: {
        colors: {
          ...definePalette({ primary: "sky", secondary: "orange" }),
        },
      },
    },
  },
});

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

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
panda-css.com

Cumbia Algarrobera / Son Rompe Pera (2020)

広告

2023年09月10日

Panda CSSでPrimaryカラーにデフォルトのパレットの色を設定する

技術記事

Top

水戸地図(β)