rc-dock: a dockable panel layout for React
Dock Layout for React Component
At a glance
- What is it?
- rc-dock gives a React application a docked, tabbed panel layout that users can rearrange by dragging, with floating panels that can be popped into separate browser windows and a light and dark theme. The layout is a serialisable tree, which means a user's arrangement can be saved and restored.
- Who is it for?
- rc-dock suits a developer building an IDE like interface in React, where panels are dragged, tabs are opened and closed and the arrangement should survive a reload, since the layout is a serialisable tree rather than component state scattered through the application.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A panel layout rather than a component library
rc-dock describes itself as a dock layout for a React component, and the screenshots in the README show what that means: a window divided into resizable boxes, each box holding a tabbed panel, with the freedom to drag tabs between panels and to tear a panel out into a floating window.
The floating window feature is the part that distinguishes it. The README has a screenshot titled popup panel as new browser window, and the package keywords include window for a reason. rc-dock depends on a package called rc-new-window, so a panel can be opened in its own browser window, which is how you build an interface that behaves like a desktop application with several windows but runs as a single web page.
There is also a dark theme, shipped as a separate stylesheet, and a documentation site with an examples section that runs in the browser rather than as screenshots, which is the more useful way to evaluate a layout component because you can interact with it.
The library is TypeScript, published to npm as rc-dock under the Apache 2.0 licence, and the repository carries an examples directory with more than twenty runnable examples, a HISTORY file and a Discord community.
The layout tree and its four types
The heart of the library is a set of four data types, and the README documents them as a table of properties, types, comments and defaults.
LayoutData is the top level. It has a dockbox property, described as the main dock box, which is required, and a floatbox property, the main float box, whose children can only be panel data, and which defaults to an empty box.
BoxData is the layout element that contains other boxes or panels. Its mode is horizontal, vertical or float, and its children property is required and holds either boxes or panels.
PanelData contains tabs and their content. Its tabs property is required, and it has a panelLock option, which keeps empty panels, prevents dragging the whole panel into the floating layer, and provides sizing and header overrides.
TabData describes one tab. The id is a unique id and is required, as are the title, which is a React child, and the content, which is either a React element or a function that receives the tab data and returns one. A tab is not closable by default, and it can belong to a group, with the note that tabs from different groups cannot share a panel through drag and drop.
That group mechanism is worth pausing on, because it is how you stop a user dragging an editor tab into a settings panel. The groups are configured through the layout props.
Controlled and uncontrolled layout, and the tab registry
There are two ways to drive the layout, and the README names them explicitly.
As an uncontrolled layout you set the layout object in the defaultLayout property, and the component owns it from then on. As a controlled layout you set the layout object in the layout property, and your application owns it. The rest of the README is written for the uncontrolled case.
The tab handling has a particular shape that is worth understanding before you design around it. The tabs property holds tab definitions keyed by id, and the layout tree can contain only id references, while titles, content and tab options live in the tabs registry. The registry key supplies the id, and full inline tab definitions remain supported for compatibility.
The consequence is that the layout is small and the registry is the source of truth. When an id is missing from the registry, a loadTab callback can create the definition on demand, and returning null skips a tab that is unavailable.
<DockLayout
defaultLayout={defaultLayout}
tabs={tabs}
loadTab={({id}) => documents[id] ? createDocumentTab(id) : null}
/>Saving works the same way. The saveLayout method and the onLayoutChange callback save tabs as id references by default, and a saveTab callback is used to include custom serialisable fields that loadTab can restore.
The remaining guidance is about React specifics, and it is the part that will save you a rendering bug. Replacing the tabs object updates the titles and content of open tabs without changing their positions or the active selection, tabs outside the registry keep their loaded definitions, and cached component state is preserved for the same id and component type. Closing a tab removes its layout reference but leaves the registry entry available for reopening with dockMove, and registry definitions are copied before use. The tabs object and unchanged definitions should be kept stable between unrelated renders, for example with useMemo, and for frequent updates to a single tab there is an updateTab method that changes that tab directly.
Side columns and theming
Side columns are the outer columns of a horizontal root that has at least two children, and they are configured through the sideColumns property.
<DockLayout
defaultLayout={defaultLayout}
tabs={tabs}
sideColumns={{
left: {collapsible: true, accordion: true, padding: 10},
right: {collapsible: true, accordion: true, padding: 10},
}}
/>Each column has three options. Collapsible collapses a column down to its tab titles, and selecting a title restores it. Accordion expands one panel and shrinks the others to their headers, which is how a file tree and a preview pane avoid competing for width. Padding sets the outer spacing in pixels, and the note says it applies even without a column and is removed while collapsed.
Column state is saved with the layout, so a user's arrangement of side columns survives a reload along with everything else.
Theming is two stylesheets and a set of SCSS variables. The light theme is imported from the distribution CSS, and the dark theme from a separate file, and to customise the variables you use the SCSS source rather than the compiled CSS.
@use "rc-dock/style/index-light" with (
$primary-color: #108ee9
);There is a matching dark entry point, and a build script regenerates both distributed CSS files from the SCSS sources.
Testing, and what the coverage is actually based on
The test setup is described in detail, which is a good sign for a library whose hard part is drag and drop behaviour.
The tests use Vitest 5 and Playwright with Chromium, following the Node and browser test setup the author uses across projects, and the README asks for Node 24 for development.
pnpm install
pnpm exec playwright install chromium
pnpm test # Layout algorithms and serialization
pnpm test-browser # React components and drag/drop in Chromium
pnpm test-browser-ui # Watch browser tests with a visible browser
pnpm test-typecheck # Type-check source, tests and test configuration
pnpm test-coverage # Node coverage in coverage/node
pnpm test-browser-coverage # Browser coverage in coverage/browserThe split between the two suites is the important design point. The Node suite covers the layout algorithms and the serialisation, which are pure and fast, and the browser suite covers the React components and the drag and drop behaviour, which need a real browser.
Tests live under the node and browser test directories, outside the published source build, and the README notes that the browser tests import the SCSS styles directly and clean up rendered roots and active drags after each test, which is the kind of detail that only matters if you have written browser tests before.
Coverage is based on a named set of examples, the basic, tab-min-size, standalone-divider, save-layout, controlled-layout, tab-cache and adv-tab-update examples, plus drag-preview opacity and cleanup. That is a useful statement of intent, because it ties coverage to behaviour rather than to line count.
Packaging, versions and the shape of the repository
The package metadata shows a library that publishes compiled output rather than source, and that is worth noting for anyone reading the examples.
The main entry points are the compiled CommonJS output, an ES module build and the type declarations, and the published files list includes both builds, the distribution CSS, the SCSS sources and the HISTORY file. The examples therefore import the compiled CSS rather than building it.
The build scripts show the pipeline: a prepack step runs the library build, the ES build and the SCSS build, the library builds are two TypeScript compilations with different module targets, the CSS is compiled by the Sass command with source maps disabled, the documentation is generated by TypeDoc and the website by a script in the tool directory.
The version in the package file is a 5.0.0 alpha, and the repository has no GitHub releases to browse. The last push was on 2026-10-09. So the current state is a major version in progress rather than a settled release, and the HISTORY file is where the changelog lives.
The dependencies are small and tell you where the heavy lifting happens. The dropdown, menu and tabs components come from the rc-component packages, classnames handles conditional class names, lodash is used for the data manipulation, and rc-new-window is what makes a floating panel open in a separate browser window.
The examples directory is the best documentation in the repository, with runnable versions for the basic layout, the dark theme, disabled docking, divider boxes, gestures, drop modes, panel extras, new windows, save layout, advanced tab updates and controlled layouts.
Editorial conclusion
rc-dock suits a developer building an IDE like interface in React, where panels are dragged, tabs are opened and closed and the arrangement should survive a reload, since the layout is a serialisable tree rather than component state scattered through the application. It is the wrong choice for a simple set of tabs, where a tabs component is enough, and the wrong choice if you cannot accept a layout model you have to learn, because the box, panel and tab types are the whole contract. Verify first which release line you take, since the published version is a 5.0.0 alpha while the repository has no GitHub releases, check that the tab registry approach in the README matches how you already manage open tabs, and run the browser test suite in Chromium before you rely on drag and drop behaviour.
Frequently asked questions
What is rc-dock?
It is a React component library that provides a dockable layout with resizable boxes, tabbed panels, drag and drop between panels, floating panels that can open as separate browser windows, and a serialisable layout tree.
How do I control the layout from my application?
Use the uncontrolled form by passing a layout object to the defaultLayout property and let the component own it, or the controlled form by passing it to the layout property and keeping the state in your application. The saveLayout method and the onLayoutChange callback give you the current layout.
How are tabs defined?
The tabs property holds definitions keyed by id, and the layout tree references tabs by id only, with titles, content and options living in the registry. A loadTab callback can create a definition on demand, and returning null from it skips an unavailable tab.
How do I customise the theme colours?
Import the compiled light or dark stylesheet for the default look, or use the SCSS sources with the style entry point and override the variables such as the primary colour, then regenerate the distributed CSS with the build SCSS script.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ticlo-rc-dock)Was this useful?