드래그 가능한 핸들로 구분된 크기 조절 가능한 패널 세트입니다.

Usage

분할 구성 요소를 사용하여 드래그 가능한 핸들로 구분된 크기 조정 가능한 패널 리스트를 표시합니다.

Left
Main
Right
<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>
Splitter는 컨테이너의 높이를 채우므로 부모 요소가 하나를 정의하는지 확인합니다.The Splitter fills the height of its container, so make sure a parent element defines one.

Items 이미지

items Prop을 다음과 같은 속성을 가진 오브젝트 배열로 사용합니다.

  • defaultSize?: number
  • minSize?: number
  • maxSize?: number - maxSize?: number
  • collapsible?: boolean
  • collapsedSize?: number (- collapsedSize?: number)
  • sizeUnit?: '%' | 'px' - sizeUnit?: '%' | 'px'
  • order?: number - {lang="ts-type"}
  • id?: string
  • slot?: string
  • class?: any
  • ui?: { panel?: ClassNameValue } Xph037x{lang="ts-type"}

패널의 내용을 채우려면 slot 키를 사용하고 class 키를 사용하여 스타일을 지정합니다. slot 키가 없는 항목은 panel-{index} 슬롯으로 돌아갑니다. 크기는 기본적으로 백분율이며 픽셀 값으로 항목에 sizeUnit: 'px'를 설정합니다.

서버에서 렌더링할 때 id Prop을 설정하고 defaultSize를 모든 항목에 또는 없음으로 설정합니다. ID는 자동으로 생성되며 서버와 클라이언트가 동의하지 않을 수 있으므로 수화 레이아웃이 중단됩니다. defaultSize가 없는 항목은 서버의 동일한 공유로 다시 떨어지므로 두 개의 크기를 혼합하면 패널이 한 번 수분을 공급하게 됩니다. 픽셀은 클라이언트에서 측정되며 항상 약간의 이동합니다.
사이드바 Sidebar
주 (Main)
<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 소품을 사용하여 Splitter의 방향을 변경합니다. 기본값은 horizontal입니다.

첫 번째(First)
두 번째
<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>

예제

With 접이식 패널

항목에 collapsible: true를 설정하여 minSize를 지나서 축소되도록 하고 collapsedSize를 사용하여 축소될 때 패널의 일부를 표시합니다. 패널 슬롯에는 collapsed, collapse 및 expand가 노출되어 프로그래밍 방식으로 제어할 수 있습니다. collapse, expand 및 resize 이벤트는 패널 인덱스와 함께 발생합니다.

Main
<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 포함

패널 내부에 Splitter를 중첩하여 2차원 IDE 스타일의 레이아웃을 만듭니다.

Left
Top
Bottom
<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 슬롯을 사용하여 내부의 내용을 그립처럼 렌더링합니다.

Left
Right
<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>

with 지속성

auto-save-id를 제공하여 레이아웃을 localStorage로 유지하고 다시 로드할 때 복원합니다.

<template>
  <USplitter id="my-layout" auto-save-id="my-layout" :items="items">
    <!-- ... -->
  </USplitter>
</template>

API 파일

Props (### Props)

Prop Default Type
as
'div'
any

The element or component this component should render as.

id
string

A 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 | string

Unique id used to auto-save group arrangement via localStorage.

keyboardResizeBy
null | number

Step size when arrow key was pressed.

storage
PanelGroupStorage

Custom storage API; defaults to localStorage

hitAreaMargins
PointerHitAreaMargins

Allow 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 테마

app.config.ts
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'
          }
        }
      }
    }
  }
})
vite.config.ts
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'
              }
            }
          }
        }
      }
    })
  ]
})

변경 로그

No recent changes