vue-dockable-desktop

Vue 3 port of react-dockable-desktop — a dockable layout engine with split docking, tabbed groups, floating windows and zero-unmount panel persistence.
2,818
Install
npm install vue-dockable-desktop
Latest Version:1.11.0
Vue:3
License:MIT
Last Updated:Oct 7, 2026
Links: GitHub  ·  npm
Maintainer: felipecarrillo100

vue-dockable-desktop

npm version Vue 3 TypeScript parity license

A window manager and dockable layout engine for Vue 3. Fluid grid splits, tabbed groups, floating resizable windows, zero-unmount state preservation, side panels and modals, toasts, context menus, per-panel overlays, and internationalisation.

Live demo  |  Users manual  |  Design decisions  |  Parity with the React version

Written as a native Vue library — plugins, composables, v-model, slots — not as a transliteration of its React sibling. It reads and writes the same serialised layout format as react-dockable-desktop, so a layout saved by either library loads in the other.

Versioning. vdd follows its own semver, independently of react-dockable-desktop: matching the two numbers would be a promise that breaks the first time either library needs a breaking change the other does not. Which rdd release a given version corresponds to is stated per release in CHANGELOG.md — this one tracks rdd 6.3.1, plus rdd 7.2.0 and 7.3.0's skin branding — and feature by feature in docs/PARITY.md.

Install

npm install vue-dockable-desktop

Requires Vue 3.4+, and a browser with CSS color-mix() (Chrome / Edge 111, Safari 16.2, Firefox 113 or later). No other runtime dependencies. The published package is vue-dockable-desktop; the public API is pinned by api-surface.json and covered by 851 tests.

Quick start

// main.ts
import { createApp } from 'vue'
import { createWorkspace } from 'vue-dockable-desktop'
import 'vue-dockable-desktop/styles.css'          // required
import App from './App.vue'
import MapPanel from './panels/MapPanel.vue'
import EditorPanel from './panels/EditorPanel.vue'

const workspace = createWorkspace({
  panels: {
    map:    { component: MapPanel,    defaultOptions: { title: 'Map' } },
    editor: { component: EditorPanel, defaultOptions: { title: 'Editor' } },
  },
})

createApp(App).use(workspace).mount('#app')
<!-- App.vue -->
<script setup lang="ts">
// Components are imported, not registered globally, so a build only carries the ones it uses.
import { VddDesktop, VddModals, VddSidePanels, VddToasts } from 'vue-dockable-desktop'
</script>

<template>
  <div class="app">
    <VddDesktop />
    <VddModals />
    <VddSidePanels />
    <VddToasts />
  </div>
</template>

<style>
.app { height: 100vh; overflow: hidden; }
</style>

createWorkspace() returns a Vue plugin — the same shape as createPinia() or createRouter() — so app.use(workspace) makes useWorkspace() available anywhere:

import { useWorkspace } from 'vue-dockable-desktop'

const ws = useWorkspace()
// openPanel(instanceId, panelKey, options?) — the id is yours, the key is from `panels`.
ws.openPanel('overview', 'map', { title: 'Overview' })
localStorage.setItem('layout', ws.saveLayout())

Features

  • Split-docking grid — drag a panel to any zone to split it into rows or columns, or drop it onto a tab strip to group it

  • Floating windows — 8-direction resize, maximise, minimise, and corner anchoring with automatic stacking

  • Zero-unmount persistence — panel DOM is moved, never destroyed, across docking, floating and tab switching, so maps, WebGL contexts and editors keep their state

  • Sidebar and toolbar — primary and secondary sidebars, a declarative toolbar, and per-panel contributions that follow the active panel

  • Panel overlay — anchored toolbars and floating widgets inside a single panel

  • Overlays — side panels, a modal stack, dirty-close confirmation, and toasts

  • Layout serialisation — save and restore the whole workspace as a JSON string

  • Theming — built-in skins, each with its own font, light/dark colour schemes, all --vdd-* CSS variables

  • Branding — your company's colour and font on any built-in skin, from three variables:

    :root {
      --vdd-brand-accent: #e4002b;                 /* every accent use, in every skin, dark and light */
      --vdd-brand-on-accent: #ffffff;              /* text on a brand-coloured fill — a dark one for light brands */
      --vdd-font-family: 'Acme Sans', sans-serif;  /* your font (the library loads none) */
    }
    

    Point them at your UI framework's theme to follow it — var(--p-primary-color) (PrimeVue), var(--bs-primary) (Bootstrap). Your own surfaces and corner shape, too:

    :root:not([data-color-scheme="light"]) {  /* dark: the attribute's absence */
      --vdd-brand-surface: #0b1f3a;   /* app background — panels, bars and borders derive from it */
      --vdd-brand-text: #e8eef7;      /* main text — set both, or neither */
    }
    :root { --vdd-radius-scale: 0; }  /* 0 square · 1 each skin's own · 1.5 rounder */
    

    See Brand your app

  • i18n and RTL — every string is a message key; dir="rtl" flips the whole workspace

  • TypeScript-first — complete types, no separate @types package

Documentation

Live demo Every capability in one application — published from demo/ by GitHub Pages on each push to main
docs/manual/ Users manual — 13 chapters, start with Getting started
docs/decisions/ ADRs — why the Vue design diverges from the React one
docs/PARITY.md Feature-by-feature parity with react-dockable-desktop, and the 16 deliberate divergences
docs/IMPLEMENTATION_PLAN.md The milestone plan and its gates
docs/PROGRESS.md One row per gate run
CHANGELOG.md What has changed, newest first

Repository layout

src/            the library — core/ (framework-free logic), components/, composables/
test/           Vitest suites; the executable specification
demo/           full sample application (maps, Monaco, Markdown, 16 panels)
playground/     minimal harness used by the browser gates
docs/           manual, ADRs, parity and plan
scripts/gates/  the verification gates
docs/evidence/  a written record per milestone gate (the gate's own output is not committed)

Development

npm install

npm test                # Vitest
npm run typecheck       # vue-tsc
npm run lint            # ESLint
npm run build           # library build + .d.ts + styles.css

npm run demo            # the demo app
npm run playground      # the minimal harness

npm run gate -- M14     # the full standing gate for a milestone
npm run gate:selftest   # prove every gate rule is non-vacuous
npm run gate:sweep      # coverage + non-vacuity sweep

npm run gate -- M<n> runs types, lint, tests, build, test counts, the CSS-prefix and API-surface checks, the docs/API cross-check, the demo build, the milestone's own rules, and a real-Chrome browser gate. Gates are never edited to make a run pass.

Continuous integration

Two workflows, both on Node 22 (vitest 5 will not run on Node 20):

  • .github/workflows/gate.yml runs npm run gate -- M14 on every push and pull request, browser gate included — the runner image already ships Chrome — and keeps the gate's evidence as a build artifact.
  • .github/workflows/pages.yml builds the demo and publishes it to GitHub Pages on each push to main: the landing page at the site root, the demo under /demo/. The demo's base is relative, so no deployment path is baked into the build.

License

MIT

Related Packages

plancia

Tiling window-manager component (niri-style) for Vue 3 — a scrollable strip of r...

829 0
@fastkit/vue-app-layout

Component implementation to control the overall layout of the Vue application.

7,889 6
@nylira/vue-notifications

Vue notification system component for Vue/Vuex 2.

6,687 0
vue-breakpoint

A set of layout components for Vue.js

4,326 9
@gits-id/layouts

GITS layout Component

2,810

Version History

Version Released License
1.11.0 MIT
1.10.0 MIT
1.9.0 MIT
1.8.2 MIT
1.8.1 MIT