Tailwind CSS v4 & daisyUI v5でtheme設定 + Storybook対応
リポジトリ
プロジェクト作成
まず、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
を修正します。
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
daisyUI
pnpm add -D daisyui@latest
src/app/globals.css
にdaisyUIを追加します。すでにあるスタイルは削除します。
@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-200
とbase-300
にはRose PineのSurface
とOverlay
を入力することにします。
また、base-content
とneutral-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
に追記します。
@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の中に追記してください。
@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のMuted
とSubtle
を追加しました。
しかし、独自に定義したカラートークンはTailwind CSS側で認識されないため、Tailwind 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
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;
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;
これで設定は完了です!
Discussion