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 插件和无样式模式的预设。
在 PrimeVue 的无样式模式下,默认样式元素(如设计令牌和 css 类)被关闭,因此您可以通过直通属性完全控制组件的样式。当您想要通过包装 PrimeVue 组件来构建基于自定义设计的 UI 库,或者只是使用 Tailwind CSS 来样式化 PrimeVue 组件时,此功能非常有用。
无样式模式还像样式模式一样使用 preset 概念来定义主题。在样式模式下,预设是使用 CSS 变量实现的一组设计令牌,而在无样式模式下,预设是将 Tailwind CSS 类注入组件的直通配置对象。如果您希望忽略默认的样式模式主题化 api 并改用 Tailwind CSS 来样式化 PrimeVue UI 组件,请在独立的 Tailwind CSS 预设 项目网站上了解更多信息。
tailwindcss-primeui 是 PrimeTek 提供的官方插件,用于在 Prime UI 库(如 PrimeVue)和 Tailwind CSS 之间提供一流的集成。它旨在同时在样式和无样式模式下工作。例如,在样式模式下,语义颜色(如 primary 和 surfaces)被提供为 Tailwind 工具 e.g. 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] | 表面颜色调色板。 |
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 | 带有强调的次要文本颜色。 |
在样式模式下,Tailwind 工具可能无法覆盖默认样式,因为 CSS 特定性,有两种可能的解决方案。
使用 ! 作为前缀以强制执行样式。
<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 颜色调色板作为工具类。
使用 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>
该插件还添加了扩展动画工具,可与 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 | 淡入 0.15s 线性 |
animate-fadeout | 淡出 0.15s 线性 |
animate-slidedown | 向下滑动 0.45s 缓入缓出 |
animate-slideup | 向上滑动 0.45s 立方贝塞尔曲线 (0, 1, 0, 1) |
animate-scalein | 放大 0.15s 线性 |
animate-fadeinleft | 从左淡入 0.15s 线性 |
animate-fadeoutleft | 从左淡出 0.15s 线性 |
animate-fadeinright | 从右淡入 0.15s 线性 |
animate-fadeoutright | 从右淡出 0.15s 线性 |
animate-fadeinup | 从上淡入 0.15s 线性 |
animate-fadeoutup | 从上淡出 0.15s 线性 |
animate-fadeindown | 从下淡入 0.15s 线性 |
animate-fadeoutup | 从上淡出 0.15s 线性 |
animate-width | 宽度 0.15s 线性 |
animate-flip | 翻转 0.15s 线性 |
animate-flipup | 向上翻转 0.15s 线性 |
animate-flipleft | 淡入 0.15s 线性 |
animate-flipright | 向右翻转 0.15s 线性 |
animate-zoomin | 放大 0.15s 线性 |
animate-zoomindown | 从下放大 0.15s 线性 |
animate-zoominleft | 从左放大 0.15s 线性 |
animate-zoominright | 从右放大 0.15s 线性 |
animate-zoominup | 从上放大 0.15s 线性 |
类 | 属性 |
---|---|
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 |