使用法
分割コンポーネントを使用して、ドラッグ可能なハンドルで区切られたサイズ変更可能なパネルのリストを表示します。
<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const card = 'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
const items: SplitterItem[] = [
{ slot: 'left', minSize: 15, defaultSize: 25, class: card },
{ slot: 'main', minSize: 30, defaultSize: 50, class: card },
{ slot: 'right', minSize: 15, defaultSize: 25, class: card }
]
</script>
<template>
<div class="w-full h-96">
<USplitter id="splitter-example" :items="items">
<template #left>
Left
</template>
<template #main>
Main
</template>
<template #right>
Right
</template>
</USplitter>
</div>
</template>
アイテム
itemsプロパティを次のプロパティを持つオブジェクトの配列として使用します。
defaultSize?: numberminSize?: numbermaxSize?: numbercollapsible?: booleancollapsedSize?: numbersizeUnit?: '%' | 'px'order?: numberid?: stringslot?: stringclass?: anyui?: { panel?: ClassNameValue }
slotキーを使用してパネルの内容を入力し、classキーを使用してスタイルを設定します。slotキーがないアイテムはpanel-{index}スロットに戻ります。サイズはデフォルトでパーセンテージです。ピクセル値の項目にsizeUnit: 'px'を設定します。
idプロパティを設定し、defaultSizeをすべてのアイテムまたはなしに指定します。そうでなければIDは自動的に生成され、サーバーとクライアントは一致しない可能性があり、ハイドレーション時のレイアウトが崩れます。defaultSizeがないアイテムはサーバー上で等しいシェアに戻ります。そのため、2つを混ぜると、ハイドレーション後にパネルがジャンプします。ピクセルサイズはクライアントで測定され、常に少しずれます。<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const items = ref<SplitterItem[]>([
{
slot: 'sidebar',
minSize: 15,
maxSize: 40,
defaultSize: 25,
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
},
{
slot: 'main',
defaultSize: 75,
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
}
])
</script>
<template>
<USplitter id="splitter-items" :items="items">
<template #sidebar> Sidebar </template>
<template #main> Main </template>
</USplitter>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { SplitterItem } from '@nuxt/ui'
const items = ref<SplitterItem[]>([
{
slot: 'sidebar',
minSize: 15,
maxSize: 40,
defaultSize: 25,
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
},
{
slot: 'main',
defaultSize: 75,
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
}
])
</script>
<template>
<USplitter id="splitter-items" :items="items">
<template #sidebar> Sidebar </template>
<template #main> Main </template>
</USplitter>
</template>Orientation
orientationプロパティを使用して、スプリッタの方向を変更します。デフォルトはhorizontalです。
<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const items = ref<SplitterItem[]>([
{
slot: 'first',
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
},
{
slot: 'second',
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
}
])
</script>
<template>
<USplitter id="splitter-orientation" orientation="vertical" :items="items">
<template #first> First </template>
<template #second> Second </template>
</USplitter>
</template><script setup lang="ts">
import { ref } from 'vue'
import type { SplitterItem } from '@nuxt/ui'
const items = ref<SplitterItem[]>([
{
slot: 'first',
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
},
{
slot: 'second',
class:
'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
}
])
</script>
<template>
<USplitter id="splitter-orientation" orientation="vertical" :items="items">
<template #first> First </template>
<template #second> Second </template>
</USplitter>
</template>例
折りたたみパネル付き
collapsible: trueをアイテムに設定すると、minSizeを超えて折りたたまれるようになります。collapsedSizeを使用して、折りたたまれたときにパネルの一部が見えるようにします。パネルスロットはcollapsed、collapse、expandを公開しているので、プログラムで制御できます。collapse、expand、resizeイベントはパネルインデックスとともに発生します。
<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const items: SplitterItem[] = [
{ slot: 'sidebar', sizeUnit: 'px', minSize: 150, defaultSize: 250, collapsible: true, collapsedSize: 48, class: 'bg-elevated/50 border border-default rounded-xl' },
{ slot: 'main', class: 'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium' }
]
</script>
<template>
<div class="w-full h-96">
<USplitter id="splitter-collapsible-example" :items="items">
<template #sidebar="{ collapsed, collapse, expand }">
<div class="flex-1 flex items-center justify-center p-2">
<UButton
:icon="collapsed ? 'i-lucide-panel-left-open' : 'i-lucide-panel-left-close'"
:label="collapsed ? undefined : 'Collapse'"
:aria-label="collapsed ? 'Expand' : undefined"
color="neutral"
variant="subtle"
@click="collapsed ? expand() : collapse()"
/>
</div>
</template>
<template #main>
Main
</template>
</USplitter>
</div>
</template>
ネストされたスプリッタ
パネル内にSplitterをネストして、2次元のIDEスタイルのレイアウトを構築します。
<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const card = 'bg-elevated/50 border border-default rounded-xl items-center justify-center text-muted font-medium'
const items: SplitterItem[] = [
{ slot: 'left', minSize: 20, class: card },
{ slot: 'right', minSize: 20 }
]
const nested: SplitterItem[] = [
{ slot: 'top', minSize: 20, class: card },
{ slot: 'bottom', minSize: 20, class: card }
]
</script>
<template>
<div class="w-full h-96">
<USplitter id="splitter-nested-example" :items="items">
<template #left>
Left
</template>
<template #right>
<USplitter id="splitter-nested-example-inner" orientation="vertical" :items="nested">
<template #top>
Top
</template>
<template #bottom>
Bottom
</template>
</USplitter>
</template>
</USplitter>
</div>
</template>
カスタムハンドル付き
ハンドルはデフォルトでは見えません。uiプロパティを使用してスタイルを変更します。例えば、フラッシュレイアウトの可視分割器として、resize-handleスロットを使用してハンドル内のコンテンツをグリップのようにレンダリングします。
<script setup lang="ts">
import type { SplitterItem } from '@nuxt/ui'
const items: SplitterItem[] = [
{ slot: 'left', minSize: 20, defaultSize: 30, class: 'items-center justify-center text-muted font-medium' },
{ slot: 'right', defaultSize: 70, class: 'items-center justify-center text-muted font-medium' }
]
</script>
<template>
<div class="w-full h-96">
<USplitter id="splitter-custom-handle-example" :items="items" :ui="{ handle: 'data-[orientation=horizontal]:w-px data-[orientation=vertical]:h-px bg-border transition-colors data-[state=hover]:bg-primary data-[state=drag]:bg-primary' }" class="rounded-lg border border-default overflow-hidden">
<template #left>
Left
</template>
<template #right>
Right
</template>
</USplitter>
</div>
</template>
持続性
レイアウトをlocalStorageに保持し、リロード時に復元するためにauto-save-idを指定します。
<template>
<USplitter id="my-layout" auto-save-id="my-layout" :items="items">
<!-- ... -->
</USplitter>
</template>
API
Props
| Prop | Default | Type |
|---|---|---|
as | 'div' | anyThe element or component this component should render as. |
id | stringA unique id for the group, also used to derive the ids of its panels and handles. Set it when rendering on the server, auto-generated ids can differ between the server and the client and break resizing on hydration. | |
orientation | 'horizontal' | "horizontal" | "vertical"The orientation of the splitter. |
items | T[] | |
disabled | false | boolean Whether the resize handles are disabled, locking the current layout. |
autoSaveId | null | stringUnique id used to auto-save group arrangement via | |
keyboardResizeBy | null | numberStep size when arrow key was pressed. | |
storage | PanelGroupStorageCustom storage API; defaults to localStorage | |
hitAreaMargins | PointerHitAreaMarginsAllow this much margin when determining resizable handle hit detection | |
ui | { root?: SlotClass; panel?: SlotClass; handle?: SlotClass; } |
スロット
| Slot | Type |
|---|---|
resize-handle | { index: number; ui: object; } |
Emits
| Event | Type |
|---|---|
layout | [val: number[]] |
collapse | [index: number] |
expand | [index: number] |
resize | [index: number, size: number, prevSize?: number | undefined] |
dragging | [index: number, dragging: boolean] |
Theme
export default defineAppConfig({
ui: {
splitter: {
slots: {
root: '',
panel: 'flex',
handle: 'group relative shrink-0 focus-visible:outline-2 focus-visible:outline-primary data-[panel-resize-handle-enabled=false]:cursor-default'
},
variants: {
orientation: {
horizontal: {
handle: 'w-2 cursor-col-resize'
},
vertical: {
handle: 'h-2 cursor-row-resize'
}
}
}
}
}
})import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
splitter: {
slots: {
root: '',
panel: 'flex',
handle: 'group relative shrink-0 focus-visible:outline-2 focus-visible:outline-primary data-[panel-resize-handle-enabled=false]:cursor-default'
},
variants: {
orientation: {
horizontal: {
handle: 'w-2 cursor-col-resize'
},
vertical: {
handle: 'h-2 cursor-row-resize'
}
}
}
}
}
})
]
})