Create Resizable Split Views with Vue Split Panel Component

Install & Download:

pnpm add @directus/vue-split-panel

Description:

Split Panel is a Vue component that allows you to create customizable, resizable, horizontal/vertical split views in Vue applications.

It handles text direction automatically and supports both Left-to-Right (LTR) and Right-to-Left (RTL) languages.

You can also nest multiple split panels to create complex grid layouts.

More Features

  • Accessibility: Follows the Window Splitter WAI-ARIA pattern to support screen readers and assistive technologies.
  • Keyboard Interaction: You can resize and collapse panes using standard keyboard controls like Arrow keys, Home, and End.
  • Transitions: Applies smooth animations when panels collapse or expand.
  • Snapping: The divider snaps to specific points defined in the configuration during drag operations.

Use Cases

  • Code Editors: Build a layout with a file explorer sidebar and a main code editing window.
  • Admin Dashboards: Create a collapsible navigation menu next to a primary content area.
  • Data Comparison: Display two distinct data sets side-by-side with a movable divider for analysis.
  • Preview Panes: Implement a vertical split where the top pane accepts input and the bottom pane renders the result.

How to Use It

1. Install the package using your preferred package manager.

pnpm add @directus/vue-split-panel

2. Import the component’s CSS file for the layout to render correctly. You can do this in your main JavaScript entry point or within a specific component.

// In main.ts or component script
import '@directus/vue-split-panel/index.css';

3. Import the SplitPanel component and define your content using the #start and #end slots. The component defaults to a horizontal layout.

<script lang="ts" setup>
import { SplitPanel } from '@directus/vue-split-panel';
</script>
<template>
  <div class="layout-wrapper">
    <SplitPanel>
      <template #start>
        <div class="panel sidebar">Sidebar Content</div>
      </template>
      <template #end>
        <div class="panel main">Main Content</div>
      </template>
    </SplitPanel>
  </div>
</template>
<style scoped>
.layout-wrapper {
  height: 400px;
  border: 1px solid #e5e7eb;
}
.panel {
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.sidebar {
  background-color: #f3f4f6;
}
.main {
  background-color: #ffffff;
}
</style>

4. Set the orientation prop to vertical to stack the panels. Ensure the parent container has a defined height.

<SplitPanel orientation="vertical" class="h-full">
  <template #start>
    <div>Top Panel</div>
  </template>
  <template #end>
    <div>Bottom Panel</div>
  </template>
</SplitPanel>

5. You can allow a panel to collapse completely. This requires setting collapsible, min-size, and collapse-threshold. The size-unit prop determines if these values represent pixels or percentages.

<SplitPanel
  collapsible
  size-unit="px"
  :min-size="200"
  :size="300"
  :max-size="600"
  :collapse-threshold="50"
>
  <template #start>
    <div>Collapsible Sidebar</div>
  </template>
  <template #end>
    <div>Main View</div>
  </template>
</SplitPanel>

6. The default divider is unstyled. Use the #divider slot to insert a custom element for styling or to increase the hit area.

<SplitPanel>
  <template #start>Panel A</template>
  <template #divider>
    <div class="custom-divider"></div>
  </template>
  <template #end>Panel B</template>
</SplitPanel>
<style>
.custom-divider {
  width: 4px;
  height: 100%;
  background-color: #cbd5e1;
  cursor: col-resize;
}
.custom-divider:hover {
  background-color: #3b82f6;
}
</style>

API Reference

Model Properties

  • size: number – Current size of the start panel
  • collapsed: boolean – Primary panel collapse state

Component Props

  • orientation: ‘horizontal’ | ‘vertical’ – Layout direction (default: ‘horizontal’)
  • direction: ‘ltr’ | ‘rtl’ – Text direction (default: ‘ltr’)
  • primary: ‘start’ | ‘end’ – Designates primary panel for resize behavior
  • dividerHitArea: string – CSS size for divider hitbox (default: ’12px’)
  • sizeUnit: ‘%’ | ‘px’ – Unit for size values (default: ‘%’)
  • disabled: boolean – Disable manual resizing (default: false)
  • minSize: number – Minimum primary panel size (requires primary)
  • maxSize: number – Maximum primary panel size (requires primary)
  • collapsible: boolean – Enable panel collapse (default: false)
  • collapseThreshold: number – Drag distance beyond minSize to trigger collapse
  • collapsedSize: number – Visible size of collapsed panel
  • transitionDuration: number – Collapse/expand animation duration in ms (default: 0)
  • transitionTimingFunctionExpand: string – CSS timing function for expand
  • transitionTimingFunctionCollapse: string – CSS timing function for collapse
  • snapPoints: number[] – Array of snap positions during drag
  • snapThreshold: number – Snap proximity threshold (default: 12)
  • ui: { start?: string, divider?: string, end?: string } – Additional CSS classes

FAQs

Q: How do I programmatically collapse the panel?
A: You can bind a variable to v-model:collapsed or access the component instance via a template ref and call the collapse() method.

Q: Does the divider have default styles?
A: No, the divider has no visual styling by default. You must add your own styles or use the #divider slot to ensure it is visible and accessible.

Q: Can I use this with Server-Side Rendering (SSR)?
A: Yes, the component supports SSR. However, you should ensure that the initial state matches the server render to avoid layout shifts during hydration.

Q: What happens if I don’t set a primary panel?
A: If no primary prop is set, both panels will resize proportionally when the parent container changes dimensions.

Related Resources

Add Comment