Window Frame
The frame of a single-pane window and its header row. The content coat over the window coat, and a 40 px header that shares its line with the macOS traffic lights, carries the window's title and drags the window.
Notes
- Open with the two-camera podcast scene.
- Show the Shure MV7 gain staging, then the noise cleanup.
- Mention Thursday's livestream at 8 PM.
Installation
$ pnpm dlx shadcn@latest add @videorc/window-frameUsage
import { WindowFrame, WindowHeader } from "@/components/window-frame";<WindowFrame className="flex flex-col">
<WindowHeader platform={platform} title="Notes">
<PinWindowButton onPinnedChange={setPinned} pinned={pinned} />
</WindowHeader>
…
</WindowFrame>Use it for a single-pane window: Stream Manager, Notes, the Captions reader. Lead with one WindowHeader: the title as the window's h1, an optional quiet meta fact after it, and the window's few controls at the end. Stream Manager keeps its row to the title: the Stream Manager block is that window, whole.
Don't use it in the main window, where each page is a Pane with its Toolbar. Don't stack a third coat inside it either: the frame is the window's one content coat.
Examples
A fact and controls, off macOS
meta is a quiet fact after the title, such as the Captions reader's state. The children are the window's controls, at the end of the row and out of the drag band. Off macOS the native frame owns the title bar, so the row pads like any other.
Captions
Welcome back, everyone.
Today we're building a scene for a two-camera podcast.
First, add both cameras in Sources.
The traffic lights
Give the window titleBarStyle: "hiddenInset", with the traffic lights centred in the 40 px header row. On macOS the header pads 88 px (TRAFFIC_LIGHT_GUTTER_CLASS): the three lights end 74 px in, which leaves the title 14 px of air. It keeps the gutter in fullscreen too. macOS draws the lights over the header when the title bar reveals on hover, and dropping the gutter there would put them on the title.
Pass the platform you know, such as Electron's process.platform. Without one, the header reads data-platform on <html>, then the user agent. A server can't know the reader's platform, so server-rendered markup has no gutter and the client adds it as it hydrates.
Theming
| Token or attribute | Meaning |
|---|---|
bg-glass-content | The content coat over the window coat |
h-toolbar | The 40 px header |
pl-[88px], pl-3 | The traffic-light gutter on macOS, a plain row elsewhere |
[-webkit-app-region:drag] | The header moves the window; its controls opt out with no-drag |
WINDOW_TITLE_CLASS | The title recipe, 14 px / 600, shared with the Toolbar |
data-slot | window-frame, window-header, window-header-title, window-header-meta, window-header-actions |
Accessibility
The title is the window's h1. meta is plain text after it: if it changes while the window is open (Listening, Paused), put it in a polite live region. Each control in the header needs a name; Pin Window Button brings its own.
API reference
WindowHeader
Every header attribute, plus:
Prop
Type
WindowFrame
Prop
Type
useTrafficLightGutter
useTrafficLightGutter(platform?) returns "pl-[88px]" on macOS and "pl-3" elsewhere, for a header row of your own.
Navigable Row
A fact row of icon, label and value. When the value's home is another page, the row becomes a button with a chevron that jumps there, and a hint lists the facts a short value stands for.
Status Bar
The window's 26 px status bar. The session state on the left, and quiet shortcut hints on the right that stay clickable, each pressed while the window it opens is open.