npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@danfessler/react-dockable

v0.4.3

Published

![react-dockable-splash](https://github.com/user-attachments/assets/3465dd6d-5ea8-4249-ae9d-09e498d26797)

Downloads

17

Readme

react-dockable-splash

⚠️ This project is currently in pre-release to get early feedback. API may change.

React-Dockable

React-Dockable is a React library to create beautiful dockable tabbed interfaces for tools, dashboards, and more.

Live Demo: dockable.netlify.app

Motivation

Writing tools is hard, and half the battle is constantly redesigning your UI to accommodate for new features. This is why many companies implement robust dockable UI systems in tools like Unity, Unreal, and Photoshop, which ensures every new feature has a home and puts the user in control of their workflow.

Unfortunately, there weren't many great existing solutions for this for web, and rolling your own is complicated and expensive. React-Dockable was created to handle that complexity for you, so you can focus on shipping.

Key features

  • Beautifully polished
    React-dockable prioritizes the user experience by staying intuitive and unobtrusive. It gets out of the way of the user and what they want to do.

  • Fully customizable layouts
    Layouts are fully dynamic and user customizable right out of the box. No work necessary.

  • Simple declarative configuration
    No complicated data structures to learn, define your Layouts the React Way™ with a simple declarative component API

  • Color Theme Presets
    Dockable provides 4 beautiful color themes: Light, Medium, Dark, and Darker.

Getting Started

npm install @danfessler/react-dockable

Then import the library and default css into your project

import { Dockable } from "@danfessler/react-dockable";
import "@danfessler/react-dockable/style.css";

Basic Usage

The quickest way to get started is simply to provide Dockable with Tab children components and let the user manage their desired layout from there.

The Tab component is the core primitive of Dockable which renders your App's custom components. Each tab can be thought of as a logic collection of like-features for your app.

<Dockable.Root>
  <Dockable.Tab id="1" name="Tab 1">
    First Tab
  </Dockable.Tab>
  <Dockable.Tab id="2" name="Tab 2">
    Second Tab
  </Dockable.Tab>
  <Dockable.Tab id="3" name="Tab 3">
    Third Tab
  </Dockable.Tab>
</Dockable.Root>

By default, Tabs are displayed in a horizontal layout.

image

⚠️ Each Tab must have a unique id to avoid undefined behavior

Predefined Layouts

Children are not intended to be managed manually. Instead, they are the initial configuration of the layout and contain the definitions for each Tab which is managed internally by React-Dockable.

You can compose the initial layout using Panel, Window, and Tab components. Each nested Panel alternates between row and column flows. Windows can contain multiple Tabs. Tabs are automatically wrapped in a Window if one isn't supplied

<Dockable.Root>
  <Dockable.Tab id="view-1" name="Left">
    Left Component
  </Dockable.Tab>
  <Dockable.Panel size={3}>
    <Dockable.Tab id="view-2" name="Top">
      Top Component
    </Dockable.Tab>
    <Dockable.Window>
      <Dockable.Tab id="view-3" name="Tab 1">
        Bottom Component 1
      </Dockable.Tab>
      <Dockable.Tab id="view-4" name="Tab 2">
        Bottom Component 2
      </Dockable.Tab>
    </Dockable.Window>
  </Dockable.Panel>
</Dockable.Root>

image

💡 Panels and Windows can have defined sizes provided as Fr units. See documentation for all props.

Controlled Layouts

Dockable is uncontrolled by default, but you can control its state through the panels and onChange props to manage layouts or persist them between sessions.

function App() {
  const [layout, setLayout] = useState();

  function handleChange(newLayout) {
    // custom logic here...
    setLayout(newLayout);
  }

  return (
    <Dockable.Root orientation="row" layout={layout} onChange={handleChange}>
      {/* Layout */}
    </Dockable.Root>
  );
}

The easiest way to persist a user's layout is with the provided useDockableLocalStorage hook which will automatically save and load layouts from local storage.

import { useDockableLocalStorage } from "react-dockable";

function App() {
  const { layout, setLayout } = useDockableLocalStorage(1);

  return (
    <Dockable.Root layout={layout} onChange={setLayout}>
      {/* Layout */}
    </Dockable.Root>
  );
}

⚠️ Always increase the version argument whenever you make changes to the layout as any missing Tab id will throw an exception

Component Props

Dockable.Root

| Prop | Value | description | | ------------ | ------------------------------------------- | ------------------------------------------------------------------------ | | orientation? | "row" \| "column" | The direction panels will be arranged. Defaults to "row". | | layout? | LayoutNode[] | Optional controlled layout state. | | onChange? | (panels: LayoutNode[]) => void | Callback fired when layout changes in controlled mode. | | children | Panel \| Window \| Tab | The panels and windows to render. | | gap? | number | The pixel spacing between panels. | | radius? | number | The corner radius of the windows | | theme? | "light" \| "medium" \| "dark" \| "darker" | Color presets. Defaults to light or dark based on user's device settings |

Dockable.Panel

| Prop | Value | description | | ------------ | ------------------------ | ---------------------------------------------------------------------------------- | | orientation? | "row" \| "column" | The direction child panels will be arranged. Defaults to the inverse of its parent | | size? | number | Optional size in Fr units. defaults to 1 | | children | Panel \| Window \| Tab | The layout to render. |

Dockable.Window

| Prop | Value | description | | --------- | -------- | ---------------------------------------------------- | | size? | number | Optional size in Fr units. Defaults to 1 | | selected? | number | Index of the initially selected tab. Defaults to 0 | | children | Tab | The tabs to render. |

Dockable.Tab

| Prop | Value | description | | --------- | ----------- | ------------------------------ | | id | string | Unique identifier for the tab. | | name | string | Display name shown in the tab. | | children? | ReactNode | The content to render. |

Layout State

You can also manage the layout state object directly to define layouts or to add custom functionality. Window children ids must match an id prop of a child Tab component. When Dockable first mounts, it serializes the children component layout into this format.

Example Layout Object:

[
  {
    type: "Window",
    id: "window-0",
    children: ["tab-1"],
    size: 1,
    selected: "tab-1",
  },
  {
    type: "Panel",
    id: "panel-3",
    children: [
      {
        type: "Window",
        id: "window-1",
        children: ["tab-2"],
        size: 1,
        selected: "tab-2",
      },
      {
        type: "Window",
        id: "window-2",
        children: ["tab-3", "tab-4"],
        size: 1,
        selected: "tab-3",
      },
    ],
    size: 3,
  },
];

⚠️ Note: We will soon be releasing an imperative API to make manipulating this object easier.

The Layout object is an array of LayoutNodes

LayoutNode

PanelNode | WindowNode

PanelNode

| Property | Value | | ------------ | -------------------------------------------------------------------------------- | | id | stringUnique identifier for the panel. | | type | "Panel"Discriminator to identify panel nodes. | | orientation? | "row" \| "column"The direction child panels will be arranged. | | size? | numberOptional size in Fr units. Defaults to 1. | | children | LayoutNode[]Array of child panel and window nodes that make up this panel. |

WindowNode

| Property | Value | | -------- | -------------------------------------------------------- | | id | stringUnique identifier for the window. | | type | "Window"Discriminator to identify window nodes. | | selected | stringID of the currently selected tab. | | children | string[]Array of tab IDs contained in this window. | | size? | numberOptional size in Fr units. Defaults to 1. |

License

This project is free to use for non-commercial purposes.
For commercial licenses, become a Github Sponsor.
See LICENSE.md for more details