Skip to Content
BlocksApplication chrome

Application chrome

ApplicationShellBlock, PageHeaderBlock, WorkspaceSwitcherBlock and CommandPaletteBlock compose into one application frame. Each block’s own page carries its full prop contract, states and verification record; this page is about putting them together.

The composition

import { useState } from "react"; import { ApplicationShellBlock, PageHeaderBlock, WorkspaceSwitcherBlock, CommandPaletteBlock, } from "@raydenui/ui/blocks"; const workspaces = [ { id: "studio", name: "Design studio", initials: "DS" }, { id: "product", name: "Product team", initials: "PT" }, ]; export function Workspace() { const [workspaceId, setWorkspaceId] = useState("studio"); return ( <ApplicationShellBlock brand="Acme" brandHref="/" navSections={[ { id: "workspace", label: "Workspace", items: [ { id: "overview", label: "Overview", href: "/overview", current: true }, { id: "projects", label: "Projects", href: "/projects" }, ], }, ]} switcher={ <WorkspaceSwitcherBlock current={workspaces.find((item) => item.id === workspaceId)} workspaces={workspaces} onSelect={setWorkspaceId} /> } search={ <CommandPaletteBlock items={[ { id: "overview", label: "Overview", href: "/overview" }, { id: "projects", label: "Projects", href: "/projects" }, ]} shortcut={{ key: "k", modifier: "mod", hint: "⌘K" }} /> } > <PageHeaderBlock title="Overview" variant="plain" description="A clear view of your current work." meta={[{ id: "workspace", label: "Workspace", value: workspaceId }]} actions={[ { id: "projects", label: "View projects", href: "/projects", priority: "primary" }, ]} /> <section aria-label="Current work" className="py-6"> Your application content </section> </ApplicationShellBlock> ); }

What composing them changes

One heading outline. The shell’s section labels default to h2 and the page header owns the h1. Drop the page header to headingLevel="h2" only if something else already owns the page heading, and do not repeat the page title as the first heading inside your content.

One scroll region. Leave mainScroll="page" so the palette overlay and the workspace do not fight two scrollbars. mainScroll="region" needs a bounded height through className.

The page gutter. Use variant="plain" on the page header inside the shell’s existing gutter rather than relying on negative margins.

Slots, not duplicates. search and switcher each keep one mounted instance at every width, so neither is dropped from the collapsed arrangement. On a narrow shell the workspace picker and tools stay together in the top bar and search wraps onto its own row.

Nested dismissal. Escape dismisses a child popover without also dismissing the parent collapsed navigation, so a workspace picker inside the collapsed panel behaves as expected.

Compact mobile context. Secondary page metadata collapses behind the Page details disclosure below 640px of container width, and secondary actions move into the overflow disclosure. Set collapseMetaOnSmallScreens={false} where metadata is essential.

Preview

The Storybook group Blocks / Compositions / Application Chrome combines all four blocks with overview, tasks, supplier and profile content, across eight stories: FullChrome, PaletteOverChrome, SwitchWorkspace, NarrowChrome, BoundedScrollChrome, DarkChrome, CustomSurfaceChrome and ShortcutChrome.

Demo data and callbacks are illustrative. These blocks do not authenticate users and do not persist workspace changes — connect your own application logic.

Last updated on