vue-dockable-desktop
| Install | |
|---|---|
npm install vue-dockable-desktop |
|
| Latest Version: | 1.11.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 7, 2026 |
| Links: | GitHub · npm |
vue-dockable-desktop
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
@typespackage
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.ymlrunsnpm run gate -- M14on 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.ymlbuilds the demo and publishes it to GitHub Pages on each push tomain: the landing page at the site root, the demo under/demo/. The demo'sbaseis relative, so no deployment path is baked into the build.
License
MIT
Related Packages
Component implementation to control the overall layout of the Vue application.
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 | |
| 1.8.0 | MIT | |
| 1.7.2 | MIT | |
| 1.7.1 | MIT | |
| 1.7.0 | MIT | |
| 1.6.0 | MIT | |
| 1.5.1 | MIT | |
| 1.4.0 | MIT | |
| 1.3.0 | MIT | |
| 1.2.0 | MIT | |
| 1.1.2 | MIT | |
| 1.1.1 | MIT | |
| 1.1.0 | MIT | |
| 1.0.1 | MIT | |
| 1.0.0 | MIT |