標籤頁

輕鬆建立具無障礙功能、可完全自訂的標籤頁介面,並支援強大的焦點管理和鍵盤導覽。

要開始使用,請透過 npm 安裝無頭 UI

npm install @headlessui/react

標籤頁是用 Tab.GroupTab.ListTabTab.PanelsTab.Panel 元件建置的。預設會選取第一個標籤頁,並按一下任意標籤頁或用鍵盤選取,將會啟用對應的面板。

import { Tab } from '@headlessui/react' function MyTabs() { return ( <Tab.Group> <Tab.List> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

無頭 UI 會追蹤每個元件的許多狀態,例如目前已勾選哪個標籤頁選項、浮動式視窗是開啟還是關閉,或選單中哪個項目目前已使用鍵盤啟用。

但是由於這些元件在未調整樣式之前是無頭的且完全未調整樣式,因此在您自己為每個狀態提供所需的樣式之前,無法在使用者介面中看見這些資訊。

每個元件都會透過 渲染 Props 公開其目前狀態的資訊,您可以使用該資訊來有條件地套用不同的樣式或渲染不同的內容。

例如,Tab 元件會公開一個 selected 狀態,告訴您標籤頁是否目前已選取。

import { Fragment } from 'react' import { Tab } from '@headlessui/react' function MyTabs() { return ( <Tab.Group> <Tab.List> <Tab as={Fragment}>
{({ selected }) => (
/* Use the `selected` state to conditionally style the selected tab. */ <button className={
selected ? 'bg-blue-500 text-white' : 'bg-white text-black'
}
>
Tab 1 </button> )} </Tab> {/* ... */} </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> {/* ... */} </Tab.Panels> </Tab.Group> ) }

若要查看每個元件的完整渲染 Props API,請參閱 元件 API 文件

每個元件還透過 data-headlessui-state 屬性公開其目前狀態的資訊,您可以使用該資訊來有條件地套用不同的樣式。

傳遞 props API 中的任一狀態為「true」時,這些狀態將會以空白分隔字串的形式列在這個屬性中,因此你可以使用 CSS 屬性選取器(例如 [attr~=value])來設定目標。

舉例,以下是具有多個子項 Tab 元件的 Tab.Group 元件,而第二個索引標籤為「selected」時呈現的畫面

<!-- Rendered `Tab.Group` --> <div> <button data-headlessui-state="">Tab 1</button> <button data-headlessui-state="selected">Tab 2</button> <button data-headlessui-state="">Tab 3</button> </div> <div> <div data-headlessui-state="">Content 1</div> <div data-headlessui-state="selected">Content 2</div> <div data-headlessui-state="">Content 3</div> </div>

如果你使用的是 Tailwind CSS,可以使用 @headlessui/tailwindcss 外掛來設定對應屬性的目標,例如 ui-open:*

import { Tab } from '@headlessui/react' function MyTabs() { return ( <Tab.Group> <Tab.List>
<Tab className="ui-selected:bg-blue-500 ui-selected:text-white ui-not-selected:bg-white ui-not-selected:text-black">
Tab 1 </Tab> {/* ... */} </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> {/* ... */} </Tab.Panels> </Tab.Group> ) }

若要停用某個索引標籤,請在 Tab 元件上使用 disabled 屬性。停用的索引標籤無法使用滑鼠選取,且在使用鍵盤瀏覽索引標籤清單時也會跳過該索引標籤。

import { Tab } from '@headlessui/react' function MyTabs() { return ( <Tab.Group> <Tab.List> <Tab>Tab 1</Tab>
<Tab disabled>Tab 2</Tab>
<Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

預設情況下,當使用者使用箭頭鍵瀏覽時,會自動選取索引標籤。

如果你希望在使用者按下「Enter」或「Space」之前,不要變更目前的索引標籤,請在 Tab.Group 元件上使用 manual 屬性。當選取索引標籤會執行成本高昂的操作,而你希望避免不必要執行時,這項設定可能很有幫助。

import { Tab } from '@headlessui/react' function MyTabs() { return (
<Tab.Group manual>
<Tab.List> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

manual 屬性並不會影響滑鼠互動—索引標籤仍會在你按一下後立即被選取。

如果你已將 Tab.List 設定成垂直顯示,請使用 vertical 屬性改為使用上下箭頭鍵(而不是左右箭頭鍵)瀏覽,並更新輔助技術的 aria-orientation 屬性。

import { Tab } from '@headlessui/react' function MyTabs() { return (
<Tab.Group vertical>
<Tab.List> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

若要變更預設選取的索引標籤,請在 Tab.Group 元件上使用 defaultIndex={number} 屬性。

import { Tab } from '@headlessui/react' function MyTabs() { return (
<Tab.Group defaultIndex={1}>
<Tab.List> <Tab>Tab 1</Tab>
{/* Selects this tab by default */}
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel>
{/* Displays this panel by default */}
<Tab.Panel>Content 2</Tab.Panel>
<Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

如果你提供的索引超出了範圍,則會在初始呈現時選取最後一個未停用的索引標籤。(例如,在上方的範例中,<Tab.Group defaultIndex={5} 會將第三個面板呈現為已選取狀態。)

若要選定的索引標籤分頁變更時執行函式,請在 Tab.Group 元件上使用 onChange 屬性。

import { Tab } from '@headlessui/react' function MyTabs() { return ( <Tab.Group
onChange={(index) => {
console.log('Changed selected tab to:', index)
}}
>
<Tab.List> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

索引標籤分頁元件也可以當作受控制的元件。為達到此目的,請提供 selectedIndex 並自己管理狀態。

import { useState } from 'react' import { Tab } from '@headlessui/react' function MyTabs() {
const [selectedIndex, setSelectedIndex] = useState(0)
return (
<Tab.Group selectedIndex={selectedIndex} onChange={setSelectedIndex}>
<Tab.List> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </Tab.List> <Tab.Panels> <Tab.Panel>Content 1</Tab.Panel> <Tab.Panel>Content 2</Tab.Panel> <Tab.Panel>Content 3</Tab.Panel> </Tab.Panels> </Tab.Group> ) }

按一下 Tab 會選取索引標籤分頁,並顯示對應的 Tab.Panel

Tab 元件取得焦點時,所有互動都會套用。

指令說明

向左箭頭向右箭頭

選取上一個/下一個非停用的索引標籤分頁。

向上箭頭向下箭頭在設定 vertical

選取上一個/下一個非停用的索引標籤分頁。

HomePageUp

選取第一個非停用的索引標籤分頁。

EndPageDown

選取最後一個非停用的索引標籤分頁。

EnterSpacemanual 設置為時

啟用所選索引標籤。

所有相關的 ARIA 屬性都會自動管理。

有關在 Tabs 中實作的所有無障礙功能的完整參考,請參閱在 Tabs 上的 ARIA 規格

主要的 Tab.Group 元件。

屬性預設說明
as區段
字串 | 元件

Tabs 應呈現的元素或元件。

defaultIndex0
Number

預設選取索引

selectedIndex
數字

如果您想使用 Tabs 元件做為受控元件,則為選取索引。

onChange
(index: number) => void

當目前選取的索引標籤變更時呼叫的函式。

verticalfalse
布林

當為 true 時,Tab.List 的方向會是 vertical,否則會是 horizontal

manualfalse
布林

當為 true 時,使用者只能透過鍵盤先使用箭頭鍵瀏覽面板,再按 EnterSpace 來顯示面板。預設情況下,當透過箭頭鍵瀏覽面板時會自動顯示面板。請注意,此屬性不會影響滑鼠行為。

渲染屬性說明
selectedIndex

Number

目前選取的索引。

屬性預設說明
asdiv
字串 | 元件

Tab.List 應呈現的元素或元件。

渲染屬性說明
selectedIndex

Number

目前選取的索引。

屬性預設說明
as按鈕
字串 | 元件

Tab 應呈現的元素或元件。

disabledfalse
布林

Tab 目前是否已停用。

渲染屬性說明
selected

布林

Tab 目前是否已選取。

屬性預設說明
asdiv
字串 | 元件

Tab.Panels 應呈現的元素或元件。

渲染屬性說明
selectedIndex

Number

目前選取的索引。

屬性預設說明
asdiv
字串 | 元件

Tab.Panel 應呈現的元素或組件。

staticfalse
布林

元素是否應忽略所選索引。

注意:staticunmount 不可同時使用。如果您嘗試執行此操作,您將收到 TypeScript 錯誤。

unmounttrue
布林

元素是否應根據所選索引取消掛載或隱藏。

注意:staticunmount 不可同時使用。如果您嘗試執行此操作,您將收到 TypeScript 錯誤。

渲染屬性說明
selected

布林

Tab.Panel 目前是否已選取。

如果您有興趣使用沒有介面的 UI 和後端 CSS 預先設計組件範例,請查看 Tailwind UI — 我們所打造一系列設計精美,精心製作的組件。

這是一個非常棒的方式來支援我們在像這樣開放原始碼專案上的工作,並讓我們得以改進它們,並持續提供妥善維護。