用法
使用Splitter组件显示由可拖动手柄分隔的可调整大小的面板的列表。
<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 prop作为具有以下属性的对象数组:
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的项目会在服务器上退回到相等的份额,因此混合两者会使面板在水合后跳动。像素大小在客户端上测量,并且总是会有一点偏移。<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属性将拆分器. xmp的方向更改为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嵌套在面板中以构建二维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>
具有持久性
提供一个auto-save-id来将布局保持为localStorage并在重新加载时恢复它。
<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; } |
Slots
| 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'
}
}
}
}
}
})
]
})