PrimeVueとTailwind CSSの統合(スタイル付きモードとスタイルなしモードの両方)。
Tailwind CSSは、ユーティリティファースト設計に基づいた人気のCSSフレームワークです。コアは、独自のUI要素を構築するための、定義済みのCSSルールを持つ柔軟なCSSクラスを提供します。たとえば、Bootstrapのような意見の強いbtnクラスの代わりに、Tailwindはボタンを適用するためにbg-blue-500、rounded、p-4などのプリミティブなクラスを提供します。再利用可能なクラスのセットはTailwind CSSコンポーネントとしてグループ化することもでき、このアプローチを採用して、特にTailwind用にコンポーネントを構築するライブラリもいくつか存在します。
Tailwindは優れたCSSライブラリですが、Vue.jsと組み合わせた真に包括的なUIスイートを欠いています。そこでPrimeVueが登場し、幅広くアクセシビリティが高く機能豊富なUIコンポーネントライブラリを提供します。PrimeVueのコアはTailwind CSSに依存しませんが、primeui tailwindプラグインやスタイルなしモードのプリセットなど、必要な統合ポイントを提供しています。
PrimeVueのスタイルなしモードでは、デザイントークンやCSSクラスなどのデフォルトのスタイル要素が無効になるため、パススループロパティを使用してコンポーネントのスタイルを完全に制御できます。この機能は、PrimeVueコンポーネントをラップすることによってカスタムデザインに基づいて独自のUIライブラリを構築する場合、または単にTailwind CSSを使用してPrimeVueコンポーネントのスタイルを設定する場合に非常に役立ちます。
スタイルなしモードも、スタイル付きモードと同様にプリセットの概念を使用してテーマを定義します。スタイル付きモードでは、プリセットはCSS変数で実装されたデザイントークンのセットであるのに対し、スタイルなしモードでは、プリセットはTailwind CSSクラスをコンポーネントに挿入するためのパススルー設定オブジェクトです。デフォルトのスタイル付きモードのテーマAPIを無視して、代わりにTailwind CSSを使用してPrimeVue UIコンポーネントのスタイルを設定する場合は、スタンドアロンのTailwind CSSプリセットプロジェクトウェブサイトで詳細を確認してください。
tailwindcss-primeuiは、PrimeTekによる公式プラグインで、PrimeVueなどのPrime UIライブラリとTailwind CSSの高度な統合を提供します。スタイル付きモードとスタイルなしモードの両方で動作するように設計されています。たとえば、スタイル付きモードでは、プライマリーやサーフェスなどのセマンティックカラーはbg-primary、text-surface-500、text-muted-colorなどのTailwindユーティリティとして提供されます。
プラグインはnpmで利用可能です。
npm i tailwindcss-primeui
インストール後、Tailwind設定ファイルでプラグインを設定します。
// tailwind.config.js
module.exports = {
// ...
plugins: [require('tailwindcss-primeui')]
};
このプラグインは、新しいユーティリティセットを使用してデフォルトの設定を拡張します。すべてのバリアントとブレークポイントはサポートされています(例:dark:sm:hover:bg-primary)。
クラス | プロパティ |
---|---|
primary-[50-950] | プライマリーカラーパレット。 |
surface-[0-950] | サーフェスカラーパレット。 |
primary | デフォルトのプライマリーカラー。 |
primary-contrast | デフォルトのプライマリーコントラストカラー。 |
primary-emphasis | デフォルトのプライマリーエンファシスカラー。 |
border-surface | デフォルトのプライマリーエンファシスカラー。 |
bg-emphasis | エンファシス背景(例:ホバーされた要素)。 |
bg-highlight | ハイライト背景。 |
bg-highlight-emphasis | エンファシス付きのハイライト背景。 |
rounded-border | ボーダー半径。 |
text-color | エンファシス付きのテキストカラー。 |
text-color-emphasis | デフォルトのプライマリーエンファシスカラー。 |
text-muted-color | セカンダリテキストカラー。 |
text-muted-color-emphasis | エンファシス付きのセカンダリテキストカラー。 |
スタイル付きモードでは、CSSの特異性のために、Tailwindユーティリティでデフォルトのスタイルをオーバーライドできない場合があります。解決策は2つあります。
スタイルを強制するには、!をプレフィックスとして使用します。
<InputText placeholder="Overriden" class="!p-8" />
PrimeVue CSSレイヤーを有効にし、レイヤーを使用してTailwindスタイルの特異性を高めます。これにより、!プレフィックスは不要になります。
import PrimeVue from 'primevue/config';
import Aura from '@primevue/themes/aura';
const app = createApp(App);
app.use(PrimeVue, {
theme: {
preset: Aura,
options: {
cssLayer: {
name: 'primevue',
order: 'tailwind-base, primevue, tailwind-utilities'
}
}
}
});
@layer tailwind-base, primevue, tailwind-utilities;
@layer tailwind-base {
@tailwind base;
}
@layer tailwind-utilities {
@tailwind components;
@tailwind utilities;
}
PrimeVueとTailwind CSSの使用例。
ユーティリティクラスとしてのPrimeVueカラーパレット。
PrimeVueコンポーネントを含むフォームのレスポンシブレイアウトにTailwindユーティリティを使用する。
<div class="flex flex-col gap-6 w-full sm:w-auto">
<div class="flex flex-col sm:flex-row sm:items-center gap-6">
<div class="flex-auto">
<label for="firstname" class="block font-semibold mb-2">Firstname</label>
<InputText id="firstname" class="w-full" />
</div>
<div class="flex-auto">
<label for="lastname" class="block font-semibold mb-2">Lastname</label>
<InputText id="lastname" class="w-full" />
</div>
</div>
<div class="flex flex-col sm:flex-row sm:items-center gap-6">
<div class="flex-1">
<label for="date" class="block font-semibold mb-2">Date</label>
<DatePicker inputId="date" class="w-full" />
</div>
<div class="flex-1">
<label for="country" class="block font-semibold mb-2">Country</label>
<Select v-model="selectedCountry" inputId="country" :options="countries" optionLabel="name" placeholder="Select a Country" class="w-full">
<template #value="slotProps">
<div v-if="slotProps.value" class="flex items-center">
<img :alt="slotProps.value.label" src="https://primefaces.org/cdn/primevue/images/flag/flag_placeholder.png" :class="`mr-2 flag flag-${slotProps.value.code.toLowerCase()}`" style="width: 18px" />
<div>{{ slotProps.value.name }}</div>
</div>
<span v-else>
{{ slotProps.placeholder }}
</span>
</template>
<template #option="slotProps">
<div class="flex items-center">
<img :alt="slotProps.option.label" src="https://primefaces.org/cdn/primevue/images/flag/flag_placeholder.png" :class="`mr-2 flag flag-${slotProps.option.code.toLowerCase()}`" style="width: 18px" />
<div>{{ slotProps.option.name }}</div>
</div>
</template>
</Select>
</div>
</div>
<div class="flex-auto">
<label for="message" class="block font-semibold mb-2">Message</label>
<Textarea id="message" class="w-full" rows="4" />
</div>
</div>
カスタムUIを持つヘッドレスPrimeVueダイアログ。
<Button label="Login" icon="pi pi-user" @click="visible = true" />
<Dialog v-model:visible="visible" pt:root:class="!border-0 !bg-transparent" pt:mask:class="backdrop-blur-sm">
<template #container="{ closeCallback }">
<div class="flex flex-col px-8 py-8 gap-6 rounded-2xl" style="background-image: radial-gradient(circle at left top, var(--p-primary-400), var(--p-primary-700))">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="block mx-auto">
<path
d="M25.87 18.05L23.16 17.45L25.27 20.46V29.78L32.49 23.76V13.53L29.18 14.73L25.87 18.04V18.05ZM25.27 35.49L29.18 31.58V27.67L25.27 30.98V35.49ZM20.16 17.14H20.03H20.17H20.16ZM30.1 5.19L34.89 4.81L33.08 12.33L24.1 15.67L30.08 5.2L30.1 5.19ZM5.72 14.74L2.41 13.54V23.77L9.63 29.79V20.47L11.74 17.46L9.03 18.06L5.72 14.75V14.74ZM9.63 30.98L5.72 27.67V31.58L9.63 35.49V30.98ZM4.8 5.2L10.78 15.67L1.81 12.33L0 4.81L4.79 5.19L4.8 5.2ZM24.37 21.05V34.59L22.56 37.29L20.46 39.4H14.44L12.34 37.29L10.53 34.59V21.05L12.42 18.23L17.45 26.8L22.48 18.23L24.37 21.05ZM22.85 0L22.57 0.69L17.45 13.08L12.33 0.69L12.05 0H22.85Z"
fill="var(--p-primary-700)"
/>
<path
d="M30.69 4.21L24.37 4.81L22.57 0.69L22.86 0H26.48L30.69 4.21ZM23.75 5.67L22.66 3.08L18.05 14.24V17.14H19.7H20.03H20.16H20.2L24.1 15.7L30.11 5.19L23.75 5.67ZM4.21002 4.21L10.53 4.81L12.33 0.69L12.05 0H8.43002L4.22002 4.21H4.21002ZM21.9 17.4L20.6 18.2H14.3L13 17.4L12.4 18.2L12.42 18.23L17.45 26.8L22.48 18.23L22.5 18.2L21.9 17.4ZM4.79002 5.19L10.8 15.7L14.7 17.14H14.74H15.2H16.85V14.24L12.24 3.09L11.15 5.68L4.79002 5.2V5.19Z"
fill="var(--p-primary-200)"
/>
</svg>
<div class="inline-flex flex-col gap-2">
<label for="username" class="text-primary-50 font-semibold">Username</label>
<InputText id="username" class="!bg-white/20 !border-0 !p-4 !text-primary-50 w-80"></InputText>
</div>
<div class="inline-flex flex-col gap-2">
<label for="password" class="text-primary-50 font-semibold">Password</label>
<InputText id="password" class="!bg-white/20 !border-0 !p-4 !text-primary-50 w-80" type="password"></InputText>
</div>
<div class="flex items-center gap-4">
<Button label="Cancel" @click="closeCallback" text class="!p-4 w-full !text-primary-50 !border !border-white/30 hover:!bg-white/10"></Button>
<Button label="Sign-In" @click="closeCallback" text class="!p-4 w-full !text-primary-50 !border !border-white/30 hover:!bg-white/10"></Button>
</div>
</div>
</template>
</Dialog>
このプラグインは、styleclassおよびanimateonscrollディレクティブで使用できる拡張アニメーションユーティリティも追加します。
<Select v-model="animation" :options="animations" placeholder="Select One" class="w-full sm:w-44" />
<div class="py-8 overflow-hidden">
<div :class="`rounded-border bg-primary w-16 h-16 mx-auto animate-${animation} animate-once animate-duration-1000`"></div>
</div>
クラス | プロパティ |
---|---|
animate-fadein | fadein 0.15s linear |
animate-fadeout | fadeout 0.15s linear |
animate-slidedown | slidedown 0.45s ease-in-out |
animate-slideup | slideup 0.45s cubic-bezier(0, 1, 0, 1) |
animate-scalein | scalein 0.15s linear |
animate-fadeinleft | fadeinleft 0.15s linear |
animate-fadeoutleft | fadeoutleft 0.15s linear |
animate-fadeinright | fadeinright 0.15s linear |
animate-fadeoutright | fadeoutright 0.15s linear |
animate-fadeinup | fadeinup 0.15s linear |
animate-fadeoutup | fadeoutup 0.15s linear |
animate-fadeindown | fadeindown 0.15s linear |
animate-fadeoutup | fadeoutup 0.15s linear |
animate-width | width 0.15s linear |
animate-flip | flip 0.15s linear |
animate-flipup | flipup 0.15s linear |
animate-flipleft | fadein 0.15s linear |
animate-flipright | flipright 0.15s linear |
animate-zoomin | zoomin 0.15s linear |
animate-zoomindown | zoomindown 0.15s linear |
animate-zoominleft | zoominleft 0.15s linear |
animate-zoominright | zoominright 0.15s linear |
animate-zoominup | zoominup 0.15s linear |
クラス | プロパティ |
---|---|
animate-duration-0 | animation-duration: 0s |
animate-duration-75 | animation-duration: 75ms |
animate-duration-100 | animation-duration: 100ms |
animate-duration-200 | animation-duration: 200ms |
animate-duration-300 | animation-duration: 300ms |
animate-duration-400 | animation-duration: 400ms |
animate-duration-500 | animation-duration: 500ms |
animate-duration-700 | animation-duration: 700ms |
animate-duration-1000 | animation-duration: 1000ms |
animate-duration-2000 | animation-duration: 2000ms |
animate-duration-3000 | animation-duration: 300ms |
クラス | プロパティ |
---|---|
animate-delay-none | animation-duration: 0s |
animate-delay-75 | animation-delay: 75ms |
animate-delay-100 | animation-delay: 100ms |
animate-delay-150 | animation-delay: 150ms |
animate-delay-200 | animation-delay: 200ms |
animate-delay-300 | animation-delay: 300ms |
animate-delay-400 | animation-delay: 400ms |
animate-delay-500 | animation-delay: 500ms |
animate-delay-700 | animation-delay: 700ms |
animate-delay-1000 | animation-delay: 1000ms |
クラス | プロパティ |
---|---|
animate-infinite | animation-iteration-count: infinite |
animate-once | animation-iteration-count: 1 |
animate-twice | animation-iteration-count: 2 |
クラス | プロパティ |
---|---|
animate-normal | animation-direction: normal |
animate-reverse | animation-direction: reverse |
animate-alternate | animation-direction: alternate |
animate-alternate-reverse | animation-direction: alternate-reverse |
クラス | プロパティ |
---|---|
animate-ease-linear | animation-timing-function: linear |
animate-ease-in | animation-timing-function: cubic-bezier(0.4, 0, 1, 1) |
animate-ease-out | animation-timing-function: cubic-bezier(0, 0, 0.2, 1) |
animate-ease-in-out | animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1) |
クラス | プロパティ |
---|---|
animate-fill-none | animation-fill-mode: normal |
animate-fill-forwards | animation-fill-mode: forwards |
animate-fill-backwards | animation-fill-mode: backwards |
animate-fill-both | animation-fill-mode: both |
クラス | プロパティ |
---|---|
animate-running | animation-play-state: running |
animate-paused | animation-play-state: paused |
クラス | プロパティ |
---|---|
backface-visible | backface-visibility: visible |
backface-hidden | backface-visibility: hidden |