# Docking layout

SvDockLayout: an IDE-style docking workspace - drag a tab onto another pane and drop on an edge to split or the centre to stack as a tab, drag the splitters to resize, close panes. The whole layout is a serializable, bindable DockNode tree.

Uses `@svgrid/grid` (MIT). Category: Layout. Live demo: https://svgrid.com/demos/361-dock-layout/

Install: `npm i @svgrid/grid` (Svelte 5).

## About this example

SvDockLayout in Svelte 5, an IDE-style docking workspace. Drag a tab onto another pane and drop it on an edge to split or on the centre to stack it as a tab, drag the splitters to resize and close panes with the x. The whole layout is a serializable DockNode tree bound through bind:layout, so a workspace can be saved and restored.

SvDockLayout - a basic docking workspace (IDE-style). Drag any tab onto another pane and drop it on an EDGE to split or the CENTRE to stack it as a tab; drag the splitters to resize; close panes with the x. The whole layout is a serializable `DockNode` tree bound to `layout`.

## Imports, features and API used

- Imports: `@svgrid/grid`

## Frequently asked questions

### What does the layout tree look like?

A DockNode is either a split with a direction, sizes and children, or a pane with tabs and an active id. Every drag rewrites the tree and bind:layout reflects it, so JSON.stringify gives a saveable workspace.

### How do I decide between split and stack?

By where you drop. The edges of a pane show a highlight for a split on that side; the centre highlights for adding the tab to that pane.

### What happens when the last tab of a pane closes?

The pane is removed and its sibling takes the space, so the tree never keeps empty panes.

## Related documentation

- [SvDockLayout](https://svgrid.com/docs/help/ui-components/sv-dock-layout.md)

## Related articles

- [Saved Views - Persist Grid Layout and Filters](https://svgrid.com/blog/saved-views-persist-layout/) - Give users named, switchable snapshots of column order, sorting, filters, and grouping - persisted to localStorage or a server adapter - using SvGrid's createNamedViews API.
- [Avoiding Layout Thrash in Custom Grid Cells](https://svgrid.com/blog/avoiding-layout-thrash-custom-cells/) - Layout thrash from interleaved DOM reads and writes is the most common cause of scroll jank in grids with custom cells - here is how to find it and design your way out of it.
- [Column Resizing and Reordering - Let Users Shape the Grid](https://svgrid.com/blog/column-resizing-and-reordering/) - How to wire drag-to-resize and drag-to-reorder in SvGrid, then persist the layout to localStorage so it survives page reloads.

## Source code (361-dock-layout.svelte)

```svelte
<script lang="ts">
  /**
   * SvDockLayout - a basic docking workspace (IDE-style). Drag any tab onto
   * another pane and drop it on an EDGE to split or the CENTRE to stack it as a
   * tab; drag the splitters to resize; close panes with the x. The whole layout
   * is a serializable `DockNode` tree bound to `layout`.
   */
  import { SvDockLayout, dockGroup, dockTabs, dockPane, type DockNode } from '@svgrid/grid'

  let layout = $state<DockNode>(
    dockGroup('row', [
      dockTabs([dockPane('explorer', 'Explorer')]),
      dockGroup('column', [
        dockTabs([dockPane('editor', 'index.ts'), dockPane('readme', 'README.md')]),
        dockTabs([dockPane('terminal', 'Terminal'), dockPane('problems', 'Problems')]),
      ], [0.68, 0.32]),
    ], [0.24, 0.76]),
  )

  const files = ['src/index.ts', 'src/app.svelte', 'src/lib/dock.ts', 'README.md', 'package.json']
</script>

<div class="wrap">
  <header>
    <h2>Docking layout</h2>
    <p>Drag a tab onto another pane - drop on an <b>edge</b> to split, the <b>centre</b> to stack as a tab. Drag the dividers to resize, and close panes with the x.</p>
  </header>

  <div class="stage">
    <SvDockLayout bind:layout>
      {#snippet pane(p)}
        {#if p.id === 'explorer'}
          <ul class="explorer">
            {#each files as f (f)}<li>{f}</li>{/each}
          </ul>
        {:else if p.id === 'editor'}
          <pre class="code">export function dock() {'{'}
  return 'drag me around'
{'}'}</pre>
        {:else if p.id === 'readme'}
          <div class="doc"><h3>README</h3><p>A basic docking layout built on a serializable tree.</p></div>
        {:else if p.id === 'terminal'}
          <pre class="term">$ npm run dev
  ready in 312 ms</pre>
        {:else if p.id === 'problems'}
          <div class="doc"><p>No problems detected.</p></div>
        {/if}
      {/snippet}
    </SvDockLayout>
  </div>
</div>

<style>
  .wrap { padding: 20px; display: flex; flex-direction: column; gap: 14px; height: 100%; box-sizing: border-box; }
  header h2 { margin: 0 0 4px; font-size: 20px; font-weight: 700; }
  header p { margin: 0; color: var(--sg-muted, #64748b); font-size: 13.5px; line-height: 1.5; }
  .stage { flex: 1; min-height: 420px; }
  .explorer { list-style: none; margin: 0; padding: 8px; font-size: 13px; display: flex; flex-direction: column; gap: 2px; }
  .explorer li { padding: 5px 8px; border-radius: 6px; cursor: default; }
  .explorer li:hover { background: var(--sg-row-hover-bg, #f1f5f9); }
  .code, .term { margin: 0; padding: 12px; font-size: 12.5px; line-height: 1.6; font-family: ui-monospace, monospace; }
  .term { color: var(--sg-muted, #64748b); }
  .doc { padding: 12px; font-size: 13px; }
  .doc h3 { margin: 0 0 6px; font-size: 14px; }
</style>
```

[View this example on GitHub](https://github.com/sv-grid/sv-grid/blob/main/examples/src/demos/361-dock-layout.svelte)
