Skip to content
Cynosurev0.5.0
SearchStorybookGitHubnpmColour mode: System. Switch to Light

Components / Structure

TitleBar

The title bar of an installed app that draws its own: a frameless Electron window, or an installed web app using Window Controls Overlay. The whole bar drags the window, every control inside stays clickable, and the app's window controls sit at its end.

Default

When to useLink to "When to use"

  • A desktop app without the system's title bar: Electron with frame: false or titleBarStyle: "hidden", or a web app whose manifest asks for window-controls-overlay.
  • The app's menus and title in the window's top edge, where people expect to drag the window.

Use something else when:

UsageLink to "Usage"

tsx
Copy
import { IconButton, Menubar, TitleBar } from "@arshad-shah/cynosure";
import { settings } from "@arshad-shah/cynosure/icons";

<TitleBar
  label="Verql"
  leading={<Menubar label="Application" menus={menus} size="sm" onSelect={run} />}
  trailing={<IconButton icon={settings} label="Settings" variant="ghost" size="sm" />}
  controls={{
    minimize: () => ipc.minimize(),
    toggleMaximize: () => ipc.toggleMaximize(),
    close: () => ipc.close(),
    maximized,
  }}
>
  orders.sql — Verql
</TitleBar>

The title is centred on the whole bar while the leading and trailing content leave room, and ends in an ellipsis when they do not.

Each platformLink to "Each platform"

Each platform, table 1
WhereWhat to pass
Windows and Linux, framelesscontrols: the bar draws minimize, maximize or restore, and close
macOS, titleBarStyle: "hidden"leadingInset={80} to clear the traffic lights, and onHeightChange to place them (Electron's setWindowButtonPosition)
Window Controls Overlay (installed web apps, Electron's titleBarOverlay)overlay: the system draws the controls, the bar takes the area it leaves

Window controlsLink to "Window controls"

controls takes { minimize, toggleMaximize, close, maximized }, and each button shows only when its callback is given (a settings window may have only close). When maximized is true the middle button shows the restore icon and is named Restore. Keep maximized in step with the window, including changes the system makes (snapping, double-clicking the bar).

Maximized shows restore

The controls are a part of TitleBar rather than a component of their own: they have one right place, at the window's edge after the trailing content, and are exactly as tall as the bar.

Overlay modeLink to "Overlay mode"

With overlay, the bar is fixed to the window's title bar area, read from env(titlebar-area-x), env(titlebar-area-y), env(titlebar-area-width) and env(titlebar-area-height), so it never runs under the controls the system draws, on whichever side it draws them. Where those values are missing (a browser tab, an engine without the overlay) it falls back to the top of the window, the full width and the --cy-title-bar-height token. Offset the page's content by the height onHeightChange reports.

PropsLink to "Props"

Every prop of TitleBar
PropWhat it doesTypeDefault
children
The title, centred on the bar (it ends in an ellipsis when there is no room). Any content: text, a SearchField.ReactNode
leading
Content at the inline start, such as a Menubar or the app's mark.ReactNode
trailing
Content at the inline end, before the window controls, such as IconButtons.ReactNode
leadingInset
Pixels kept clear at the inline start for window buttons the system draws over the bar (macOS traffic lights: about 80). A fixed number, since the system draws them at a fixed size whatever the theme's scale. Default 0.number0
overlay
Window Controls Overlay (installed web apps, Electron's titleBarOverlay): the bar is fixed to the window's title bar area, env(titlebar-area-x/y/width/height), so it never runs under the controls the system draws. Without those values it falls back to the top of the window, full width and the height token. Offset the page's content with onHeightChange. Default false.booleanfalse
controls
Window controls drawn by the app (Linux, frameless windows): minimize, maximize or restore, and close, as tall as the bar at its inline end. Leave out where the system draws them (macOS, Window Controls Overlay).TitleBarControls
onHeightChange
Called with the bar's height (border box, in pixels) on mount and whenever it changes, to offset content under an overlay bar or to place the system's own window buttons (Electron's traffic-light position).((height: number) => void)
label
Accessible name of the bar (a group). Default "Title bar".string"Title bar"
labels
Names of the window controls, for other languages.Partial<TitleBarLabels>
className
Layout only.string
style
Layout only. Restyle through --cy-title-bar-* tokens.CSSProperties

Generated from the type definitions in @arshad-shah/cynosure 0.5.0.

Behaviour and accessibilityLink to "Behaviour and accessibility"

Behaviour and accessibility, table 2
InputResult
Drag on the bar, the title or empty spaceMoves the window (app-region: drag, Chromium-based hosts only)
Click, Enter or Space on a controlCalls minimize, toggleMaximize or close
TabMoves through the bar's controls in reading order, the window controls last (minimize, maximize, close)
  • Dragging: the bar has app-region: drag (and -webkit-app-region). Interactive elements inside it, whoever rendered them (links, buttons, fields, labels, anything with a tabindex or a widget role such as a menubar's titles), get no-drag, so they stay clickable.
  • Roles: the bar is a group named by label (default "Title bar"). The controls are buttons named Minimize, Maximize or Restore, and Close, each with a tooltip; rename them through labels.
  • Height: onHeightChange reports the border-box height on mount and whenever it changes (ResizeObserver), not again for the same height.
  • Right to left: the bar mirrors. leadingInset is at the inline start (the right) and the controls at the inline end (the left), close outermost, as Windows draws its caption buttons in right-to-left languages.
  • Isolation: it never writes to <html> or <body>; overlay mode positions the bar itself. Works inside a shadow root.

TouchLink to "Touch"

Each control is at least 24px to press, and 44px on coarse pointers; a tap acts.

ThemingLink to "Theming"

Tokens: --cy-title-bar-height, --cy-title-bar-bg, --cy-title-bar-ink, --cy-title-bar-border, --cy-title-bar-padding-inline, --cy-title-bar-gap, --cy-title-bar-title-font-size, --cy-title-bar-control-width (46px by default, as tall as the bar), --cy-title-bar-close-hover-bg and --cy-title-bar-close-hover-ink (close's danger fill on hover) and --cy-title-bar-z (overlay mode).

ts
Copy
createTheme({ components: { titleBar: { height: "32px", controlWidth: "46px" } } });

Menubar · AppShell · IconButton · Toolbar

These examples run Cynosure 0.5.0 (commit 50ce30b), the version on npm.

Getting started
Theming
Icons
Accessibility
Code editors and highlighters
Using Cynosure without React
Build-tool adapters
Components
Accordion
AppShell
AspectRatio
Breadcrumbs
Calendar
Card
Container
Disclosure
Divider
DocumentViewport
Grid
Inline
PageHeader
PanZoomCanvas
ScrollArea
SideNav
SortableList
SplitPane
Stack
StatusBar
Tabs
TitleBar
Toolbar
Tree
VirtualList
ZoomControls
Announcer
Avatar
Badge
CodeBlock
DescriptionList
EmptyState
ErrorBoundary
Field
Heading
IconTile
Image
Kbd
List
LoadingDots
Notice
ProgressBar
Prose
Skeleton
Stat
Steps
Table
Text
Button
Checkbox
Checklist
ColorField
ColorSwatches
Combobox
CompareSlider
CopyButton
DateField
FileDrop
IconButton
KeyValueEditor
Link
NumberField
Pagination
PathField
RadioGroup
SearchField
SegmentedControl
Select
SelectionFrame
SignaturePad
Slider
Switch
TagInput
TextArea
TextField
ThemeToggle
TimeField
ButtonBase
ChoiceBase
DialogBase
FileInputBase
HiddenValue
Icon
InputBase
LinkBase
LiveRegion
TextAreaBase
ChatMessage
Choice
DataGrid
DeviceFrame
HighlightedText
HotkeyField
ListRow
OptionList
OverlayFrame
QRCode
RowActions
Section
SiteFooter
SiteHeader
SkipLink
SortButton
VisuallyHidden
CommandPalette
ContextMenu
Dialog
FloatingToolbar
HoverCard
Menu
Menubar
Popover
ProgressOverlay
Sheet
Toast
Tooltip
Changelog