Headless UI v1.6、Tailwind UI 團隊管理、Tailwind Play 改善等等

Adam Wathan

我已經有一段時間沒有寫關於我們正在做的事情了,所以有很多東西要分享!老實說太多了 — 我甚至發布此更新的主要動機是,我們下週會有更多東西推出,而且我覺得在分享我們已經發布的所有內容之前,我不允許分享那些東西。

所以穿上你的泳衣,坐在你的躺椅上,準備吸收一些維他命 CSS 吧。


Headless UI v1.6 已發布

幾週前,我們發布了 Headless UI 的新次要版本,這是我們建立的無樣式 UI 函式庫,可讓 Tailwind UI 新增 React 和 Vue 支援。

請查看版本說明以了解所有詳細資訊,但以下是一些重點。

多重選擇支援

我們已在 ComboboxListbox 元件中新增了新的 multiple 屬性,以便使用者可以選擇多個選項。

只需新增 multiple 屬性並將陣列繫結為您的 value,即可開始使用

function MyCombobox({ items }) {  const [selectedItems, setSelectedItems] = useState([]);  return (    <Combobox value={selectedItems} onChange={setSelectedItems} multiple>      {selectedItems.length > 0 && (        <ul>          {selectedItems.map((item) => (            <li key={item}>{item}</li>          ))}        </ul>      )}      <Combobox.Input />      <Combobox.Options>        {items.map((item) => (          <Combobox.Option key={item} value={item}>            {item}          </Combobox.Option>        ))}      </Combobox.Options>    </Combobox>  );}

請查看組合方塊文件清單方塊文件以了解更多資訊。

可為空的組合方塊

在 v1.6 之前,如果您刪除了組合方塊的內容並按下 Tab 鍵離開,它會還原先前選取的選項。這在很多時候都說得通,但有時候您確實想要清除組合方塊的值。

我們新增了一個新的 nullable 屬性,使這成為可能 — 只需新增該屬性,現在您就可以刪除值,而不會還原先前的值

function MyCombobox({ items }) {  const [selectedItem, setSelectedItem] = useState([]);  return (    <Combobox value={selectedItem} onChange={setSelectedItem} nullable>      <Combobox.Input />      <Combobox.Options>        {items.map((item) => (          <Combobox.Option key={item} value={item}>            {item}          </Combobox.Option>        ))}      </Combobox.Options>    </Combobox>  );}

簡易 HTML 表單支援

現在,如果您在表單元件(如 ListboxComboboxSwitchRadioGroup)中新增 name 屬性,我們將自動建立一個與元件值同步的隱藏輸入。

這讓使用常規表單提交或使用 Remix 中的 <Form> 元件等方式將資料傳送至伺服器變得非常容易。

<form action="/projects/1/assignee" method="post">  <Listbox    value={selectedPerson}    onChange={setSelectedPerson}    name="assignee"  >    {/* ... */}  </Listbox>  <button>Submit</button></form>

這適用於數字和字串等簡單值,也適用於物件 — 我們使用 1996 年的方括號表示法自動將它們序列化為多個欄位

<input type="hidden" name="assignee[id]" value="1" /><input type="hidden" name="assignee[name]" value="Durward Reynolds" />

如果您想再次閱讀我剛才寫的內容,但位於不同的網域中,請查看文件

可捲動對話方塊改善

對話方塊實際上是地球上最難建立的東西。我們一直努力解決棘手的捲動問題一段時間了,並且認為我們終於在 v1.6 中將其全部整理好。

關鍵在於我們已變更「點擊外部關閉」的運作方式。我們過去使用此 Dialog.Overlay 元件,將其放在您的實際對話方塊後面,並且我們有一個點擊處理程式,可以在點擊時關閉對話方塊。我實際上非常喜歡這種原則上的簡單性 — 偵測何時點擊特定元素比偵測何時點擊特定元素以外的任何項目,尤其是當您在對話方塊內呈現本身會在入口網站和其他內容中呈現其他內容時,要少很多怪異之處。

此方法的問題在於,如果您有一個需要捲動的長對話方塊,您的覆蓋層會位於捲軸的上方,而且嘗試點擊捲軸會關閉對話方塊。這不是您想要的!

因此,為了以非破壞性的方式解決這個問題,我們新增了一個新的 Dialog.Panel 元件,您可以改用它,而且現在只要您點擊該元件外部的任何位置,我們就會關閉對話方塊,而不是在點擊覆蓋層時關閉。

<Dialog  open={isOpen}  onClose={closeModal}  className="fixed inset-0 flex items-center justify-center ...">   <Dialog.Overlay className="fixed inset-0 bg-black/25" />   <div className="fixed inset-0 bg-black/25" />   <div className="bg-white shadow-xl rounded-2xl ...">   <Dialog.Panel className="bg-white shadow-xl rounded-2xl ...">    <Dialog.Title>Payment successful</Dialog.Title>    {/* ... */}  </div>  </Dialog.Panel></Dialog>

請查看更新的對話方塊文件,以取得使用新面板元件而非覆蓋層的更完整範例。

更好的焦點陷阱

對話方塊是地球上最難建立的東西的眾多原因之一是因為焦點陷阱。我們首次嘗試的方法涉及劫持 Tab 鍵並手動聚焦下一個/上一個元素,以便當您到達結尾時,我們可以循環回到焦點陷阱中的第一個項目。

在人們開始在焦點陷阱內使用入口網站之前,這都還好。現在基本上不可能管理,因為您可以 Tab 到概念上位於對話方塊內,但並非實際在內(因為出於樣式原因它在入口網站中呈現)的日期選擇器或其他東西。

Robin 提出了一個非常酷的解決方案,這個解決方案非常簡單 — 無需嘗試手動控制 Tab 鍵的運作方式,只需在焦點陷阱的開頭和結尾處擲入一個不可見的可聚焦元素即可。現在,每當這些哨兵元素之一收到焦點時,您只需根據您是否在第一個元素或最後一個元素,以及使用者是向前還是向後 Tab 時,將焦點移到它實際應該在的位置即可。

使用這種方法,您根本不必劫持 Tab 鍵 — 您只需讓瀏覽器完成所有工作,並且僅在您的哨兵元素之一收到焦點時手動移動焦點即可。

在搞懂這個之後,我們注意到已經有其他幾個函式庫在做一樣的事情了,所以這並不是什麼開創性或新穎的東西,但我認為這非常聰明,值得分享給任何沒有想到這種技巧的人。


Tailwind UI 的團隊管理功能

當我們第一次發布 Tailwind UI 時,「團隊」只有我和 Steve,所以如果我們想在只有我們兩個人的情況下將產品推出,我們必須盡量簡化許多事情。

其中一件事就是團隊授權。我們沒有提供任何花俏的團隊成員邀請流程,我們只是請大家與團隊分享他們的 Tailwind UI 憑證。這對我們來說足以將產品推出,因為 Tailwind UI 並沒有真正以使用者特定的方式運作,而且你們團隊的每個成員都會獲得相同的體驗。

此外,對我們來說,必須取得你們團隊中每個人的電子郵件地址,將它們輸入到某個表單中,向每個人發送邀請電子郵件,並讓他們接受邀請,感覺就像是管理上的地獄,尤其是當每個人登入後都獲得相同的體驗時。

但同時,共享任何憑證都是非常低階的做法,這不是一個我們引以為傲的設計決策。我使用與我的銀行帳戶相同的密碼 (slayerfan1234) 來登入 Tailwind UI — 我不想與任何人分享這個密碼!

所以幾個星期前,我們決定把它弄清楚並建立一些東西。

Interface with a copyable invite URL and list of team members

我們最終決定採用純粹的連結式邀請系統,您只需複製您的邀請連結,在 Slack/Discord/任何地方與您的團隊分享,並在需要時重設您的連結。您還可以給予人們「成員」或「擁有者」權限,這會控制他們是否可以管理團隊成員或查看帳單記錄。

這讓您可以在沒有一堆繁瑣的資料輸入的情況下輕鬆邀請您的團隊,並且可以在 UI 中直接撤銷某人離開時的存取權限,而不是更改您共享的密碼。

現在,任何擁有 Tailwind UI 團隊帳號的人都可以使用此功能 — 只需打開下拉式選單並點擊「我的團隊」即可為您的團隊命名並開始邀請您的同事。

您可以在 Tailwind UI 網站上 購買您團隊的授權,或者如果您擁有個人授權並想開始與您的團隊一起使用 Tailwind UI,則可以 升級到團隊授權


更新 Tailwind UI 中的 Vue 範例至 <script setup>

自從發布 Tailwind UI 的 Vue 支援以來,Vue 3 中新的 <script setup> 語法已成為撰寫單一檔案元件的建議方式。

我們已更新 Tailwind UI 中的所有 Vue 範例以使用此新格式,這減少了大量的樣板程式碼

<template>  <Listbox as="div" v-model="selected">    <!-- ... -->  </Listbox></template><script setup>  import { ref } from "vue";  import { Listbox, ListboxButton, ListboxLabel, ListboxOption, ListboxOptions } from "@headlessui/vue";  import { CheckIcon, SelectorIcon } from "@heroicons/vue/solid";  const people = [    { id: 1, name: "Wade Cooper" },    // ...  ];  const selected = ref(people[3]);</script>

對我來說,最好的部分是您不再需要明確地在 components 下註冊任何內容 — 範圍內的任何元件都會自動在範本中使用。

使用 <script setup> 也讓您可以使用 命名空間元件,例如我們在 Headless UI 的 React 版本中所做的 Listbox.Button。我們尚未更新 Headless UI 以這種方式公開元件,但我們可能很快就會這麼做,這將讓您省去大量的導入。


適用於 VS Code 的新 Tailwind CSS 語言模式

Tailwind 使用了許多非標準的 at-規則,例如 @tailwind@apply,因此如果您使用常規的 CSS 語言模式,您會在 VS Code 中收到 lint 警告。

為了規避這個問題,我們一直建議人們使用 PostCSS 語言支援 外掛程式,這可以消除這些警告,但也移除了所有其他的 CSS IntelliSense 支援。

因此,在幾個星期前,我們發布了第一個由我們自己開發的 Tailwind CSS 語言模式,作為我們 Tailwind CSS IntelliSense 擴充功能的一部分,該擴充功能建立在內建的 CSS 語言模式之上,以新增 Tailwind 特有的語法高亮顯示並修復您通常會看到的 lint 警告,而不會遺失您確實想要保留的任何 CSS IntelliSense 功能。

Sample CSS code shown with lint warnings when using a built-in CSS language mode, and no lint warnings when using the Tailwind CSS language mode.

嘗試下載最新版本的 Tailwind CSS IntelliSense,並為您的 CSS 檔案選擇「Tailwind CSS」作為語言模式。


Tailwind Play 中的「產生 CSS」面板

在過去的幾個月裡,我們對 Tailwind Play 進行了一些小的改進,我最喜歡的是新的「產生 CSS」面板。

Tailwind Play interface with a panel showing the CSS generated for that playground.

它會顯示從您的 HTML 產生的所有 CSS,並讓您按圖層篩選,這對於疑難排解非常有用。在內部,我們一直都在使用它來偵錯類別未被偵測到的奇怪問題,以便我們可以執行任何必要的 可怕的 regex 手術 來使其正常工作。

我們還在每個窗格中新增了一個「整理」按鈕 (Cmd + S),可以自動格式化您的程式碼 (並排序您的類別!),以及一個「複製」按鈕 (Cmd + A Cmd + C,但您已經知道了)。


重新設計 Refactoring UI 網站

當我們在 2018 年 12 月發布 Refactoring UI 時,Steve 和我實際上是在發布前一晚凌晨 1 點左右設計並建構了最終的登陸頁面。

事情是這樣的,我們設計了這個性感的登陸頁面,然後我正在撰寫發送給我們郵件清單上所有人的公告電子郵件,而我們都認為「這封電子郵件中的內容很棒,而且比我們在登陸頁面設計中的內容更有說服力」。

但該內容不太符合我們的設計,所以我們在最後一刻放棄了我們設計的所有內容,並根據新內容倉促拼湊了一個更簡單的頁面。它看起來還不錯,但它不是我們真正想要的超級美麗的體驗。

所以在幾個星期前,我們決定最終設計 一些新的東西

Header section of redesigned Refactoring UI website.

我仍然對這本書感到非常自豪 — 可能比我們製作過的任何東西都更自豪。它在 Goodreads 上獲得了 4.68 的評分,有超過 1100 個評分和近 200 則評論,對於一本自行出版的電子書來說,我覺得這非常令人難以置信。

期待有一天推出第二版,其中包含我們自那以來學到的所有東西!


Tailwind CSS 範本即將推出

我們 在 Twitter 上 稍微預告了一下,但在過去的幾個月裡,我們一直非常努力地開發許多完整的 Tailwind CSS 網站範本。

這是其中一個範本的搶先看 — 一個使用 Next.js 和 Stripe 新的 Markdoc 函式庫建構的文件網站範本

Artboards for a documentation site design that includes mobile and desktop layouts, and light and dark color schemes.

我對於能推出這些東西感到異常興奮。我為 Tailwind UI 作為一個產品感到非常自豪,但可複製貼上的程式碼片段格式的限制之一是,我們沒有機會真正向您展示如何將事物組件化、最小化重複,以及如何將事物架構為完整、可供生產使用的網站。

我們現在正在開發的範本將會非常棒,能夠填補這個缺口。除了獲得美觀的範本,可以用作您自己專案的起點之外,您還可以深入研究程式碼,並準確地了解我們自己如何使用 Tailwind CSS 建構網站。

我們尚未確定這些範本的確切發布日期,但我們希望下個月能推出一些東西。當我們取得更多進展時,將會分享更多資訊!

直接將我們所有的更新資訊發送到您的收件匣。
註冊我們的電子報。