在建構現代網路應用程式時,最大的痛點之一是建立自訂元件,例如選單、下拉式選單、切換開關、模組、標籤頁、單選按鈕群組 — 這些元件在專案與專案之間非常相似,但從來都不完全相同。
您可以使用現成的套件,但它們通常與自己提供的樣式緊密耦合。最終很難讓它們與您自己專案的外觀和風格相符,而且幾乎總是需要編寫一堆 CSS 覆蓋,這在使用 Tailwind CSS 時感覺像是退了一大步。
另一個選項是從頭開始建立您自己的元件。一開始似乎很容易,但隨後您會想起需要新增對鍵盤導覽、管理 ARIA 屬性、焦點捕獲的支援,突然間您就花了 3-4 週的時間試圖建立一個真正萬無一失的下拉式選單。
我們認為有一個更好的選項,因此我們正在建構它。
Headless UI 是一組完全無樣式、完全易於存取的 React 和 Vue UI 元件(並且很快就會支援 Alpine.js),讓您可以輕鬆建立這類自訂元件,而無需擔心任何複雜的實作細節,而且不會犧牲使用簡單的實用類別從頭開始設定樣式的能力。

以下是使用 @headlessui/react
建構自訂下拉式選單(此程式庫包含的眾多元件之一)的外觀,具有完整的鍵盤導覽支援和 ARIA 屬性管理,並使用簡單的 Tailwind CSS 實用程式設定樣式
import { Menu } from "@headlessui/react";function MyDropdown() { return ( <Menu as="div" className="relative"> <Menu.Button className="rounded bg-blue-600 px-4 py-2 text-white ...">Options</Menu.Button> <Menu.Items className="absolute right-0 mt-1"> <Menu.Item> {({ active }) => ( <a className={`${active && "bg-blue-500 text-white"} ...`} href="/account-settings"> Account settings </a> )} </Menu.Item> <Menu.Item> {({ active }) => ( <a className={`${active && "bg-blue-500 text-white"} ...`} href="/documentation"> Documentation </a> )} </Menu.Item> <Menu.Item disabled> <span className="opacity-75 ...">Invite a friend (coming soon!)</span> </Menu.Item> </Menu.Items> </Menu> );}
在該範例中,您免費獲得的內容如下,無需自己編寫任何相關的程式碼
- 下拉式面板會在點擊、空格鍵、Enter 鍵或使用方向鍵時開啟
- 當您按下 Esc 鍵或點擊外部時,下拉式選單會關閉
- 您可以使用向上和向下方向鍵瀏覽項目
- 您可以使用
Home
鍵跳到第一個項目,並使用End
鍵跳到最後一個項目 - 使用鍵盤導覽時會自動略過已停用的項目
- 使用鍵盤導覽後,將滑鼠懸停在項目上會切換到基於滑鼠位置的焦點
- 使用鍵盤瀏覽時,會向螢幕閱讀器正確宣告項目
- 下拉式選單按鈕會正確宣告為控制選單給螢幕閱讀器
- ...可能還有更多我忘記的事項。
所有這些都不需要在您自己的程式碼中撰寫任何 aria
字母,也不需要撰寫任何事件監聽器。而且您仍然可以完全控制設計!
這個元件有超過 3000 行的測試。您不必自己做,感覺很好,對吧?
以下是一個完全設定樣式的即時示範(取自Tailwind UI),因此您可以看看它的實際運作
請務必使用鍵盤或螢幕閱讀器嘗試,才能真正體會它的價值!
我們剛剛標記了 v0.2.0,目前包含以下元件
若要瞭解更多資訊並深入瞭解,請前往 Headless UI 網站並閱讀文件。
如果您在過去幾年追蹤我在線上的作品,您可能會記得我對無渲染 UI 元件的迷戀 — 我在 2017 年底開始真正投入其中。我一直希望存在這樣的程式庫,但在我們開始擴大團隊之前,我們沒有資源來實現它。
今年稍早,我們聘請了 Robin Malfait,而且他從那時起就一直在全職開發 Headless UI。
這個專案的最大動機是我們真的想將可投入生產的 JS 範例新增至 Tailwind UI,目前這是一個僅限 HTML 的專案,需要您自己提供 JavaScript。這對於許多想要完全控制所有工作方式的客戶來說很棒,但對許多其他人來說,這是一個摩擦點。
我們不想將 200 行的複雜 JS 新增至每個元件範例,因此我們開始開發 Headless UI 作為一種提取所有雜訊的方式,而不會放棄實際 UI 設計中的任何彈性。
為什麼要重新發明輪子?
我們不是第一個嘗試解決這個問題的人。Downshift 是我最早看到的讓我對這個想法感到興奮的程式庫,時間回到 2017 年,Reach UI 和 Reakit 在 2018 年開始開發,而 React Aria 最近才發布,就在今年稍早。
我們決定嘗試自己解決這個問題的原因有幾個
- 現有的解決方案幾乎完全專注於 React,而且我們希望將這些想法帶到其他生態系統,例如 Vue、Alpine,並希望未來會有更多。
- 這些程式庫將成為在 Tailwind UI 中新增 JS 支援的基礎,而且由於這關係到公司的營運,因此對於如何運作這些程式庫以及它們支援哪些內容,擁有完全的決策權非常重要。
- 對於這些元件的 API 應該如何設計,我們有自己的想法,並希望能夠自由地探索這些想法。
- 我們希望確保使用 Tailwind 來設定這些元件的樣式總是超級容易,而不需要編寫自訂的 CSS。
我們認為目前所提出的方案在彈性和開發者體驗之間取得了很好的平衡,並且我們很感激還有其他人也在研究類似的問題,我們可以從他們身上學習並分享我們的想法。
下一步是什麼
我們還有相當多的元件需要為 Headless UI 開發,包括:
- 模態視窗 (Modal)
- 單選群組 (Radio group)
- 分頁 (Tabs)
- 手風琴 (Accordion)
- 組合框 (Combobox)
- 日期選擇器 (Datepicker)
...以及可能更多。我們也即將開始支援 Alpine.js,並希望在年底前能夠為 React、Vue 和 Alpine 版本標記 v1.0。
在那之後,我們將開始探索其他框架,希望能最終為 Svelte、Angular 和 Ember 等生態系統提供相同的工具,無論是以原生方式還是與社群夥伴合作。
如果您想隨時掌握我們的進度,請務必在 GitHub 上關注該專案。
想討論這篇文章嗎?在 GitHub 上討論 →