Zenn
🌼

Tailwind CSS v4 & daisyUI v5でtheme設定 + Storybook対応

2025/03/15に公開

リポジトリ

プロジェクト作成

まず、Next.js のプロジェクトを作成し、必要なパッケージをインストールします。
Next.js以外でも大丈夫です。

pnpm dlx create-next-app@latest --use-pnpm
✔ What is your project named? … tailwindcss-daisyui-storybook-sample
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like your code inside a `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to use Turbopack for `next dev`? … No / Yes
✔ Would you like to customize the import alias (`@/*` by default)? … No / Yes
cd tailwindcss-daisyui-storybook-sample

Storybookがうまく動作しない問題が起きるため、postcss.config.mjsを修正します。

postcss.config.mjs
export default {
  plugins: {
    '@tailwindcss/postcss': {},
  },
};

daisyUI

pnpm add -D daisyui@latest

src/app/globals.cssにdaisyUIを追加します。すでにあるスタイルは削除します。

src/app/globals.css
@import "tailwindcss";
@plugin "daisyui";

theme設定

daisyUI のテーマ生成ツールを利用し、Rose Pine をベースにカスタムテーマを作成します。

まず、daisyUIのtheme generatorにアクセスします。

このgeneratorを使用してthemeを出力します。

Rose PineにはdaisyUI用の設定が存在するのですが、CSS First Configurationsに対応していないためこれをもとに自分で作成します。

今回は、rosepine-dawnをlight-theme、rosepine-moonをdark-themeとして設定します。

とりあえず対応する色が存在する項目だけ入力しました。

残りはbase-200, base-300とそれぞれのcontentです。

base-200base-300にはRose PineのSurfaceOverlayを入力することにします。

また、base-contentneutral-contentにはRose PineのTextを入力することにします。

他のcontentに関してはTextの色だとコントラストが悪いためaccessible-color-generatorを使用して適切な色を生成します。

すべての色を入力し終えたあとのconfigがこちらです。

@plugin "daisyui/theme" {
  name: "rosepine-dawn";
  default: true;
  prefersdark: false;
  color-scheme: "light";
  --color-base-100: #fffaf3;
  --color-base-200: #fffaf3;
  --color-base-300: #f2e9e1;
  --color-base-content: #575279;
  --color-primary: #907aa9;
  --color-primary-content: #221339;
  --color-secondary: #d7827e;
  --color-secondary-content: #5d161b;
  --color-accent: #907aa9;
  --color-accent-content: #221339;
  --color-neutral: #faf4ed;
  --color-neutral-content: #575279;
  --color-info: #286983;
  --color-info-content: #abe6ff;
  --color-success: #56949f;
  --color-success-content: #002831;
  --color-warning: #ea9d34;
  --color-warning-content: #6a3300;
  --color-error: #b4637a;
  --color-error-content: #2d0000;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}

これをdark-themeでも行います。

@plugin "daisyui/theme" {
  name: "rosepine-moon";
  default: false;
  prefersdark: true;
  color-scheme: "dark";
  --color-base-100: #232136;
  --color-base-200: #2a273f;
  --color-base-300: #393552;
  --color-base-content: #e0def4;
  --color-primary: #c4a7e7;
  --color-primary-content: #503970;
  --color-secondary: #ea9a97;
  --color-secondary-content: #702d2f;
  --color-accent: #c4a7e7;
  --color-accent-content: #503970;
  --color-neutral: #2a273f;
  --color-neutral-content: #e0def4;
  --color-info: #3e8fb0;
  --color-info-content: #00213b;
  --color-success: #9ccfd8;
  --color-success-content: #265961;
  --color-warning: #f6c177;
  --color-warning-content: #744e03;
  --color-error: #eb6f92;
  --color-error-content: #660025;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}

これをsrc/app/globals.cssに追記します。

src/app/globals.css
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui";
@plugin "daisyui/theme" {
  name: "rosepine-dawn";
  default: true;
  prefersdark: false;
  color-scheme: "light";
  --color-base-100: #fffaf3;
  --color-base-200: #fffaf3;
  --color-base-300: #f2e9e1;
  --color-base-content: #575279;
  --color-primary: #907aa9;
  --color-primary-content: #221339;
  --color-secondary: #d7827e;
  --color-secondary-content: #5d161b;
  --color-accent: #907aa9;
  --color-accent-content: #221339;
  --color-neutral: #faf4ed;
  --color-neutral-content: #575279;
  --color-info: #286983;
  --color-info-content: #abe6ff;
  --color-success: #56949f;
  --color-success-content: #002831;
  --color-warning: #ea9d34;
  --color-warning-content: #6a3300;
  --color-error: #b4637a;
  --color-error-content: #2d0000;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}
@plugin "daisyui/theme" {
  name: "rosepine-moon";
  default: false;
  prefersdark: true;
  color-scheme: "dark";
  --color-base-100: #232136;
  --color-base-200: #2a273f;
  --color-base-300: #393552;
  --color-base-content: #e0def4;
  --color-primary: #c4a7e7;
  --color-primary-content: #503970;
  --color-secondary: #ea9a97;
  --color-secondary-content: #702d2f;
  --color-accent: #c4a7e7;
  --color-accent-content: #503970;
  --color-neutral: #2a273f;
  --color-neutral-content: #e0def4;
  --color-info: #3e8fb0;
  --color-info-content: #00213b;
  --color-success: #9ccfd8;
  --color-success-content: #265961;
  --color-warning: #f6c177;
  --color-warning-content: #744e03;
  --color-error: #eb6f92;
  --color-error-content: #660025;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}

また、daisyUIで用意されているカラートークン以外の色を追加したい場合は同様にthemeの中に追記してください。

src/app/globals.css
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui";
@plugin "daisyui/theme" {
  name: "rosepine-dawn";
  default: true;
  prefersdark: false;
  color-scheme: "light";
  --color-base-100: #fffaf3;
  --color-base-200: #fffaf3;
  --color-base-300: #f2e9e1;
  --color-base-content: #575279;
  --color-primary: #907aa9;
  --color-primary-content: #221339;
  --color-secondary: #d7827e;
  --color-secondary-content: #5d161b;
  --color-accent: #907aa9;
  --color-accent-content: #221339;
  --color-neutral: #faf4ed;
  --color-neutral-content: #575279;
  --color-info: #286983;
  --color-info-content: #abe6ff;
  --color-success: #56949f;
  --color-success-content: #002831;
  --color-warning: #ea9d34;
  --color-warning-content: #6a3300;
  --color-error: #b4637a;
  --color-error-content: #2d0000;
+  --color-muted: #9893a5;
+  --color-subtle: #797593;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}
@plugin "daisyui/theme" {
  name: "rosepine-moon";
  default: false;
  prefersdark: true;
  color-scheme: "dark";
  --color-base-100: #232136;
  --color-base-200: #2a273f;
  --color-base-300: #393552;
  --color-base-content: #e0def4;
  --color-primary: #c4a7e7;
  --color-primary-content: #503970;
  --color-secondary: #ea9a97;
  --color-secondary-content: #702d2f;
  --color-accent: #c4a7e7;
  --color-accent-content: #503970;
  --color-neutral: #2a273f;
  --color-neutral-content: #e0def4;
  --color-info: #3e8fb0;
  --color-info-content: #00213b;
  --color-success: #9ccfd8;
  --color-success-content: #265961;
  --color-warning: #f6c177;
  --color-warning-content: #744e03;
  --color-error: #eb6f92;
  --color-error-content: #660025;
+  --color-muted: #6e6a86;
+  --color-subtle: #908caa;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}

今回はRose PineのMutedSubtleを追加しました。

しかし、独自に定義したカラートークンはTailwind CSS側で認識されないため、Tailwind CSS側の設定にも追加します。

src/app/globals.css
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui";
@plugin "daisyui/theme" {
  name: "rosepine-dawn";
  default: true;
  prefersdark: false;
  color-scheme: "light";
  --color-base-100: #fffaf3;
  --color-base-200: #fffaf3;
  --color-base-300: #f2e9e1;
  --color-base-content: #575279;
  --color-primary: #907aa9;
  --color-primary-content: #221339;
  --color-secondary: #d7827e;
  --color-secondary-content: #5d161b;
  --color-accent: #907aa9;
  --color-accent-content: #221339;
  --color-neutral: #faf4ed;
  --color-neutral-content: #575279;
  --color-info: #286983;
  --color-info-content: #abe6ff;
  --color-success: #56949f;
  --color-success-content: #002831;
  --color-warning: #ea9d34;
  --color-warning-content: #6a3300;
  --color-error: #b4637a;
  --color-error-content: #2d0000;
  --color-muted: #9893a5;
  --color-subtle: #797593;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}
@plugin "daisyui/theme" {
  name: "rosepine-moon";
  default: false;
  prefersdark: true;
  color-scheme: "dark";
  --color-base-100: #232136;
  --color-base-200: #2a273f;
  --color-base-300: #393552;
  --color-base-content: #e0def4;
  --color-primary: #c4a7e7;
  --color-primary-content: #503970;
  --color-secondary: #ea9a97;
  --color-secondary-content: #702d2f;
  --color-accent: #c4a7e7;
  --color-accent-content: #503970;
  --color-neutral: #2a273f;
  --color-neutral-content: #e0def4;
  --color-info: #3e8fb0;
  --color-info-content: #00213b;
  --color-success: #9ccfd8;
  --color-success-content: #265961;
  --color-warning: #f6c177;
  --color-warning-content: #744e03;
  --color-error: #eb6f92;
  --color-error-content: #660025;
  --color-muted: #6e6a86;
  --color-subtle: #908caa;
  --radius-selector: 0.5rem;
  --radius-field: 0.25rem;
  --radius-box: 0.5rem;
  --size-selector: 0.25rem;
  --size-field: 0.25rem;
  --border: 1px;
  --depth: 1;
  --noise: 0;
}

@theme {
  --color-muted: var(--color-muted);
  --color-subtle: var(--color-subtle);
}

これでthemeの設定は完了です。

足りない色の生成には、theme-colorsもおすすめです。

Storybook

pnpm create storybook@latest

theme用のaddonを追加します。

pnpm add -D @storybook/addon-themes
.storybook/main.ts
import type { StorybookConfig } from '@storybook/experimental-nextjs-vite';

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: [
    '@storybook/addon-essentials',
    '@storybook/addon-onboarding',
    '@chromatic-com/storybook',
    '@storybook/experimental-addon-test',
    '@storybook/addon-themes',
  ],
  framework: {
    name: '@storybook/experimental-nextjs-vite',
    options: {},
  },
  staticDirs: ['../public'],
};
export default config;
.storybook/preview.ts
import { withThemeByDataAttribute } from '@storybook/addon-themes';
import type { Preview, ReactRenderer } from '@storybook/react';

import '../src/app/globals.css';

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  decorators: [
    withThemeByDataAttribute<ReactRenderer>({
      themes: {
        light: 'rosepine-dawn',
        dark: 'rosepine-moon',
      },
      defaultTheme: 'light',
      attributeName: 'data-theme',
    }),
  ],
};

export default preview;

これで設定は完了です!

GitHubで編集を提案

Discussion

ログインするとコメントできます