ComponentsPage layouts

Editor layout

The "edit one thing" page: a sticky publish bar (back, title, save status, actions), a wide content canvas, and a side panel of folding meta boxes — status, permalink, categories, SEO — that remember whether they're open. Below 44rem (704px) of its own width the panel opens as a non-modal sheet; focus mode hides the panel and fades the bar.

CSS grid + container queries · Radix Collapsible · Tabs · Sheet components/editor-layout.tsx, styles/navigation.csstheme · material · accent · density · font
Five dishes from our spring menu

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { EditorLayout, EditorBar, SaveStatus, EditorCanvas, EditorPanel, EditorPanelSection } from "@vamos-ui/react";

<EditorLayout>
  <EditorBar
    back={{ href: "/posts", label: "Posts" }}
    title={title}
    status={<SaveStatus state="saved" at={savedAt} />}
    actions={<Button size="sm" variant="primary">Publish</Button>}
  />
  <EditorCanvas width="prose">{editor}</EditorCanvas>
  <EditorPanel>
    <EditorPanelSection id="status" title="Status & visibility" summary="Draft · Public" defaultOpen>…</EditorPanelSection>
    <EditorPanelSection id="permalink" title="Permalink" summary="/blog/spring-menu">…</EditorPanelSection>
  </EditorPanel>
</EditorLayout>

Autosave scheduling (debounce, conflicts) is your app's job — feed the result into SaveStatus.

Examples

Save status

Every SaveState. A polite status; the error is an alert with Retry. "Saved 2 min. ago" uses Intl.RelativeTimeFormat. While dirty or saving it guards beforeunload (guard={false} to opt out).

dirty
Unsaved changes
saving
Saving…
saved
Saved 2 min. ago
saved (hours)
Saved 3 hr. ago
error
Couldn't save
offline
Offline · changes kept locally

Panel tabs

tabs splits the panel into Document / Block; put each tab's sections in an EditorPanelContent. tone="scene" drops the canvas surface.

Renewal reminder — 30 days

Hi {{first_name}},

Your Northwind plan renews on {{renewal_date}}. Nothing changes unless you want it to — here's a summary of what you're using today.

12 seats · Analytics add-on — $36,000 per year

Reply to this email or book a call with {{owner_name}} if you'd like to review your plan.

Focus mode

Hides the panel and fades the bar until the pointer moves; ⌘/Ctrl+Shift+F toggles, Esc leaves. Hide the App shell sidebar from onFocusModeChange.

Senior product designer

Senior product designer

You'll own the design of our scheduling product end to end — from the first sketch with a customer to the last pixel in production. We're a team of nine designers across Istanbul, Lisbon and remote, and we ship every week.

You have five or more years of product design experience, a portfolio that shows how you think, and you're comfortable presenting to customers.

Narrow and read-only

On narrow layouts the panel toggle opens a non-modal sheet, secondary actions hide (mirror them in menu). readOnly hides actions and disables every panel control.

Atlas reseller agreement

Reseller agreement

1. Territory. Atlas Distribution is appointed as a non-exclusive reseller of the Products in the EMEA region for an initial term of 24 months.

Version 3 · signed

You're viewing a locked version

Signed on Oct 14, 2026. Restore it to make changes.

1. Territory. Atlas Distribution is appointed as a non-exclusive reseller…

API

EditorLayout

PropTypeDefault
panelOpen · defaultPanelOpen · onPanelOpenChange
Panel visibility; drives the sheet on narrow layouts.
booleantrue
panelWidth · defaultPanelWidth · onPanelWidthChange
Panel width in px.
number320
resizable
Drag or arrow-key the panel edge.
booleanfalse
focusMode · defaultFocusMode · onFocusModeChange
Distraction-free mode.
booleanfalse
readOnly
Locked version: bar actions hidden, panel disabled.
booleanfalse
scroll
Page scroll with sticky bar/panel, or fill the parent with independently scrolling panes.
"page" | "panes""page"
stickyTop
Sticky offset in page mode.
number | string"var(--topbar-h)"
shortcuts
⌘/Ctrl+Shift+, toggles the panel; ⌘/Ctrl+Shift+F focus mode.
booleantrue
labels
Overrides for the editor namespace.
EditorLayoutLabels—

EditorBar

PropTypeDefault
back
Back link; the label hides on narrow layouts.
{ href: string; label: string }—
title · status
Document title and a SaveStatus.
ReactNode—
actions
Primary actions, always shown (hidden when readOnly).
ReactNode—
secondaryActions
Hidden below 640px — mirror them in menu.
ReactNode—
menu
"⋯" menu at the end.
MenuEntry[]—
panelToggle
Panel toggle (aria-expanded, aria-controls).
booleantrue
focusToggle
A visible focus-mode button.
booleanfalse

SaveStatus

PropTypeDefault
state
Where the changes are.
"idle" | "dirty" | "saving" | "saved" | "error" | "offline"—
at
Last save, for "Saved 2 min. ago".
Date | number—
onRetry
Retry button in the error state.
() => void—
guard
beforeunload warning while dirty or saving.
booleantrue
now
Fixed reference time (docs, tests).
Date | number—

EditorCanvas

PropTypeDefault
width
720 / 1080 px / full.
"prose" | "wide" | "full""prose"
tone
Canvas background.
"surface" | "scene""surface"
notice
Banner above the content (read-only Alert).
ReactNode—
loading
Skeleton title and paragraphs.
boolean—

EditorPanel · EditorPanelContent

PropTypeDefault
tabs
Panel tabs; EditorPanelContent value matches an id.
{ id: string; label: string }[]—
value · defaultValue · onValueChange
Selected tab.
string—
footer
Sticky footer inside the panel.
ReactNode—
aria-label
Name of the complementary landmark.
string"Settings"

EditorPanelSection

PropTypeDefault
id
Open state is remembered per id (localStorage).
string—
title · summary
Header and the one-line summary shown while folded.
ReactNode—
defaultOpen · open · onOpenChange
Open state.
booleanfalse
actions
Controls next to the toggle.
ReactNode—
headingLevel
Heading level.
2 | 32