Splitter

GitHub
A component that divides your layout into resizable sections.
Panel A
Panel B
Panel C
<script setup lang="ts">
import { ASplitterGroup, ASplitterPanel, ASplitterResizeHandle } from 'akar';
</script>

<template>
  <div class="text-sm color-primary font-semibold px-8 h-64 w-full md:px-16">
    <ASplitterGroup
      id="splitter-group-1"
      direction="horizontal"
    >
      <ASplitterPanel
        id="splitter-group-1-panel-1"
        :min-size="20"
        class="border rounded-xl flex items-center justify-center"
      >
        Panel A
      </ASplitterPanel>
      <ASplitterResizeHandle
        id="splitter-group-1-resize-handle-1"
        class="w-2"
      />
      <ASplitterPanel
        id="splitter-group-1-panel-2"
        :min-size="20"
      >
        <ASplitterGroup
          id="splitter-group-2"
          direction="vertical"
        >
          <ASplitterPanel
            id="splitter-group-2-panel-1"
            :min-size="20"
            class="border rounded-xl flex items-center justify-center"
          >
            Panel B
          </ASplitterPanel>
          <ASplitterResizeHandle
            id="splitter-group-2-resize-handle-1"
            class="h-2"
          />
          <ASplitterPanel
            id="splitter-group-2-panel-2"
            :min-size="20"
            class="border rounded-xl flex items-center justify-center"
          >
            Panel C
          </ASplitterPanel>
        </ASplitterGroup>
      </ASplitterPanel>
    </ASplitterGroup>
  </div>
</template>

Features

  • Supports keyboard interaction.
  • Supports horizontal/vertical layout.
  • Supports nested layout.
  • Supports Right to Left direction.
  • Can resize across another panel.
  • Can be mounted conditionally.

Anatomy

Import all parts and piece them together.

<script setup>
import { ASplitterGroup, ASplitterPanel, ASplitterResizeHandle } from 'akar';
</script>

<template>
  <ASplitterGroup>
    <ASplitterPanel />
    <ASplitterResizeHandle />
  </ASplitterGroup>
</template>

API Reference

Group

Contains all the parts of a ASplitter.

Data Attributes

Attribute Value
[data-orientation]'vertical' | 'horizontal'
[data-state]'collapsed' | 'expanded' | 'Present when collapsible'

Panel

A collapsible section.

Resize Handle

Handle that use for resizing.

Data Attributes

Attribute Value
[data-orientation]'vertical' | 'horizontal'
[data-state]'drag' | 'hover' | 'inactive'
[data-disabled]Present when disabled

Examples

Collapsible

Use the collapsible prop to allow the panel to collapse into collapsedSize when minSize is reached.

(collapsedSize and minSize props are required.)

<template>
  <ASplitterGroup>
    <ASplitterPanel
      collapsible
      :collapsed-size="10"
      :min-size="35"
    >
      Panel A
    </ASplitterPanel>
    <ASplitterResizeHandle />
    <ASplitterPanel>
      Panel B
    </ASplitterPanel>
  </ASplitterGroup>
</template>

Persist in localStorage

Use the autoSaveId prop to save the layout data into localStorage.

<template>
  <ASplitterGroup auto-save-id="any-id">
  </ASplitterGroup>
</template>

Persist layout with SSR

By default, ASplitter uses localStorage to persist layouts. With server rendering, this can cause a flicker when the default layout (rendered on the server) is replaced with the persisted layout (in localStorage). The way to avoid this flicker is to also persist the layout with a cookie like so:

<!-- with Nuxt -->
<script setup lang="ts">
const layout = useCookie<number[]>('splitter:layout')
</script>

<template>
  <ASplitterGroup
    direction="horizontal"
    @layout="layout = $event"
  >
    <ASplitterPanel :default-size="layout[0]">
    </ASplitterPanel>
    <ASplitterResizeHandle />
    <ASplitterPanel :default-size="layout[1]">
    </ASplitterPanel>
  </ASplitterGroup>
</template>

Collapse/Expand programmatically

Sometimes panels need to resize or collapse/expand in response to user actions. ASplitterPanel exposes the collapse and expand methods to achieve this.

<script setup lang="ts">
const panelRef = ref<InstanceType<typeof ASplitterPanel>>()
</script>

<template>
  <button
    @click="panelRef?.isCollapsed ? panelRef?.expand() : panelRef?.collapse() "
  >
    {{ panelRef?.isCollapsed ? 'Expand' : 'Collapse' }}
  </button>

  <ASplitterGroup>
    <ASplitterPanel
      ref="panelRef"
      collapsible
      :collapsed-size="10"
      :min-size="35"
    >
    </ASplitterPanel>
    <ASplitterResizeHandle />
    <ASplitterPanel>
    </ASplitterPanel>
  </ASplitterGroup>
</template>

Custom handle

Customize the handle by passing any element as the slot.

<template>
  <ASplitterGroup>
    <ASplitterPanel>
    </ASplitterPanel>
    <ASplitterResizeHandle>
      <Icon icon="radix-icons-drag-handle-dots-2" />
    </ASplitterResizeHandle>
    <ASplitterPanel>
    </ASplitterPanel>
  </ASplitterGroup>
</template>

SSR

ASplitter component heavily relies on unique id, however for Vue<3.4 we don't have a reliable way of generating SSR-friendly id.

Thus, if you are using Nuxt or other SSR framework, you are required to manually add the id for all ASplitter components. Alternatively, you can wrap the component with <ClientOnly>.

<template>
  <ASplitterGroup id="group-1">
    <ASplitterPanel id="group-1-panel-1">
    </ASplitterPanel>
    <ASplitterResizeHandle id="group-1-resize-1">
      <Icon icon="radix-icons-drag-handle-dots-2" />
    </ASplitterResizeHandle>
    <ASplitterPanel id="group-1-panel-2">
    </ASplitterPanel>
  </ASplitterGroup>
</template>

Accessibility

Adheres to the Window ASplitter WAI-ARIA design pattern.

Keyboard Interactions

Key Description
Enter

If the primary pane is not collapsed, collapses the pane. If the pane is collapsed, restores the splitter to its previous position.

ArrowDown

Moves a horizontal splitter down.

ArrowUp

Moves a horizontal splitter up.

ArrowRight

Moves a vertical splitter to the right.

ArrowLeft

Moves a vertical splitter to the left.

Home

Moves splitter to the position that gives the primary pane its smallest allowed size.

End

Moves splitter to the position that gives the primary pane its largest allowed size.