Tabs タブ
同じ階層のコンテンツを切り替えます。WAI-ARIA APG の tabs pattern に厳密に準拠:tablist/tab/tabpanel の 3 ロール連携 + roving tabindex + 矢印キーナビゲーション。
基本的な使い方
基本的な使い方
水墨画の散文コンテンツ。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="散文">水墨画の散文コンテンツ。</LhTabPane>
<LhTabPane name="poem" label="詩詞">詩詞の格律コンテンツ。</LhTabPane>
<LhTabPane name="calligraphy" label="書道">書道の碑帖コンテンツ。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="散文">水墨画の散文コンテンツ。</LhTabPane>
<LhTabPane name="poem" label="詩詞">詩詞の格律コンテンツ。</LhTabPane>
<LhTabPane name="calligraphy" label="書道">書道の碑帖コンテンツ。</LhTabPane>
</LhTabs>
</template>カードタイプと無効化
カードタイプと無効化
墨は五色に分かれる。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="墨">墨は五色に分かれる。</LhTabPane>
<LhTabPane name="cinnabar" label="朱" disabled>丹砂は使用不可。</LhTabPane>
<LhTabPane name="gold" label="金">藤黄で彩色する。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="墨">墨は五色に分かれる。</LhTabPane>
<LhTabPane name="cinnabar" label="朱" disabled>丹砂は使用不可。</LhTabPane>
<LhTabPane name="gold" label="金">藤黄で彩色する。</LhTabPane>
</LhTabs>
</template>下部配置
下部配置
山の趣は雄大。
vue
<script setup lang="ts">
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="山">山の趣は雄大。</LhTabPane>
<LhTabPane name="water" label="水">水の趣は空霊。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {}
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="山">山の趣は雄大。</LhTabPane>
<LhTabPane name="water" label="水">水の趣は空霊。</LhTabPane>
</LhTabs>
</template>クローズ可能と追加可能
クローズ可能と追加可能
第 1 巻のコンテンツ。
vue
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
{ name: 's1', label: '画巻 1', content: '第 1 巻のコンテンツ。', disabled: false },
{ name: 's2', label: '画巻 2', content: '第 2 巻のコンテンツ。', disabled: false },
])
let index = 2
const removePane = (name) => {
const target = panes.value.find((pane) => pane.name === name)
if (target) panes.value.splice(panes.value.indexOf(target), 1)
}
const addPane = () => {
index += 1
panes.value.push({ name: `s${index}`, label: `画巻 ${index}`, content: '新規巻のコンテンツ。', disabled: false })
}
</script>
<template>
<!-- クローズ可能と追加可能 -->
<LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
<LhTabPane
v-for="pane in panes"
:key="pane.name"
:name="pane.name"
:label="pane.label"
:disabled="pane.disabled"
>{{ pane.content }}</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {
data() {
return {
panes: [
{ name: 's1', label: '画巻 1', content: '第 1 巻のコンテンツ。', disabled: false },
{ name: 's2', label: '画巻 2', content: '第 2 巻のコンテンツ。', disabled: false },
],
index: 2,
}
},
methods: {
removePane(name) {
const target = this.panes.find((pane) => pane.name === name)
if (target) this.panes.splice(this.panes.indexOf(target), 1)
},
addPane() {
this.index += 1
this.panes.push({ name: `s${this.index}`, label: `画巻 ${this.index}`, content: '新規巻のコンテンツ。', disabled: false })
},
},
}
</script>
<template>
<!-- クローズ可能と追加可能 -->
<LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
<LhTabPane
v-for="pane in panes"
:key="pane.name"
:name="pane.name"
:label="pane.label"
:disabled="pane.disabled"
>{{ pane.content }}</LhTabPane>
</LhTabs>
</template>アクティブなタブを閉じたとき、コンポーネントは隣接する利用可能なタブへ自動的に切り替え、
tab-removeを発火します。データソースから対応する pane を削除するのは利用者の責任です。
制御用法
制御用法
水墨画コンテンツ。
現在のタブ:mo
vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('mo')
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="中華風">中華風コンテンツ。</LhTabPane>
<LhTabPane name="mo" label="水墨画">水墨画コンテンツ。</LhTabPane>
</LhTabs>
</template>vue
<script>
export default {
data() {
return { active: 'mo' }
},
}
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="中華風">中華風コンテンツ。</LhTabPane>
<LhTabPane name="mo" label="水墨画">水墨画コンテンツ。</LhTabPane>
</LhTabs>
</template>Tabs API
LhTabs Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| modelValue | 現在アクティブなタブの name(v-model) | string | — |
| type | 外観 | "line" | "card" | 'line' |
| closable | タブを閉じられるか | boolean | false |
| addable | 追加ボタンを表示するか | boolean | false |
| tabPosition | タブの配置 | "top" | "bottom" | 'top' |
| sx | sx クイックレイアウトプロパティ | LhSxProps | — |
LhTabs Events
| イベント名 | 説明 | コールバック引数 |
|---|---|---|
| update:modelValue | アクティブタブの変化(v-model) | (name: string) |
| tab-change | アクティブタブの変化 | (name: string) |
| tab-remove | タブを閉じた | (name: string) |
| tab-add | 追加ボタンをクリック | — |
LhTabPane Props
| プロパティ名 | 説明 | 型 | デフォルト値 |
|---|---|---|---|
| name | タブの一意識別子(安定キー。動的な変更は推奨しない) | string | — |
| label | タブのタイトル | string | '' |
| disabled | 無効化するか | boolean | false |
Slots
| スロット名 | 説明 | 対象コンポーネント |
|---|---|---|
| default | タブパネル(LhTabPane のリスト) | LhTabs |
| default | パネルのコンテンツ | LhTabPane |
アクセシビリティ
WAI-ARIA APG の tabs pattern に厳密に準拠:
- タブヘッダーは
role="tablist"、各タブはrole="tab"(aria-selected+aria-controls)、パネルはrole="tabpanel"(aria-labelledby+tabindex="0") - roving tabindex:アクティブなタブのみ Tab でフォーカス可能。それ以外は
tabindex="-1" - 矢印キーで利用可能なタブ間を移動し、自動的にアクティブ化する(無効化された項目はスキップ)。Home/End で先頭・末尾へジャンプ
closableのとき Delete キーで現在のタブを閉じる。閉じるアイコンはaria-hiddenの装飾とし、キーボード操作は Delete を使用。ボタンのネストを避けている- 無効化されたタブはフォーカス・アクティブ化できず、
tab-removeなどの操作も無効化された項目には作用しない
型定義
本コンポーネントが外部にエクスポートする TypeScript 型構造は以下のとおりです(packages/components/tabs/src/types.ts および @lh-ui/share/core/* ソースから自動抽出。各エントリをクリックすると完全な定義を確認できます。プロパティの説明は上記の Props 表を参照してください):
LhTabsProps
ts
export interface LhTabsProps {
/** 現在アクティブなタブの name(v-model) */
modelValue?: string
/** 外観 */
type?: LhTabsType
/** タブを閉じられるか */
closable?: boolean
/** 追加ボタンを表示するか */
addable?: boolean
/** タブの配置 */
tabPosition?: LhTabsPosition
/** sx クイックレイアウトプロパティ */
sx?: LhSxProps
}LhTabPaneProps
ts
export interface LhTabPaneProps {
/** タブの一意識別子(安定キーとして使用。動的な変更は推奨しない) */
name: string
/** タブのタイトル */
label?: string
/** 無効化するか */
disabled?: boolean
}LhTabsType (@lh-ui/share/core/tabs から)
ts
/**
* タブの外観
*/
export type LhTabsType = 'line' | 'card'LhTabsPosition (@lh-ui/share/core/tabs から)
ts
/**
* タブの配置
*/
export type LhTabsPosition = 'top' | 'bottom'