Split View

A split view is a two-panel resizable layout container with a draggable divider between the panels.

Use it for layouts that benefit from user-controlled allocation of space — file browsers next to a file editor, list/detail views, or master/detail panels — where users may want to adjust the relative size of the two panels.

Example

SplitView
Show demo markup
<div class="split-view" aria-label="a two-panel resizable layout container with a draggable divider between them">SplitView</div>
Usage example
<script lang="ts">
  import SplitView from './SplitView.svelte';
</script>

<SplitView label="Editor and preview" splitPercent={40}>
  {#snippet primary()}
    <textarea>Editor</textarea>
  {/snippet}
  {#snippet secondary()}
    <article>Preview</article>
  {/snippet}
</SplitView>
Show Svelte source
// In your Svelte component:
import SplitView from "lily-design-system-svelte-headless/components/SplitView/SplitView.svelte";

<SplitView label="Label" value="Sample value" />

Usage

<SplitView
  label="Files and editor"
  orientation="horizontal"
  splitPercent={30}
  primary={<FileBrowser />}
  secondary={<Editor />}
/>

Props

  • label: string (required) -- aria-label for the container
  • orientation: "horizontal" | "vertical" (default "horizontal") -- divider orientation
  • primary: slot/snippet/ReactNode (required) -- first panel content
  • secondary: slot/snippet/ReactNode (required) -- second panel content
  • divider: slot/snippet/ReactNode (optional) -- custom divider content
  • splitPercent: number 0-100 (default 50) -- initial split position as percentage
  • ...restProps: any additional HTML attributes

Keyboard Interactions

  • Tab: Move focus to and from the divider
  • Arrow keys: (Consumer-provided) move the divider in orientation-appropriate increments
  • Home / End: (Consumer-provided) snap the divider to its minimum or maximum
  • Enter / Space: (Consumer-provided) toggle a collapsed panel

ARIA

  • Container: aria-label (required), data-orientation, data-split-percent
  • Default divider: role="separator", aria-orientation, aria-valuenow={splitPercent}, aria-valuemin="0", aria-valuemax="100", tabindex="0"

When to Use

  • Use for two-pane layouts where users benefit from controlling pane size
  • Use for list/detail or master/detail views
  • Use when content density justifies user-controlled space allocation

When Not to Use

  • Do not use for full page layouts — use GrailLayout instead
  • Do not use for three-or-more pane layouts — compose multiple split views
  • Do not use when the layout proportions are fixed

Headless

Renders the container, two <section> panels, and a focusable role="separator" divider. Drag handling, keyboard resize logic, and visual treatment are entirely the consumer's responsibility.

Styles

Consumer CSS targets the split-view class plus the inner split-view-primary, split-view-secondary, and split-view-divider classes. Use data-orientation and data-split-percent to drive layout proportions and divider direction.

Testing

  • Verify the component renders a <div> with class split-view
  • Verify aria-label equals the label prop
  • Verify data-orientation equals the orientation prop
  • Verify data-split-percent equals the splitPercent prop
  • Verify primary content renders inside <section class="split-view-primary">
  • Verify secondary content renders inside <section class="split-view-secondary">
  • Verify the default divider has role="separator", matching aria-orientation, aria-valuenow={splitPercent}, aria-valuemin="0", aria-valuemax="100", and tabindex="0"
  • Verify a custom divider slot replaces the default divider when provided

Advice

  • Designers: Communicate divider affordance with a hover/focus indicator; ensure it meets minimum 44×44 px target size or provide an enlarged hit area.
  • Developers: Persist splitPercent in user preferences so the layout survives reloads.

Implementation Notes

  • Uses a <div class="split-view"> container with aria-label
  • data-orientation reflects orientation for consumer styling and tests
  • data-split-percent reflects splitPercent for consumer styling and tests
  • The primary panel renders inside <section class="split-view-primary">
  • The secondary panel renders inside <section class="split-view-secondary">
  • The divider, if not customized, defaults to <div class="split-view-divider" role="separator" aria-orientation aria-valuenow aria-valuemin="0" aria-valuemax="100" tabindex="0">
  • Consumers can supply a custom divider via the divider slot/snippet/prop

Related components

  • splitter — a draggable divider for resizing adjacent panels
  • drawer — a panel that slides in from the edge of the screen
  • sidebar — a side panel for navigation or supplementary content

References

  • WAI-ARIA Separator: https://www.w3.org/TR/wai-aria-1.2/#separator
  • WAI-ARIA Window Splitter Pattern: https://www.w3.org/WAI/ARIA/apg/patterns/windowsplitter/
  • Adobe Spectrum Split View: https://spectrum.adobe.com/page/split-view/

Canonical contract

Generated from this component's canonical metadata — the machine-checked source the implementations are held to.

Metadata

  • Component: split-view
  • PascalCase: SplitView
  • Description: a two-panel resizable layout container with a draggable divider between them
  • Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
  • HTML tag: <div> container with two <section> panels and a role="separator" divider
  • CSS class: .split-view
  • Interactive: yes (separator is focusable)

ARIA

  • Container: aria-label (required)
  • Container: data-orientation, data-split-percent for consumer CSS
  • Default divider: role="separator", aria-orientation, aria-valuenow, aria-valuemin, aria-valuemax, tabindex="0"

Keyboard

  • Tab: Focus to and from the divider
  • Arrow keys: (Consumer-provided) move divider position
  • Home / End: (Consumer-provided) snap to min / max
  • Enter / Space: (Consumer-provided) toggle a collapsed panel

Props

  • label: string (REQUIRED)
  • orientation: "horizontal" | "vertical" (default "horizontal")
  • primary: slot/snippet/ReactNode (REQUIRED)
  • secondary: slot/snippet/ReactNode (REQUIRED)
  • divider: slot/snippet/ReactNode (optional)
  • splitPercent: number 0-100 (default 50)
  • ...restProps: any additional HTML attributes