1
1

More than 1 year has passed since last update.

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

Posted at

環境

- @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)を持つトークンとして利用できるようにすること。

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}}` },
        }),
        {},
      ),
    }),
    {},
  );
}
panda.config.ts
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のコードです。

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: https://play.panda-css.com/94nv8kumTM

1. panda.configsemanticTokensを設定する

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

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

panda.config.ts
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を記述します。

panda.config.ts
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 - Build modern websites using build time and type-safe CSS-in-JS

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1