Title Bar
A window title bar for free windows — PC/2in1 and tablets in 自由多窗 / 电脑模式. It replaces the system title bar with a SparkUI one: icon, title, slots, caption buttons in the theme, drag to move and double-click to maximize. On phones and full-screen windows it disappears by itself.
The title bar is window chrome (caption buttons, dragging, maximize, decor APIs) that only exists in a HarmonyOS free window, so the examples on this page show code only.
Preview
Detached previews never touch the real window; caption presses only report the action.
STitleBar({ title: 'SparkUI Gallery', icon: 'sparkles', systemButtons: 'custom' }) {
SButton({ variant: 'ghost', sizing: 'icon-sm', icon: 'search', label: 'Search' }) // actions slot
}
// systemButtons:
// 'keep' — system buttons stay (restyled via setDecorButtonStyle), the bar reserves getTitleButtonRect
// 'custom' — system buttons hidden, SparkUI draws its own (minimize / maximize·restore / close)
// 'hidden' — no caption buttonsSlots
The trailing closure holds the actions; sidebarController adds a sidebar toggle at the start; startBuilder / leadingBuilder / centerBuilder take wrapBuilder(globalBuilder) for anything else. Regions never start a window drag; the free space around them does.
// regions take wrapBuilder(globalBuilder); a component keeps the region's state
@Builder function noteMenu() { SButton({ variant: 'ghost', sizing: 'icon-sm', icon: 'menu', label: 'Menu' }) }
@Builder function noteTabs() { NoteTabs() } // @ComponentV2 struct with its own @Local tab
STitleBar({
title: 'Notes', icon: 'file-text',
sidebarController: this.sidebar, // SSidebarTrigger before the icon
leadingBuilder: wrapBuilder(noteMenu), // after the title
centerBuilder: wrapBuilder(noteTabs) // centred
}) {
SButton({ variant: 'ghost', sizing: 'icon-sm', icon: 'share', label: 'Share' }) // trailing actions
}
// every region is no-drag; the free bar area drags the window, double-click maximizes / restores.This window
Live state from SparkWindowChrome. "Apply" hides the system title bar of this window and shows STitleBar at the top of the gallery; it needs a free window.
Setup
Bind the main window once, then place the bar on top of the page.
// EntryAbility.onWindowStageCreate — inside the loadContent callback (decor APIs need it):
windowStage.loadContent('pages/Index', (err) => {
if (err.code) { return; }
SparkWindowChrome.init(windowStage, this.context);
});
// Page: the bar lives outside the scrolling content. On phones / outside free windows /
// in full screen it renders nothing, and the system title bar comes back when it unmounts.
Column() {
STitleBar({ title: 'My App', icon: 'sparkles' })
MyContent().layoutWeight(1)
}