/setting-up-charcoal-tailwind
Use before writing or editing code that uses @charcoal-ui with Tailwind, and whenever such a project's charcoal setup is unverified or incomplete. The v2 token route still needs the theme CSS and the .ch-token-v2 opt-in, which the preset does not supply.
Claude Code
$ npx -y skills add pixiv/charcoal --skill setting-up-charcoal-tailwind --agent claude-code
Codex
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a codex -y
Cursor
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a cursor -y
Gemini CLI
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a gemini-cli -y
GitHub Copilot
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a github-copilot -y
OpenCode
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a opencode -y
Windsurf
$ npx skills add pixiv/charcoal --skill setting-up-charcoal-tailwind -a windsurf -y
SKILL.md
setting-up-charcoal-tailwind.SKILL.mdname: setting-up-charcoal-tailwind
description: Use before writing or editing code that uses @charcoal-ui with Tailwind, and whenever such a project's charcoal setup is unverified or incomplete. The v2 token route still needs the theme CSS and the .ch-token-v2 opt-in, which the preset does not supply.
Setting up charcoal with Tailwind
`@charcoal-ui/tailwind-config` turns charcoal tokens into a Tailwind preset. This is the actively developed utility route — new Design Token 2.0 features land here first.
Install
npm install --save-dev @charcoal-ui/tailwind-config @charcoal-ui/theme
Peer dependencies: `tailwindcss >=1.4.6`, `postcss >=7.0.32`, `csstype >=3.0.0`. Tailwind v4 support is WIP — v4 works only by pointing `@config` at a v3-shaped config.
Configure
// tailwind.config.js
const { light, dark } = require('@charcoal-ui/theme')
const { createTailwindConfig } = require('@charcoal-ui/tailwind-config')
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
presets: [
createTailwindConfig({
version: 'v3',
theme: {
':root': light,
'@media (prefers-color-scheme: dark)': dark,
},
unstableTokenV2: true, // Design Token 2.0 — omit and you get 1.0
iconsV2: true,
}),
],
}`createTailwindConfig()` options: `version` (`'v1' | 'v2' | 'v3'`, Tailwind's version — unrelated to charcoal's), `theme`, `cssVariablesV1`, `unstableTokenV2`, `iconsV1`, `iconsV2`. A bare default preset is also exported as `config`.
`unstableTokenV2: true` needs the theme CSS too
The preset does **not** define Design Token 2.0 variables. `unstable_createTailwindConfigTokenV2()` contains no plugin and no `addBase()` — it only emits class values that _reference_ `var(--charcoal-color-*)`. Something else has to define them.
Two disjoint namespaces are in play:
| Defined by | Names | Example | | ------------------------------------------------- | ----------------------------- | -------------------------------------------- | | The preset, when `cssVariablesV1` is on (default) | `--charcoal-<v1 token>` | `--charcoal-background1`, `--charcoal-text1` | | `@charcoal-ui/theme/css/v2/*.css` | `--charcoal-color-<v2 token>` | `--charcoal-color-container-default` |
`customPropertyToken()` produces `--charcoal-${id}`, so the v1 variables never satisfy a v2 reference. Turning on `unstableTokenV2` without loading the theme CSS gives you classes that resolve to nothing — colors silently disappear.
So with `unstableTokenV2: true`, do all three:
/* globals.css */
@import '@charcoal-ui/theme/css/v2/light.css';
@import '@charcoal-ui/theme/css/v2/dark.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
<html lang="ja" class="ch-token-v2">
<body>
<div id="root"></div>
</body>
</html>`.ch-token-v2` gates the light-theme rules in `light.css`. Without it, no light rule matches and every v2 variable is undefined — the same failure described in setting-up-charcoal-css-variables.
If you stay on Design Token 1.0 (`unstableTokenV2` omitted), the preset's own `addBase()` supplies everything and the three `@tailwind` lines are all you need.
The preset replaces Tailwind's defaults
`createTailwindConfig()` writes `colors`, `spacing`, `width`, `gap`, `borderRadius`, `screens`, and `transitionDuration` at the **top level of `theme`**, not under `extend`. Tailwind's preset merge therefore _replaces_ the stock scales:
- `bg-red-500`, `text-blue-600` and the rest of the default palette stop existing. Only `transparent`, `current`, `black`, `white`, and charcoal tokens remain.
- `p-4` no longer means 1rem. Spacing keys are charcoal's px values: `0, 4, 8, 16, 24, 40, 64, 104, 168, 272, 440` — so `p-16` is 16px.
- `corePlugins: { lineHeight: false }` disables every `leading-*` utility.
If existing markup relies on stock Tailwind classes, add them back explicitly:
const colors = require('tailwindcss/colors')
module.exports = {
presets: [createTailwindConfig({/* … */})],
theme: { extend: { colors: { red: colors.red } } },
}Classes you get
<div className="bg-background1 text-text1 rounded-8 p-16">
<h2 className="typography-20">タイトル</h2>
<button className="ch-focus-ring bg-brand hover:bg-brand-hover active:bg-brand-press">
送信
</button>
</div>- Colors carry `DEFAULT` / `hover` / `press` / `disabled` variants — `bg-brand`, `bg-brand-hover`, …
- `typography-{12|14|16|20|32}` sets font-size and line-height together.
- `.ch-focus-ring` reproduces the focus ring used by `@charcoal-ui/react`.
- `w-col-span-{n}` and `w-{n}/12` come from the grid system.
Those names are Design Token 1.0. They keep working when `unstableTokenV2` is on, because the preset merges v2 entries on top of v1 rather than replacing them.
Design Token 2.0 adds five color groups — `background`, `border`, `container`, `icon`, `text` — folded so that a `default` key becomes the bare class:
color.container.default → bg-container
color.container.hover → bg-container-hover
color.text.default → text-text
color.text.info.default → text-text-info
color.text.negative.hover → text-text-negative-hover
color.background.secondary → bg-background-secondary
Spacing splits into `component-*` and `layout-*` (`p-component-20`, `gap-layout-40`), radius becomes `rounded-{xs|s|m|l|xl|xxl|oval}`, and border colors take a `ch` prefix (`border-ch-secondary`).
To see exactly what your config produces, resolve it rather than guessing:
console.log(
require('tailwindcss/resolveConfig')(require('./tailwind.config.js')).theme
.colors,
)Dark theme
Tailwind's `dark:` variant is **not supported**. A charcoal token keeps its name across themes while its value changes, so `dark:bg-background
Read more
name: setting-up-charcoal-tailwind description: Use before writing or editing code that uses @charcoal-ui with Tailwind, and whenever such a project's charcoal setup is unverified or incomplete. The v2 token route still needs the theme CSS and the .ch-token-v2 opt-in, which the preset does not supply.
Setting up charcoal with Tailwind
`@charcoal-ui/tailwind-config` turns charcoal tokens into a Tailwind preset. This is the actively developed utility route — new Design Token 2.0 features land here first.
Install
npm install --save-dev @charcoal-ui/tailwind-config @charcoal-ui/theme
Peer dependencies: `tailwindcss >=1.4.6`, `postcss >=7.0.32`, `csstype >=3.0.0`. Tailwind v4 support is WIP — v4 works only by pointing `@config` at a v3-shaped config.
Configure
// tailwind.config.js
const { light, dark } = require('@charcoal-ui/theme')
const { createTailwindConfig } = require('@charcoal-ui/tailwind-config')
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,ts,jsx,tsx}'],
presets: [
createTailwindConfig({
version: 'v3',
theme: {
':root': light,
'@media (prefers-color-scheme: dark)': dark,
},
unstableTokenV2: true, // Design Token 2.0 — omit and you get 1.0
iconsV2: true,
}),
],
}`createTailwindConfig()` options: `version` (`'v1' | 'v2' | 'v3'`, Tailwind's version — unrelated to charcoal's), `theme`, `cssVariablesV1`, `unstableTokenV2`, `iconsV1`, `iconsV2`. A bare default preset is also exported as `config`.
`unstableTokenV2: true` needs the theme CSS too
The preset does **not** define Design Token 2.0 variables. `unstable_createTailwindConfigTokenV2()` contains no plugin and no `addBase()` — it only emits class values that _reference_ `var(--charcoal-color-*)`. Something else has to define them.
Two disjoint namespaces are in play:
| Defined by | Names | Example | | ------------------------------------------------- | ----------------------------- | -------------------------------------------- | | The preset, when `cssVariablesV1` is on (default) | `--charcoal-<v1 token>` | `--charcoal-background1`, `--charcoal-text1` | | `@charcoal-ui/theme/css/v2/*.css` | `--charcoal-color-<v2 token>` | `--charcoal-color-container-default` |
`customPropertyToken()` produces `--charcoal-${id}`, so the v1 variables never satisfy a v2 reference. Turning on `unstableTokenV2` without loading the theme CSS gives you classes that resolve to nothing — colors silently disappear.
So with `unstableTokenV2: true`, do all three:
/* globals.css */ @import '@charcoal-ui/theme/css/v2/light.css'; @import '@charcoal-ui/theme/css/v2/dark.css'; @tailwind base; @tailwind components; @tailwind utilities;
<html lang="ja" class="ch-token-v2">
<body>
<div id="root"></div>
</body>
</html>`.ch-token-v2` gates the light-theme rules in `light.css`. Without it, no light rule matches and every v2 variable is undefined — the same failure described in setting-up-charcoal-css-variables.
If you stay on Design Token 1.0 (`unstableTokenV2` omitted), the preset's own `addBase()` supplies everything and the three `@tailwind` lines are all you need.
The preset replaces Tailwind's defaults
`createTailwindConfig()` writes `colors`, `spacing`, `width`, `gap`, `borderRadius`, `screens`, and `transitionDuration` at the **top level of `theme`**, not under `extend`. Tailwind's preset merge therefore _replaces_ the stock scales:
- `bg-red-500`, `text-blue-600` and the rest of the default palette stop existing. Only `transparent`, `current`, `black`, `white`, and charcoal tokens remain.
- `p-4` no longer means 1rem. Spacing keys are charcoal's px values: `0, 4, 8, 16, 24, 40, 64, 104, 168, 272, 440` — so `p-16` is 16px.
- `corePlugins: { lineHeight: false }` disables every `leading-*` utility.
If existing markup relies on stock Tailwind classes, add them back explicitly:
const colors = require('tailwindcss/colors')
module.exports = {
presets: [createTailwindConfig({/* … */})],
theme: { extend: { colors: { red: colors.red } } },
}Classes you get
<div className="bg-background1 text-text1 rounded-8 p-16">
<h2 className="typography-20">タイトル</h2>
<button className="ch-focus-ring bg-brand hover:bg-brand-hover active:bg-brand-press">
送信
</button>
</div>- Colors carry `DEFAULT` / `hover` / `press` / `disabled` variants — `bg-brand`, `bg-brand-hover`, …
- `typography-{12|14|16|20|32}` sets font-size and line-height together.
- `.ch-focus-ring` reproduces the focus ring used by `@charcoal-ui/react`.
- `w-col-span-{n}` and `w-{n}/12` come from the grid system.
Those names are Design Token 1.0. They keep working when `unstableTokenV2` is on, because the preset merges v2 entries on top of v1 rather than replacing them.
Design Token 2.0 adds five color groups — `background`, `border`, `container`, `icon`, `text` — folded so that a `default` key becomes the bare class:
color.container.default → bg-container color.container.hover → bg-container-hover color.text.default → text-text color.text.info.default → text-text-info color.text.negative.hover → text-text-negative-hover color.background.secondary → bg-background-secondary
Spacing splits into `component-*` and `layout-*` (`p-component-20`, `gap-layout-40`), radius becomes `rounded-{xs|s|m|l|xl|xxl|oval}`, and border colors take a `ch` prefix (`border-ch-secondary`).
To see exactly what your config produces, resolve it rather than guessing:
console.log(
require('tailwindcss/resolveConfig')(require('./tailwind.config.js')).theme
.colors,
)Dark theme
Tailwind's `dark:` variant is **not supported**. A charcoal token keeps its name across themes while its value changes, so `dark:bg-background
Other skills on charcoal.
More skills from other plugins.
banner-design
Design banners for social media, ads, website heroes, creative assets, and print. Multiple art direction options with optional…
impeccable
Use to design, redesign, critique, audit, polish or animate a frontend: websites, landing pages, dashboards, app UI, components,…
8-bit-orbit-video-temp…
Hyperframes-based video template for retro pixel deck motion design. Use when users want a high-fidelity, multi-scene…
diagram-design
Create branded architecture, architecture delta, IT current-state, flowchart, sequence, state machine, ER/data model, timeline,…
Questions about setting-up-charcoal-tailwind.
- Which coding agents can use setting-up-charcoal-tailwind?
- setting-up-charcoal-tailwind installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

