Skip to content

texodus/regular-layout

Repository files navigation




Build Status NPM Version Bundlephobia (Minified)

A library for resizable & repositionable panel layouts.

  • Zero depedencies, pure TypeScript, tiny.
  • Implemented as a Web Component, interoperable with any framework.
  • Zero DOM mutation at runtime, implemented entirely by generating using CSS grid rules.
  • Supports arbitrary theming via CSS variables and ::part.
  • Supports async-aware container rendering for smooth animations even when rendering ovvurs over an event loop boundary.
  • Covered in bees.

Demo

Installation

npm install regular-layout

Quick Start

Import the library and add <regular-layout> to your HTML. Children are matched to layout slots by their name attribute.

<script type="module" src="regular-layout/dist/index.js"></script>

<regular-layout>
    <div name="main">Main content</div>
    <div name="sidebar">Sidebar content</div>
</regular-layout>

For draggable, tabbed panels, use <regular-layout-frame>:

<regular-layout>
    <regular-layout-frame name="main">
        Main content
    </regular-layout-frame>
    <regular-layout-frame name="sidebar">
        Sidebar content
    </regular-layout-frame>
</regular-layout>

Panels must be added and remove programmatically (e.g they are not auto-registered):

const layout = document.querySelector("regular-layout");

// This adds the panel definition to the layout (and makes it visible via CSS),
// but does not mutat the DOM.
layout.insertPanel("main");
layout.insertPanel("sidebar");

// This removes the panel from the layout (and hides it via CSS) but does not
// mutate the DOM.
layout.removePanel("sidebar");

Save/Restore

Layout state serializes to a JSON tree of splits and tabs, which can be persisted and restored:

const state = layout.save();
localStorage.setItem("layout", JSON.stringify(state));

// Later...
layout.restore(JSON.parse(localStorage.getItem("layout")));

restore() dispatches a cancelable regular-layout-before-resize event before applying the new state. Call preventDefault() to suspend the update, then layout.resumeResize() when ready:

layout.addEventListener("regular-layout-before-resize", (event) => {
    event.preventDefault();
    // ... prepare for resize ...
    layout.resumeResize();
});

The restore() API can also be used as an alternative to insertPanel/removePanel for initializing a <regular-layout>.

Theming

Themes are plain CSS files that style the layout and its ::part() selectors, scoped by a class on <regular-layout>. Apply a theme by adding its stylesheet and setting the class:

<link rel="stylesheet" href="regular-layout/themes/chicago.css">

<regular-layout class="chicago">
    ...
</regular-layout>

<regular-layout-frame> exposes these CSS parts:

Part Description
titlebar Tab bar container
tab Individual tab
active-tab Currently selected tab
close Close button
active-close Close button on the active tab
container Content area
regular-layout.mytheme regular-layout-frame::part(titlebar) {
    background: #333;
}

regular-layout.mytheme regular-layout-frame::part(active-tab) {
    background: #fff;
    color: #000;
}

See the example themes/ directory for examples of how to write a complete theme for <regular-layout> and regular-layout-frame>.

Events

Event Detail Cancelable Description
regular-layout-before-resize { calculatePresizePaths() } Yes Fired before any layout change. Cancel to suspend until resumeResize().
regular-layout-update Layout No Fired after layout state is updated.
layout.addEventListener("regular-layout-update", (event) => {
    console.log("New layout:", event.detail);
});

About

A regular CSS `grid` container

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors