regular-layout
v0.4.0
Published
A regular CSS `grid` container
Readme
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
gridrules. - 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-layoutQuick 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);
});