Frame Design System

Layout

How a whole screen is assembled, and the parts it is assembled from — every surface plugs into one three-panel shell, and each part below carries its spec and a live demo in the same place. Single source: content/layoutTemplates.tsx.

App Shell — Three-Panel Structure

App.tsx

Every WorkPal view composes into a single three-panel shell: NavPanel (global navigation), ConversationPanel (primary working surface), and InspectorPanel (contextual detail). Foundations tokens flow through all three; edit a color once and every panel updates.

NavPanel
260 / 64 px
ConversationPanel
flex-1
InspectorPanel
280 / 504 px
NavPanel260 / 64 px

Global navigation, view switching, recents, profile

SidebarMiniSidebar
Sidebar · 260px (drag 220–400) · sidebar-bg
MiniSidebar · 64px · collapsed
ConversationPanelflex-1

The user’s primary working surface — chat, page content, forms

ChatPanelPageLayout (+ any page)
flex-1 · centered content max-w-[863px]
InspectorPanel280 / 504 px

Contextual detail to the right: document, task context, side cards

DetailPanelTaskContextPanelSplitView side
DetailPanel · 504px
TaskContextPanel · 280px
Overlays on narrow viewports

Rule: a new feature is a slot in one of these three panels — never a new top-level chrome element. If you need a new panel primitive, build it in shared.tsx and register it under the relevant panel here.

PageLayout

#MasterUsed in: Wingman 26 · WorkPal 15

Page shell — pinned single-row header (toggle + title + rightSlot/actions) that the filters + body scroll beneath (frosted, like the header on this site) + optional pinned footer. Wraps HeaderBar internally.

PageLayout owns the title + filters + scrollable body. Pass a `footer` for a pinned ChatInput.

Demo content row.
Demo content row.
Demo content row.
Demo content row.
Demo content row.
Demo content row.
Demo content row.
Demo content row.

Spec

shared.tsx

Canonical page shell. A pinned single-row header (sidebar toggle · title · flexible gap · rightSlot search/actions · onNewChat · headerRight · onBack) stays pinned at the top as a frosted layer while the body scrolls beneath it, and an optional footer stays pinned to the bottom. The title lives on the pinned row and is truncated to one line — pass a short label, not prose. Edit the spec in shared.tsx once — every page updates.

Pinned header row: px-4 sm:px-8 · pt-6 pb-3 · title inline (truncated) · .frosted-header
Horizontal pad: px-4 sm:px-8
Header → body: header pb-3 + body pt-3
filters → content: mb-8
maxWidth 'full': no limit
maxWidth 'reading': 863px centered
maxWidth 'wide': 1040px centered
Used by · WorkPal
OverviewPageLibraryPageConnectorsPageDesignSystemPageOnboardingProjectPageComingSoonPage
Used by · Wingman
AboutPageAdminObservabilityPageAgentConfirmPageAgentVoicePreviewPageChatPageCheckoutCompletePageCheckoutPageDateArrangePageDateDetailPageDatesPageDesignSystemPageMatchDetailPageMatchesPageNotFoundPagePrivacySettingsPageProfilePhotosPageSSOCallbackPageSelfSnapshotPageSettingsPageSignInPageSignUpPageTokenSettingsPageVideoFeedbackPageVideoInvitePageVideoRoomPage

HeaderBar

#MasterUsed in: Wingman 6 · WorkPal 2

Canonical top toolbar. Sidebar toggle (when closed) + optional left/right slots. Used by every top-level shell.

Project · Wingman
Page content lives below the header.

Spec

shared.tsx

The pinned top row. Bare — as ChatPanel and the Wingman chat/quiz shells use it — it's just the sidebar-toggle button (only when the sidebar is closed) + optional left/right slots. DS-029: the toggle glyph is not fixed; each product supplies it through NavToggleIconProvider (WorkPal shows a panel-left icon, Wingman a hamburger). DS-080: PageLayout renders through HeaderBar, passing title / rightSlot / widthClass / padX so the page title sits inline on the pinned row; bare consumers pass none of these and render exactly the toolbar they always did.

Props: sidebarOpen, onToggleSidebar, headerRight, title, titleAs, rightSlot, widthClass, padX
Used by · WorkPal
ChatPanel
Used by · Wingman
ChatPageChatsPageDesignSystemPageOnboardingPageQuizChatPageQuizPageSelfTestChatPage

SplitView

#MasterUsed in: Wingman 0 · WorkPal 4

Two-column shell that flips inline ↔ overlay based on container width (ResizeObserver, not viewport). Used by ProjectPage, ChatPanel + DetailPanel, TaskContextPanel.

Main column

Resize this card horizontally to see the panel collapse to overlay.

Side panel

SplitView decides inline ↔ overlay based on container width.

Spec

shared.tsx

Main column + collapsible side column. Auto-switches to overlay mode when the CONTAINER is too narrow to fit both inline — DS-029: this used to say "viewport". It is measured with a ResizeObserver on SplitView's own element, which is deliberately agnostic of viewport size, sidebar width and collapsed state.

Props: side, sideOpen, onCloseSide, sideWidth, mainMinWidth
Used by · WorkPal
ProjectPageLibraryPage (detail panel)
Used by · Wingman
DesignSystemPage (showcase)

SidePanelHeader

#MasterUsed in: Wingman 0 · WorkPal 5

Canonical header row for a side panel. Title + optional children + close button (X or panel-right collapse icon).

Inspector

Collapsible

Spec

shared.tsx

Shared header row for any side panel. Unifies close-button size (40px rounded-xl), hover, and typography across every panel.

Props: title, onClose, closeIcon ('x' | 'panel-right'), closeLabel
Used by · WorkPal
ProjectPage side panelTaskContextPanelDetailPanel
Used by · Wingman
DesignSystemPage (showcase)

SidePanelBody

#MasterUsed in: Wingman 0 · WorkPal 3

Scrollable conversation inspector body with spacing and an automatic scrollbar.

View source

Requires React 19, ReactDOM 19, TypeScript and lucide-react 1.14.0. Import frame.css once and use a frame-root wrapper; set its background to var(--color-bg-page) and color to var(--color-text-primary), or supply a matching host surface; add dark to an ancestor for dark mode.

Scrollable body container — pairs with SidePanelHeader. Holds a vertical stack of SideCards.

Side panel

notes.md · 4 KB

Spec

shared.tsx

Scrollable body that pairs with SidePanelHeader and holds a vertical stack of SideCards. Single source of truth for right-panel L/R padding (px-3) and inter-card gap (gap-4) — switching between project view and task view no longer shifts content horizontally.

Props: children. Padding / gap are intentionally not configurable — that's the point.
Used by · WorkPal
ProjectPage side panelTaskContextPanel
Used by · Wingman
No pages yet

SideCard

#MasterUsed in: Wingman 0 · WorkPal 6

Collapsible section inside a right-column side panel — no panel fill, border or radius; sections are separated by a fading 1px rule. Pairs with SidePanelHeader / SidePanelBody.

Pre-fetch the user's calendar and reference last week's meeting notes.

Spec

shared.tsx

Collapsible section inside a right-column side panel. DS-029: this used to say "card" — it has no panel fill, no border and no radius; sections are separated by a 1px rule along the bottom edge that fades out at both ends (side-card-divider, with last:bg-none on the final one). Header with title + optional icon + optional add affordance + chevron.

Props: title, icon, hasAdd, defaultOpen
Used by · WorkPal
ProjectPage (Instructions/Scheduled/Files/Context)TaskContextPanel
Used by · Wingman
DesignSystemPage (showcase)

ShellGlow

#MasterUsed in: Wingman 1 · WorkPal 1

Dark-mode background glow: one rotating field carrying all three color gradients, turning together around the screen center — never changing brightness, color or size. Mount once per app root — never per `.app-shell-bg` surface — so every dark-mode shell shares one animation clock instead of a second instance rotating out of phase.

Purple · --shell-glow-purple
25%
Orange · --shell-glow-orange
30%
Blue · --shell-glow-blue
20%

% is today's brightness — a ceiling that never changes. The three glows keep their positions relative to each other and rotate together as one field around the screen center, 60 seconds per full turn, clockwise, at a constant speed. prefers-reduced-motion freezes the field at today's rest position (0° = 360°, so the freeze frame is never mid-turn).

ResizeHandle

#MasterUsed in: Wingman 1 · WorkPal 2

User-draggable column width (useResizableWidth + ResizeHandle). The products' NavPanel defaults to 260px, drags 220–400px and is remembered per product; this demo uses a smaller range. Drag the right edge, or focus it and use ←/→, Home/End; Enter or double-click resets.

Navigation

160px

Main content