Window Splitter
키보드로도 조작할 수 있는 구분선으로 인접 영역의 크기를 바꿉니다.
용법
가로 방향
같은 값과 경계 규칙을 유지하면서 가로 방향으로 조작합니다.
<script setup lang="ts">
const release = 'stable'
</script>
<template>
<ReleaseCard :channel="release" />
</template><!-- Window Splitter / Horizontal -->
<script setup lang="ts">
import { ref } from 'vue'
import { FileCode2, Folder, Search } from '@lucide/vue'
import { WindowSplitterHandle, WindowSplitterPane, WindowSplitterRoot } from '@sectile/vue/window-splitter'
const size = ref('34')
const editorSource = `<script setup lang="ts">
const release = 'stable'
<\/script>
<template>
<ReleaseCard :channel="release" />
</template>`
</script>
<template>
<WindowSplitterRoot v-model="size" orientation="horizontal" :min="22" :max="72" :step="1">
<WindowSplitterPane side="before">
<header><strong>Project</strong><Search :size="16" aria-hidden="true" /></header>
<nav aria-label="Project files">
<span><Folder :size="16" aria-hidden="true" /> src</span>
<span><FileCode2 :size="16" aria-hidden="true" /> App.vue</span>
<span><FileCode2 :size="16" aria-hidden="true" /> tokens.ts</span>
</nav>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize project and editor panes" />
<WindowSplitterPane side="after">
<header><strong>App.vue</strong><span>Saved</span></header>
<pre><code>{{ editorSource }}</code></pre>
</WindowSplitterPane>
</WindowSplitterRoot>
</template>세로 방향
같은 크기 규칙을 유지하면서 세로 방향으로 영역을 조절합니다.
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')$ pnpm test 18 passed
<!-- Window Splitter / Vertical -->
<script setup lang="ts">
import { ref } from 'vue'
import { SquareTerminal } from '@lucide/vue'
import { WindowSplitterHandle, WindowSplitterPane, WindowSplitterRoot } from '@sectile/vue/window-splitter'
const size = ref('56')
</script>
<template>
<WindowSplitterRoot v-model="size" orientation="vertical" :min="32" :max="76" :step="1">
<WindowSplitterPane side="before">
<header><strong>Editor</strong><span>main.ts</span></header>
<pre><code>import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')</code></pre>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize editor and terminal panes" />
<WindowSplitterPane side="after">
<header><span><SquareTerminal :size="15" aria-hidden="true" /> Terminal</span><span>zsh</span></header>
<p><span>$</span> pnpm test <span>18 passed</span></p>
</WindowSplitterPane>
</WindowSplitterRoot>
</template>외부 상태 관리
현재 값은 부모가 관리하고, 허용된 변경을 컴포넌트에 다시 전달합니다.
const layout = {
sidebar: '28%',
editor: '68%'
}<!-- Window Splitter / Controlled -->
<script setup lang="ts">
import { ref } from 'vue'
import { CheckCircle2, FileCode2, Folder, Search } from '@lucide/vue'
import { WindowSplitterHandle, WindowSplitterPane, WindowSplitterRoot } from '@sectile/vue/window-splitter'
const sidebarSize = ref('28')
const editorSize = ref('68')
// Parent state remains the source of truth for both separators.
</script>
<template>
<WindowSplitterRoot v-model="sidebarSize" orientation="horizontal" :min="22" :max="46" :step="1">
<WindowSplitterPane side="before">
<header><strong>Workspace</strong><Search :size="16" aria-hidden="true" /></header>
<nav aria-label="Workspace files">
<span><Folder :size="16" aria-hidden="true" /> components</span>
<span><FileCode2 :size="16" aria-hidden="true" /> SplitPane.vue</span>
<span><Folder :size="16" aria-hidden="true" /> tests</span>
</nav>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize workspace and main panes" />
<WindowSplitterPane side="after">
<WindowSplitterRoot v-model="editorSize" orientation="vertical" :min="42" :max="78" :step="1">
<WindowSplitterPane side="before">
<header><strong>SplitPane.vue</strong><span>TypeScript</span></header>
<pre><code>const layout = {
sidebar: {{ sidebarSize }}%,
editor: {{ editorSize }}%
}</code></pre>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize editor and preview panes" />
<WindowSplitterPane side="after">
<span><CheckCircle2 :size="17" aria-hidden="true" /> Preview ready</span>
<small>Both separators remain independently adjustable.</small>
</WindowSplitterPane>
</WindowSplitterRoot>
</WindowSplitterPane>
</WindowSplitterRoot>
</template>예시
방향 혼합
크기를 조절할 수 있는 사이드바 안쪽에 편집기와 미리보기 영역을 다시 나눕니다.
const layout = {
sidebar: '28%',
editor: '68%'
}<!-- Window Splitter / Nested Layout -->
<script setup lang="ts">
import { ref } from 'vue'
import { CheckCircle2, FileCode2, Folder, Search } from '@lucide/vue'
import { WindowSplitterHandle, WindowSplitterPane, WindowSplitterRoot } from '@sectile/vue/window-splitter'
const sidebarSize = ref('28')
const editorSize = ref('68')
</script>
<template>
<WindowSplitterRoot v-model="sidebarSize" orientation="horizontal" :min="22" :max="46" :step="1">
<WindowSplitterPane side="before">
<header><strong>Workspace</strong><Search :size="16" aria-hidden="true" /></header>
<nav aria-label="Workspace files">
<span><Folder :size="16" aria-hidden="true" /> components</span>
<span><FileCode2 :size="16" aria-hidden="true" /> SplitPane.vue</span>
<span><Folder :size="16" aria-hidden="true" /> tests</span>
</nav>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize workspace and main panes" />
<WindowSplitterPane side="after">
<WindowSplitterRoot v-model="editorSize" orientation="vertical" :min="42" :max="78" :step="1">
<WindowSplitterPane side="before">
<header><strong>SplitPane.vue</strong><span>TypeScript</span></header>
<pre><code>const layout = {
sidebar: {{ sidebarSize }}%,
editor: {{ editorSize }}%
}</code></pre>
</WindowSplitterPane>
<WindowSplitterHandle aria-label="Resize editor and preview panes" />
<WindowSplitterPane side="after">
<span><CheckCircle2 :size="17" aria-hidden="true" /> Preview ready</span>
<small>Both separators remain independently adjustable.</small>
</WindowSplitterPane>
</WindowSplitterRoot>
</WindowSplitterPane>
</WindowSplitterRoot>
</template>API
Vue 패키지: @sectile/vue/window-splitter
WindowSplitterRootWindowSplitterPaneWindowSplitterHandle
Props
WindowSplitterRootProps
as이 파트가 렌더링할 요소 또는 컴포넌트입니다.
asChild하나뿐인 자식 요소에 파트 속성을 직접 합칠지 여부입니다.
defaultValue컴포넌트가 값을 관리할 때 사용할 초깃값입니다.
disabled사용자 조작을 막을지 여부입니다.
form컨트롤을 연결할 네이티브 form 요소의 ID입니다.
formatValue값을 화면에 표시할 문자열로 바꾸는 함수입니다.
label보조 기술이 읽는 컨트롤 이름입니다.
max컴포넌트가 받을 수 있는 최댓값입니다.
min컴포넌트가 받을 수 있는 최솟값입니다.
modelValue부모가 상태를 관리할 때 사용할 현재 값입니다.
name네이티브 폼 제출에 사용할 이름입니다.
orientation배치와 키보드 이동에 사용할 축입니다.
pageStepPage Up과 Page Down이 사용할 큰 증감 간격입니다.
required제출 전에 올바른 값이 반드시 있어야 하는지 여부입니다.
step컴포넌트가 받을 수 있는 최소 증감 간격입니다.
WindowSplitterPaneProps
as이 파트가 렌더링할 요소 또는 컴포넌트입니다.
asChild하나뿐인 자식 요소에 파트 속성을 직접 합칠지 여부입니다.
side기준 요소를 중심으로 팝업을 우선 배치할 방향입니다.
이벤트
WindowSplitterRoot
update:modelValue컴포넌트가 외부 제어 값의 변경을 요청할 때 발생합니다.
기타 타입
WindowSplitterValueFormatter
type WindowSplitterValueFormatter = NonNullable<WindowSplitterRootProps['formatValue']>WindowSplitterValueChangeHandler
type WindowSplitterValueChangeHandler = (value: string) => void파트
공통 범위: [data-scope="window-splitter"]. 컴포넌트 내부로 스타일을 제한할 때 파트 선택자와 함께 사용합니다.
| 파트 | 선택자 | 역할 | 추가 속성 |
|---|---|---|---|
root | [data-part="root"] | 컴포넌트 경계와 내부 파트를 묶습니다. | — |
pane | [data-part="pane"] | 크기를 조절할 수 있는 영역 하나를 담습니다. | — |
handle | [data-part="handle"] | 인접한 영역의 크기를 조절합니다. | — |
키보드 동작
| 키 | 동작 |
|---|---|
| Arrow Left / Arrow Right | 좌우 배치에서 앞쪽 영역을 한 단계 줄이거나 늘립니다. |
| Arrow Up / Arrow Down | 상하 배치에서 앞쪽 영역을 한 단계 줄이거나 늘립니다. |
| Home / End | 구분선을 허용된 최소 또는 최대 경계로 이동합니다. |
| Page Up / Page Down | 설정된 큰 단계만큼 영역 크기를 바꿉니다. |
접근성
핸들이 구분선 방향과 현재·최소·최대 영역 크기를 노출합니다.
관련 WAI-ARIA 패턴에서 호스트 접근성 규칙을 확인할 수 있습니다.
