タブ

堅牢なフォーカス管理とキーボードナビゲーションサポートにより、アクセシビリティが高く、完全にカスタマイズ可能なタブインターフェースを簡単に作成できます。

開始するには、npm を介して Headless UI をインストールします。

npm install @headlessui/vue

タブは、TabGroupTabListTabTabPanels、およびTabPanelコンポーネントを使用して構築されています。デフォルトでは最初のタブが選択され、任意のタブをクリックするか、キーボードで選択すると、対応するパネルがアクティブになります。

<template> <TabGroup> <TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

Headless UI は、現在チェックされているタブオプション、ポッパーが開いているか閉じているか、メニューのどのアイテムが現在キーボードでアクティブになっているかなど、各コンポーネントに関する多くの状態をトラッキングします。

しかし、コンポーネントはヘッドレスであり、すぐに使える状態では完全にスタイルが適用されていないため、各状態に必要なスタイルを自分で提供するまで、UIでこの情報を見ることはできません。

各コンポーネントは、スロットプロップを介して現在の状態に関する情報を公開しており、これを使用して条件付きで異なるスタイルを適用したり、異なるコンテンツをレンダリングしたりできます。

たとえば、Tabコンポーネントはselected状態を公開しており、タブが現在選択されているかどうかを示します。

<template> <TabGroup> <TabList> <!-- Use the `selected` state to conditionally style the selected tab. -->
<Tab as="template" v-slot="{ selected }">
<button
:class="{ 'bg-blue-500 text-white': selected, 'bg-white text-black': !selected }"
>
Tab 1 </button> </Tab> <!-- ... --> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <!-- ... --> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

各コンポーネントのスロットプロップAPIの完全なリストについては、コンポーネントAPIドキュメントを参照してください。

各コンポーネントは、条件付きで異なるスタイルを適用するために使用できるdata-headlessui-state属性を介して、現在の状態に関する情報を公開します。

スロットプロップAPIのいずれかの状態がtrueの場合、それらはスペース区切りの文字列としてこの属性にリストされます。そのため、[attr~=value]形式のCSS属性セレクターを使用してターゲットにすることができます。

たとえば、2番目のタブがselectedの場合、いくつかの子Tabコンポーネントを含むTabGroupコンポーネントは次のようにレンダリングされます。

<!-- Rendered `TabGroup` --> <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:*などの修飾子でこの属性をターゲットにすることができます。

<template> <TabGroup> <TabList> <Tab
class="ui-selected:bg-blue-500 ui-selected:text-white ui-not-selected:bg-white ui-not-selected:text-black"
>
Tab 1 </Tab> <!-- ... --> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <!-- ... --> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

タブを無効にするには、Tabコンポーネントでdisabledプロップを使用します。無効なタブはマウスで選択できず、キーボードを使用してタブリストをナビゲートするときにもスキップされます。

<template> <TabGroup> <TabList> <Tab>Tab 1</Tab>
<Tab disabled>Tab 2</Tab>
<Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

デフォルトでは、ユーザーが矢印キーを使用してタブを移動すると、タブが自動的に選択されます。

ユーザーがEnterキーまたはSpaceキーを押すまで現在のタブを変更しないようにするには、TabGroupコンポーネントでmanualプロップを使用します。これは、タブの選択が高価な操作を実行し、不要に実行したくない場合に役立ちます。

<template>
<TabGroup manual>
<TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

manualプロップはマウス操作には影響しません。タブはクリックされるとすぐに選択されます。

TabListを垂直に表示するようにスタイル設定した場合は、verticalプロップを使用して、左右の矢印キーではなく上下の矢印キーでナビゲートし、補助技術のためにaria-orientation属性を更新します。

<template>
<TabGroup vertical>
<TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

デフォルトで選択されているタブを変更するには、TabGroupコンポーネントで:defaultIndex="number"プロップを使用します。

<template>
<TabGroup :defaultIndex="1">
<TabList> <Tab>Tab 1</Tab>
<!-- Selects this tab by default -->
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel>
<!-- Displays this tab by default -->
<TabPanel>Content 2</TabPanel>
<TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue' </script>

範囲外のインデックスを指定した場合、最初のレンダリング時に最後の無効でないタブが選択されます。(たとえば、上記の例では、<TabGroup :defaultIndex="5"は3番目のパネルを選択してレンダリングします。)

選択されたタブが変更されるたびに関数を実行するには、TabGroupコンポーネントで@changeイベントを使用します。

<template>
<TabGroup @change="changeTab">
<TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue'
function changeTab(index) {
console.log('Changed active tab to:', index)
}
</script>

タブコンポーネントは、制御されたコンポーネントとしても使用できます。これを行うには、selectedIndexを提供し、自分で状態を管理します。

<template>
<TabGroup :selectedIndex="selectedTab" @change="changeTab">
<TabList> <Tab>Tab 1</Tab> <Tab>Tab 2</Tab> <Tab>Tab 3</Tab> </TabList> <TabPanels> <TabPanel>Content 1</TabPanel> <TabPanel>Content 2</TabPanel> <TabPanel>Content 3</TabPanel> </TabPanels> </TabGroup> </template> <script setup> import { ref } from 'vue' import { TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue'
const selectedTab = ref(0)
function changeTab(index) {
selectedTab.value = index
}
</script>

Tabをクリックすると、そのタブが選択され、対応するTabPanelが表示されます。

Tabコンポーネントにフォーカスがある場合、すべての操作が適用されます。

コマンド説明

左矢印右矢印

無効でない前の/次のタブを選択します。

上矢印下矢印 vertical が設定されている場合

無効でない前の/次のタブを選択します。

HomeまたはPageUp

無効でない最初のタブを選択します。

EndまたはPageDown

無効でない最後のタブを選択します。

EnterまたはSpace manual が設定されている場合

選択したタブをアクティブにします。

すべての関連するARIA属性が自動的に管理されます。

Tabsに実装されているすべてのアクセシビリティ機能の完全なリファレンスについては、タブに関するARIA仕様を参照してください。

メインのTabGroupコンポーネント。

プロップデフォルト説明
asテンプレート
文字列 | コンポーネント

TabGroupがレンダリングされる要素またはコンポーネント。

defaultIndex0
数値

デフォルトで選択されているインデックス

selectedIndex
数値

タブコンポーネントを制御されたコンポーネントとして使用する場合の選択インデックス。

verticalfalse
ブール値

trueの場合、TabListの向きはverticalになり、それ以外の場合はhorizontalになります。

manualfalse
ブール値

trueの場合、ユーザーはキーボードを使用してパネルを表示するには、最初に矢印キーを使用してパネルに移動し、次にEnterキーまたはSpaceキーを押す必要があります。デフォルトでは、矢印キーを使用して移動すると、パネルが自動的に表示されます。このプロップはマウスの動作には影響しません。

スロットプロップ説明
selectedIndex

数値

現在選択されているインデックス。

イベント説明
change

アクティブなタブが変更されるたびに呼び出される関数。

プロップデフォルト説明
asdiv
文字列 | コンポーネント

TabListがレンダリングされる要素またはコンポーネント。

スロットプロップ説明
selectedIndex

数値

現在選択されているインデックス。

プロップデフォルト説明
asbutton
文字列 | コンポーネント

Tabがレンダリングされる要素またはコンポーネント。

disabledfalse
ブール値

Tabが無効かどうか。

スロットプロップ説明
selected

ブール値

Tabが現在選択されているかどうか。

プロップデフォルト説明
asdiv
文字列 | コンポーネント

TabPanelsとしてレンダリングされる要素またはコンポーネント。

スロットプロップ説明
selectedIndex

数値

現在選択されているインデックス。

プロップデフォルト説明
asdiv
文字列 | コンポーネント

TabPanelとしてレンダリングされる要素またはコンポーネント。

静的false
ブール値

要素が選択インデックスを無視するかどうか。

_注記: staticunmountは同時に使用できません。

アンマウントtrue
ブール値

選択インデックスに基づいて、要素をアンマウントするか、非表示にするか。

_注記: staticunmountは同時に使用できません。

スロットプロップ説明
selected

ブール値

TabPanelが現在選択されているかどうか。

Headless UIとTailwind CSSを使用した、事前にデザインされたコンポーネントの例にご興味があれば、Tailwind UIをご覧ください。これは、私たちが作成した美しくデザインされ、専門的に作られたコンポーネントのコレクションです。

これは、このようなオープンソースプロジェクトへの私たちの活動を支援する素晴らしい方法であり、それらを改善し、適切に維持することを可能にします。