Tailwind UI 中的所有元件都設計用於最新版本的 Tailwind CSS,目前為 Tailwind CSS v4.0。為了確保您使用的是最新版本的 Tailwind,請透過 npm 更新
npm install tailwindcss@latest
如果您是 Tailwind CSS 的新手,您也會需要閱讀 Tailwind CSS 文件,以便充分利用 Tailwind UI。
我們在所有 Tailwind UI 範例中都使用了 Inter,因為它是 UI 設計的優美字體,並且完全開源且免費。使用自訂字體很好,因為它可以讓我們在所有瀏覽器和作業系統上使元件看起來相同。
您當然可以在自己的專案中使用任何您想要的字體,但如果您想使用 Inter,最簡單的方法是先透過 CDN 新增它
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
然後將 "InterVariable" 新增到您的 Tailwind 主題中的 "sans" 字體系列
@theme {
--font-sans: InterVariable, sans-serif;
}
如果您仍在使用 Tailwind CSS v3.x,您可以在 tailwind.config.js
檔案中執行此操作
const defaultTheme = require('tailwindcss/defaultTheme')
module.exports = {
theme: {
extend: {
fontFamily: {
sans: ['InterVariable', '...defaultTheme.fontFamily.sans'],
},
},
},
// ...
}
Tailwind UI 中的所有元件都以三種格式提供:React、Vue 和 vanilla HTML。
React 和 Vue 範例是完全開箱即用的,並由 Headless UI 提供支援,這是一個我們設計的無樣式元件庫,可與 Tailwind CSS 完美整合。
vanilla HTML 範例不包含任何 JavaScript,適用於喜歡自己編寫任何必要 JavaScript 的人,或者想要與 React 或 Vue 以外的框架整合的人。
絕大多數元件根本不需要 JavaScript,並且完全可以開箱即用,但像是下拉選單、對話框等互動式元件,需要您編寫一些 JS 來使其以您期望的方式運作。
在這些情況下,我們在 HTML 中提供了一些簡單的註解,以說明不同狀態下需要使用的類別(例如切換開關開啟或關閉),或我們建議用於在螢幕上轉場元素的類別(例如開啟對話框)。
我們已盡力確保 Tailwind UI 中的所有標記盡可能具有可及性,但是當您建置互動式元件時,許多可及性最佳實務只能透過 JavaScript 實作。
例如
aria-expanded="true"
,當切換開關開啟時設定 aria-checked
為 true,當在自動完成選單中導覽選項時更新 aria-activedescendant
等等。)如果您正在使用 Tailwind UI 與 React 或 Vue,所有這些複雜性都會由 Headless UI 自動為您處理。但如果您要自行提供 JS,當您加入互動行為時,您必須遵循無障礙的最佳實務。
若要深入了解如何建立無障礙的 UI 組件,我們建議您研究 W3C 發佈的 WAI-ARIA 製作實務。
當一個元素需要根據某種狀態套用不同的類別時(例如切換開關的開啟或關閉),我們會將每個狀態的類別列在元素正上方的註解中
<!-- On: "bg-indigo-600", Off: "bg-gray-200" -->
<span aria-checked="false" class="bg-gray-200 relative inline-block shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline" role="checkbox" tabindex="0">
<!-- On: "translate-x-5", Off: "translate-x-0" -->
<span aria-hidden="true" class="translate-x-0 inline-block size-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"></span>
</span>
我們提供的 HTML 始終預先配置為其中一個已定義的狀態,而當切換狀態時需要變更的類別始終位於類別清單的最開頭,方便您尋找。
舉例來說,若要調整此 HTML 以使用 Alpine.js,您可以根據 x-data
中宣告的某些狀態,使用 :class
指令有條件地套用正確的類別
<span
x-data="{ isOn: false }"
@click="isOn = !isOn"
:aria-checked="isOn"
:class="{'bg-indigo-600': isOn, 'bg-gray-200': !isOn }"
class="bg-gray-200 relative inline-block shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none focus:shadow-outline"
role="checkbox"
tabindex="0"
>
<span
aria-hidden="true"
:class="{'translate-x-5': isOn, 'translate-x-0': !isOn }"
class="translate-x-0 inline-block size-5 rounded-full bg-white shadow transform transition ease-in-out duration-200"
></span>
</span>
我們在此包含了一個基本的點擊處理器來演示基本概念,但當您建立像這樣的組件時,請參考 WAI-ARIA 製作實務,以確保您實作了所有必要的鍵盤互動,並正確管理任何必要的 ARIA 屬性。
對於應動態顯示或隱藏的元素(例如下拉選單中的面板),我們會在動態元素正上方的註解中包含建議的過渡樣式
<div class="relative ...">
<button type="button" class="...">
Options
</button>
<!--
Show/hide this element based on the dropdown state
Entering: "transition ease-out duration-100 transform"
From: "opacity-0 scale-95"
To: "opacity-100 scale-100"
Closing: "transition ease-in duration-75 transform"
From: "opacity-100 scale-100"
To: "opacity-0 scale-95"
-->
<div class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg">
<div class="rounded-md bg-white shadow-xs">
<!-- Snipped -->
</div>
</div>
</div>
舉例來說,若要調整此 HTML 以使用 Alpine.js,您可以使用 x-transition
指令,在過渡週期的每個點套用正確的類別
<div x-data="{ isOpen: false }" class="relative ...">
<button type="button" @click="isOpen = !isOpen" class="...">
Options
</button>
<div
x-show="isOpen"
x-transition:enter="transition ease-out duration-100 transform"
x-transition:enter-start="opacity-0 scale-95"
x-transition:enter-end="opacity-100 scale-100"
x-transition:leave="transition ease-in duration-75 transform"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg"
>
<div class="rounded-md bg-white shadow-xs">
<!-- Snipped -->
</div>
</div>
</div>
我們在此包含了一個基本的點擊處理器來演示基本概念,但當您建立像這樣的組件時,請參考 WAI-ARIA 製作實務,以確保您實作了所有必要的鍵盤互動,並正確管理任何必要的 ARIA 屬性。
由於 Tailwind UI 中包含的原始 HTML 範例無法利用迴圈之類的功能,因此存在許多重複的情況,但在真實專案中,HTML 是從某些動態資料來源產生的,實際上不會出現這種情況。例如,我們可能會提供一個包含 5 個清單項目的清單組件,每個清單項目都重複了所有的工具類別,而在您的專案中,您實際上是透過迴圈處理一個陣列來產生這些清單項目。
當您將我們的範例調整為您自己的專案時,我們建議您根據需要建立可重複使用的模板部分或 JS 組件,以管理任何重複的情況。
在 Tailwind CSS 網站上的 「提取組件」文件中了解更多資訊。
React 的 Tailwind UI 依賴 Headless UI 來驅動所有互動行為,並依賴 Heroicons 來提供圖示,因此您需要將這兩個函式庫新增至您的專案中
npm install @headlessui/react @heroicons/react
這些函式庫和 Tailwind UI 本身都需要 React >= 16.
所有 React 範例都以簡單的單個組件形式提供,並且不對您希望如何分解、您想要公開的 prop API 或您從哪裡取得任何資料做出任何假設。
某些資料已被提取到基本的本地變數中,只是為了清理重複的部分,並使程式碼更容易閱讀和理解,但我們盡量減少了操作,以避免強制執行任何不必要的嚴格意見。
當您為自己的專案調整 Tailwind UI 中的程式碼時,您應該根據需要將範例分解為較小的組件,以達到您的專案所需的任何重複使用程度。
例如,您可以從這個堆疊清單組件開始
const people = [
{
name: 'Calvin Hawkins',
email: 'calvin.hawkins@example.com',
image:
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Kristen Ramos',
email: 'kristen.ramos@example.com',
image:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Ted Fox',
email: 'ted.fox@example.com',
image:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
]
export default function Example() {
return (
<ul className="divide-y divide-gray-200">
{people.map((person) => (
<li key={person.email} className="py-4 flex">
<img className="size-10 rounded-full" src={person.image} alt="" />
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">{person.name}</p>
<p className="text-sm text-gray-500">{person.email}</p>
</div>
</li>
))}
</ul>
)
}
在為您自己的專案調整內容、將其分解為單獨的組件並連接資料來源後,它可能看起來更像這樣
function HockeyTeamItem({ team }) {
return (
<li className="py-4 flex">
<img className="size-10 rounded-full" src={team.logo} alt="" />
<div className="ml-3">
<p className="text-sm font-medium text-gray-900">{team.name}</p>
<p className="text-sm text-gray-500">{team.city}</p>
</div>
</li>
)
}
export default function HockeyTeamList({ teams }) {
return (
<ul className="divide-y divide-gray-200">
{teams.map((team) => <HockeyTeamItem key={team.id} team={team} />)}
</ul>
)
}
Tailwind UI 更像是一組藍圖、模式和想法,而不是僵化的 UI 工具包。您最終得到的程式碼是您自己的,您可以隨意處理它。
Vue 的 Tailwind UI 依賴 Headless UI 來驅動所有互動行為,並依賴 Heroicons 來提供圖示,因此您需要將這兩個函式庫新增至您的專案中
npm install @headlessui/vue @heroicons/vue
這些函式庫和 Tailwind UI 本身都需要 Vue 3+。我們目前不提供對 Vue 2 的支援。
所有 Vue 範例都以簡單的單個組件形式提供,並且不對您希望如何分解、您想要公開的 prop API 或您從哪裡取得任何資料做出任何假設。
某些資料已被提取到基本的本地變數中,只是為了清理重複的部分,並使程式碼更容易閱讀和理解,但我們盡量減少了操作,以避免強制執行任何不必要的嚴格意見。
當您為自己的專案調整 Tailwind UI 中的程式碼時,您應該根據需要將範例分解為較小的組件,以達到您的專案所需的任何重複使用程度。
例如,您可以從這個堆疊清單組件開始
<template>
<ul class="divide-y divide-gray-200">
<li v-for="person in people" :key="person.email" class="py-4 flex">
<img class="size-10 rounded-full" :src="person.image" alt="" />
<div class="ml-3">
<p class="text-sm font-medium text-gray-900">{{ person.name }}</p>
<p class="text-sm text-gray-500">{{ person.email }}</p>
</div>
</li>
</ul>
</template>
<script>
const people = [
{
name: 'Calvin Hawkins',
email: 'calvin.hawkins@example.com',
image:
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Kristen Ramos',
email: 'kristen.ramos@example.com',
image:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
name: 'Ted Fox',
email: 'ted.fox@example.com',
image:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
]
export default {
setup() {
return {
people,
}
},
}
</script>
在為您自己的專案調整內容、將其分解為單獨的組件並連接資料來源後,它可能看起來更像這樣
<!-- HockeyTeamList.vue -->
<template>
<ul class="divide-y divide-gray-200">
<HockeyTeamItem v-for="team in teams" :key="team.id" :team="team"/>
</ul>
</template>
<script>
export default {
props: {
teams: Array
},
}
</script>
<!-- HockeyTeamListItem.vue -->
<template>
<li class="py-4 flex">
<img class="size-10 rounded-full" :src="team.logo" alt="" />
<div class="ml-3">
<p class="text-sm font-medium text-gray-900">{{ team.name }}</p>
<p class="text-sm text-gray-500">{{ team.city }}</p>
</div>
</li>
</template>
<script>
export default {
props: {
team: Object
},
}
</script>
Tailwind UI 更像是一組藍圖、模式和想法,而不是僵化的 UI 工具包。您最終得到的程式碼是您自己的,您可以隨意處理它。
我們在 Tailwind UI 中使用的所有圖示都來自 Heroicons,這是一個免費的 MIT 授權圖示集,是我們在開始開發 Tailwind UI 時自行設計和開發的。
Tailwind UI 中的圖片幾乎全部來自 Unsplash。如果您需要可免費使用的攝影作品來用於您的專案,這是一個很棒的資源。
Tailwind UI 中的某些範例使用了來自 Lucid Illustrations 免費套件中的插圖,該套件由 Pixsellz 提供。您可以在 他們的網站上取得完整的插圖集,並查看他們的其他設計資源。
我們已停止提供 Figma 素材,以便我們可以專注於使用 Tailwind CSS 建立更多出色的範例。
我們過去曾為 Tailwind UI 提供 Figma 素材,但維護它們的工作量非常巨大,而且很少有人使用它們。我們做出了非常艱難的決定,停止提供它們,以便我們可以將更多時間花在實際程式碼上,我們認為這才是我們可以提供最大價值的地方。
Tailwind UI 的客戶可以下載我們發佈的最終 Figma 檔案,但請注意Figma 檔案不會收到更新,並且不包含 2021 年 7 月 14 日之後發佈的任何範例。