# <span style="font-size: 75%;">Tailwind CSSプラグインをv4に移行した</span> [Meguro.css #12 @ oRo](https://megurocss.connpass.com/event/354285/) [くのきみ](https://blog.kimiaki.space/about/) --- どんな Tailwind CSS プラグインなのか --- ## [![Jumpu UI](https://github.com/tuqulore/jumpu-ui/raw/main/public/logo.svg)](https://jumpu-ui.pages.dev/) - 汎用的なデザインシステム - デザイントークンとコンポーネントの実装をTailwind CSSプラグインで提供している - [株式会社ツクロア](https://tuqulore.com/)のメンバーで開発しているオープンソースソフトウェア --- 詳細は[Buttonコンポーネント](https://jumpu-ui.pages.dev/components/button.html)の ドキュメントなどみてもらえれば ![Buttonコンポーネントのドキュメントをブラウザーで開いた様子。Buttonのデフォルト、リンクボタンの例が見た目とコード付きで示されている。](https://hackmd.io/_uploads/r1b9YT8zlx.png) --- Tailwind CSS v3でプラグインが どのように実装されていたか --- [Plugin API](https://v3.tailwindcss.com/docs/plugins)を使ってコンポーネントを実装していた ```javascript= module.exports = plugin.withOptions( () => { return ({ addComponents, theme }) => { const { base, disabled } = buttonStyle(theme); addComponents({ [`.${theme("jumpu.prefix")}button`]: { ...base, backgroundColor: theme("colors.primary.700"), color: "#fff", transition: "30ms filter cubic-bezier(0, 0, 0.12, 1)", "&:hover": { filter: "brightness(90%)", }, "&:active": { filter: "brightness(75%)", }, "&[disabled]": disabled, }, }); }; }, () => ({ theme }), ); ``` [ソースコード](https://github.com/tuqulore/jumpu-ui/blob/v1.0.1/packages/tailwindcss/button.js) --- Tailwind CSS v4リリース :tada: [Tailwind CSS v4.0 - Tailwind CSS](https://tailwindcss.com/blog/tailwindcss-v4) --- [Tailwind CSSの設定がCSSで書ける](https://tailwindcss.com/blog/tailwindcss-v4#css-first-configuration)ようになった! ```css= @import "tailwindcss"; @theme { --font-display: "Satoshi", "sans-serif"; --breakpoint-3xl: 1920px; --color-avocado-100: oklch(0.99 0 0); --color-avocado-200: oklch(0.98 0.04 113.22); --color-avocado-300: oklch(0.94 0.11 115.03); --color-avocado-400: oklch(0.92 0.19 114.08); --color-avocado-500: oklch(0.84 0.18 117.33); --color-avocado-600: oklch(0.53 0.12 118.34); --ease-fluid: cubic-bezier(0.3, 0, 0, 1); --ease-snappy: cubic-bezier(0.2, 0, 0, 1); /* ... */ } ``` リンク先から引用 --- Tailwind CSS の プラグインエコシステムってどうなるの…? ```javascript // Tailwind CSS v3 では... const jumpu = require("@jumpu-ui/tailwindcss"); module.exports = { content: ["src/**/*.tsx"], plugins: [...jumpu], }; ``` --- 後方互換のために [@pluginディレクティブ](https://tailwindcss.com/docs/functions-and-directives#plugin-directive)が提供されてはいる > Use the @plugin directive to load a legacy JavaScript-based plugin: > > _リンク先から引用_ ```css= @plugin "@tailwindcss/typography"; ``` --- プラグインで提供されうるもの: - カスタム[ユーティリティー](https://tailwindcss.com/docs/styling-with-utility-classes) - カスタム[バリアント](https://tailwindcss.com/docs/hover-focus-and-other-states) - コンポーネント - それらの設定でのカスタマイズ --- v4でのカスタムスタイルの書き方は [Adding custom styles - Core concepts - Tailwind CSS](https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes)を読むと書いてある --- カスタムユーティリティー ```css= @utility content-auto { content-visibility: auto; } ``` https://tailwindcss.com/docs/adding-custom-styles#adding-custom-utilities より引用 \@utilityディレクティブが提供されている --- カスタムバリアント ```css= @custom-variant theme-midnight { &:where([data-theme="midnight"] *) { @slot; } } ``` https://tailwindcss.com/docs/adding-custom-styles#adding-custom-variants より引用 \@custom-variantディレクティブが提供されている --- コンポーネント ```css= @layer components { .card { background-color: var(--color-white); border-radius: var(--rounded-lg); padding: var(--spacing-6); box-shadow: var(--shadow-xl); } } ``` https://tailwindcss.com/docs/adding-custom-styles#adding-component-classes より引用 componentsカスケードレイヤーにCSSを記述する --- 設定でのカスタマイズ - [テーマ変数](https://tailwindcss.com/docs/theme#what-are-theme-variables)を定義 - [var()関数](https://developer.mozilla.org/ja/docs/Web/CSS/var)で参照 --- というわけで… --- [Migrate to Tailwind v4 & Use VitePress for documentation by knokmki612 · Pull Request #665 · tuqulore/jumpu-ui](https://github.com/tuqulore/jumpu-ui/pull/665)で v4のカスタムスタイルの書き方に移行した! --- before (Buttonコンポーネント): ```javascript= module.exports = plugin.withOptions( () => { return ({ addComponents, theme }) => { const { base, disabled } = buttonStyle(theme); addComponents({ [`.${theme("jumpu.prefix")}button`]: { ...base, backgroundColor: theme("colors.primary.700"), color: "#fff", transition: "30ms filter cubic-bezier(0, 0, 0.12, 1)", "&:hover": { filter: "brightness(90%)", }, "&:active": { filter: "brightness(75%)", }, "&[disabled]": disabled, }, }); }; }, () => ({ theme }), ); ``` [ソースコード](https://github.com/tuqulore/jumpu-ui/blob/v1.0.1/packages/tailwindcss/button.js) --- after (Buttonコンポーネント): ```css= .jumpu-button { appearance: none; border-radius: var(--radius-md); display: inline-block; padding-block: calc(var(--spacing-relative) * 2.5); padding-inline: calc(var(--spacing-relative) * 5); text-decoration: none; background-color: var(--color-primary-700); color: var(--color-white); transition-duration: 30ms; transition-property: filter; transition-timing-function: cubic-bezier(0, 0, 0.12, 1); &:hover { filter: brightness(90%); } &:active { filter: brightness(75%); } &[role="button"] { cursor: default; } &[disabled] { color: var(--color-white); background-color: var(--color-gray-300); border-color: var(--color-gray-300); &:hover { filter: none; box-shadow: none; } } } ``` [ソースコード](https://github.com/tuqulore/jumpu-ui/blob/v2.0.0-alpha.0/packages/tailwindcss/src/components/button.css) --- v4のカスタムスタイルの書き方で書いたスタイルはどうやって配布するの…? --- これは「こうなってるといいな~」で試したら 期待通りだった …ので結論だけ書きますが… (いかにしてそうなったかまでは調べていない) (どう配布すればよいかドキュメントがあるようなら有識者教えてください) --- Node.jsによるESM解決アルゴリズム https://nodejs.org/api/esm.html#resolution-and-loading-algorithm これに準拠(されると期待)して ESM形式のNPMパッケージとして配布 --- 具体的には: ```jsonc { "name": "@jumpu-ui/tailwindcss", // ... "exports": { ".": { "default": "./src/style.css", "browser": "./dist/style.css" }, "./*": { "default": "./src/*", "browser": "./dist/*" }, "./package.json": "./package.json" }, // ... "type": "module" } ``` カスタムスタイルが記述されたCSSファイルを[exportsフィールドのエントリーポイントに指定](https://nodejs.org/api/packages.html#package-entry-points) --- 配布しているカスタムスタイルの Tailwind CSS v4の設定での読み込みかた ```css @import "tailwindcss"; @import "@jumpu-ui/tailwindcss"; ``` \@import ルールを使うだけ! --- 試した範囲では… - @tailwindcss/viteで導入した環境: [OK](https://github.com/tuqulore/jumpu-ui/blob/main/packages/docs/.vitepress/theme/style.css#L1-L7) - @tailwindcss/postcssで導入した環境: [OK](https://github.com/tuqulore/website-boilerplate/blob/726d362af7de4048f56ac7d00a5697b691b48c82/src/main.css#L1-L4) やったー :raised_hands: --- v4に移行したメリット - Stylelintの[カスタムシンタックス](https://stylelint.io/developer-guide/syntaxes/)を書かなくてもStylelintでコンポーネントのスタイルが検査できるようになった! - Tailwind CSS v4がCSS-Firstな設計になったおかげ - 過去にこれが原因で導入を[断念](https://github.com/tuqulore/jumpu-ui/pull/618#discussion_r1797287744)した --- まとめ - Tailwind CSS v4はプラグインで提供していた スタイルがCSSで書けるようになった - ESM形式のNPMパッケージとしてスタイルを配布・利用できるようになった
{"description":"くのきみ @knokmki612","title":"Tailwind CSSプラグインをv4に対応した","contributors":"[{\"id\":\"f14001d4-975b-4504-b1d2-003ba7c0f49e\",\"add\":8923,\"del\":1521}]"}
    235 views