PrimeVue 和 Tailwind CSS 在样式和无样式模式下的集成。
Tailwind CSS 是一个流行的 CSS 框架,基于实用优先的设计。其核心提供了灵活的 CSS 类,带有预定义的 CSS 规则,用于构建您自己的 UI 元素。例如,与 Bootstrap 中带有主观的 btn 类不同,Tailwind 提供了像 bg-blue-500、rounded 和 p-4 这样的原始类来应用按钮样式。一组可重用的类也可以组合为 Tailwind CSS 组件,甚至有一些库采用这种方法专门为 Tailwind 构建组件。
Tailwind 是一个出色的 CSS 库,但当与 Vue.js 结合使用时,它缺乏一个真正的综合 UI 套件,这就是 PrimeVue 的用武之地,它提供了一个范围广泛、高度可访问且功能丰富的 UI 组件库。PrimeVue 的核心不依赖于 Tailwind CSS,相反,我们提供了必要的集成点,例如 primeui tailwind 插件和无样式模式的 Tailwind 版本。
PrimeTek 在 无样式模式下,基于 @apply 指令和 IntelliSense 支持,提供了整个 PrimeVue UI 套件的 Tailwind CSS 版本。请访问 PrimeVue 的 Tailwind 版本,获取文档、演示和其他资源。
tailwindcss-primeui 是 PrimeTek 的官方插件,用于提供像 PrimeVue 和 Tailwind CSS 这样的 Prime UI 库之间的首要集成。它被设计为在样式和无样式模式下都能工作。例如,在样式模式下,诸如主要和表面之类的语义颜色作为 Tailwind 实用程序提供,例如 bg-primary、text-surface-500、text-muted-color。
插件可在 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] | 表面颜色调色板。 |
主要 | 默认主要颜色。 |
主要对比 | 默认主要对比色。 |
主要强调 | 默认主要强调色。 |
边框表面 | 默认主要强调色。 |
背景强调 | 强调背景,例如悬停的元素。 |
背景高亮 | 高亮背景。 |
背景高亮强调 | 带有强调的高亮背景。 |
圆角边框 | 边框半径。 |
文本颜色 | 带有强调的文本颜色。 |
文本颜色强调 | 默认主要强调色。 |
文本静音颜色 | 辅助文本颜色。 |
文本静音颜色强调 | 带有强调的辅助文本颜色。 |
在样式模式下,由于 css 特异性,Tailwind 实用程序可能无法覆盖默认样式,有两种可能的解决方案。
使用 ! 作为前缀来强制样式。
<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 调色板作为实用程序类。
<div class="flex flex-col gap-12">
<div class="flex gap-6 flex-wrap">
<div class="rounded-border p-4 border border-transparent flex items-center justify-center bg-primary hover:bg-primary-emphasis text-primary-contrast font-medium flex-auto transition-colors">primary</div>
<div class="rounded-border p-4 border border-transparent flex items-center justify-center bg-highlight hover:bg-highlight-emphasis font-medium flex-auto transition-colors">highlight</div>
<div class="rounded-border p-4 border border-surface flex items-center justify-center text-muted-color hover:text-color hover:bg-emphasis font-medium flex-auto transition-colors">box</div>
</div>
</div>
使用 Tailwind 实用程序为带有 PrimeVue 组件的表单进行响应式布局。
<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>
<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>
类 | 属性 |
---|---|
动画-淡入 | 淡入 0.15 秒线性 |
动画-淡出 | 淡出 0.15 秒线性 |
动画-向下滑动 | 向下滑动 0.45 秒缓入缓出 |
动画-向上滑动 | 向上滑动 0.45 秒三次贝塞尔曲线(0, 1, 0, 1) |
动画-放大 | 放大 0.15 秒线性 |
动画-从左淡入 | 从左淡入 0.15 秒线性 |
动画-从左淡出 | 从左淡出 0.15 秒线性 |
动画-从右淡入 | 从右淡入 0.15 秒线性 |
动画-从右淡出 | 从右淡出 0.15 秒线性 |
动画-从上淡入 | 从上淡入 0.15 秒线性 |
动画-从上淡出 | 从上淡出 0.15 秒线性 |
动画-从下淡入 | 从下淡入 0.15 秒线性 |
动画-从上淡出 | 从上淡出 0.15 秒线性 |
动画-宽度 | 宽度 0.15 秒线性 |
动画-翻转 | 翻转 0.15 秒线性 |
动画-向上翻转 | 向上翻转 0.15 秒线性 |
动画-向左翻转 | 淡入 0.15 秒线性 |
动画-向右翻转 | 向右翻转 0.15 秒线性 |
动画-放大 | 放大 0.15 秒线性 |
动画-向下放大 | 向下放大 0.15 秒线性 |
动画-从左放大 | 从左放大 0.15 秒线性 |
动画-从右放大 | 从右放大 0.15 秒线性 |
动画-从上放大 | 从上放大 0.15 秒线性 |
类 | 属性 |
---|---|
动画-持续时间-0 | 动画-持续时间:0 秒 |
动画-持续时间-75 | 动画-持续时间:75 毫秒 |
动画-持续时间-100 | 动画-持续时间:100 毫秒 |
动画-持续时间-200 | 动画-持续时间:200 毫秒 |
动画-持续时间-300 | 动画-持续时间:300 毫秒 |
动画-持续时间-400 | 动画-持续时间:400 毫秒 |
动画-持续时间-500 | 动画-持续时间:500 毫秒 |
动画-持续时间-700 | 动画-持续时间:700 毫秒 |
动画-持续时间-1000 | 动画-持续时间:1000 毫秒 |
动画-持续时间-2000 | 动画-持续时间:2000 毫秒 |
动画-持续时间-3000 | 动画-持续时间:300 毫秒 |
类 | 属性 |
---|---|
动画-延迟-无 | 动画-持续时间:0 秒 |
动画-延迟-75 | 动画-延迟:75 毫秒 |
动画-延迟-100 | 动画-延迟:100 毫秒 |
动画-延迟-150 | 动画-延迟:150 毫秒 |
动画-延迟-200 | 动画-延迟:200 毫秒 |
动画-延迟-300 | 动画-延迟:300 毫秒 |
动画-延迟-400 | 动画-延迟:400 毫秒 |
动画-延迟-500 | 动画-延迟:500 毫秒 |
动画-延迟-700 | 动画-延迟:700 毫秒 |
动画-延迟-1000 | 动画-延迟:1000 毫秒 |
类 | 属性 |
---|---|
无限次动画 | animation-iteration-count: infinite |
动画一次 | animation-iteration-count: 1 |
动画两次 | animation-iteration-count: 2 |
类 | 属性 |
---|---|
正常方向动画 | animation-direction: normal |
反向动画 | animation-direction: reverse |
交替动画 | animation-direction: alternate |
反向交替动画 | animation-direction: alternate-reverse |
类 | 属性 |
---|---|
线性缓动动画 | animation-timing-function: linear |
缓入动画 | animation-timing-function: cubic-bezier(0.4, 0, 1, 1) |
缓出动画 | animation-timing-function: cubic-bezier(0, 0, 0.2, 1) |
缓入缓出动画 | animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1) |
类 | 属性 |
---|---|
不填充动画 | animation-fill-mode: normal |
向前填充动画 | animation-fill-mode: forwards |
向后填充动画 | animation-fill-mode: backwards |
双向填充动画 | animation-fill-mode: both |
类 | 属性 |
---|---|
运行动画 | animation-play-state: running |
暂停动画 | animation-play-state: paused |
类 | 属性 |
---|---|
背面可见 | backface-visibility: visible |
背面隐藏 | backface-visibility: hidden |