// DesktopShell — WinUI3 layout: Toolbar + SideNav + Content + StatusBar.
// MenuBar is NOT here — it must live in the Window (Slint constraint).
// Parent provides content as @children (placed inside the content frame).
import { Colors, Spacing } from "../../tokens/theme.slint";
import { Sizes } from "../../tokens/sizes.slint";
import { NavItem } from "../types.slint";
import { ShellToolbarItem } from "../types.slint";
import { ShellToolbar } from "tool-bar.slint";
import { ShellSideNav } from "side-nav.slint";
import { ShellContentFrame } from "content-frame.slint";
import { ShellStatusBar } from "status-bar.slint";
import { DragHandle } from "../../modules/DragHandle.slint";
/// Fluent desktop shell composed of toolbar, side navigation, content frame, and status bar.
export component DesktopShell inherits VerticalLayout {
/// Navigation items rendered in the left side navigation.
in property <[NavItem]> nav-items;
/// Toolbar items rendered in the optional toolbar row.
in property <[ShellToolbarItem]> toolbar-items;
/// Controls whether the toolbar row is shown.
in property <bool> show-toolbar: false;
/// Id of the currently active content view.
in property <string> active-view: "";
/// Status text shown in the bottom status bar.
in property <string> status-text: "Ready";
/// Optional progress value shown in the status bar. Negative hides it.
in property <float> progress: -1.0;
// State
/// Private property "nav-width" used internally.
private property <length> nav-width: Sizes.panel-sm;
/// Private property "nav-collapsed" used internally.
private property <bool> nav-collapsed: nav-width <= Spacing.xl + Spacing.sm + Spacing.xs;
/// Fired when a navigation destination is selected.
callback navigate(string);
/// Fired when a toolbar action is selected.
callback toolbar-clicked(string);
spacing: Sizes.no-size;
// ── Toolbar (optional) ────────────────────────────────────────────────
if root.show-toolbar: ShellToolbar {
items: root.toolbar-items;
item-clicked(id) => { root.toolbar-clicked(id); }
}
// ── SideNav + Content (main area) ─────────────────────────────────────
HorizontalLayout {
vertical-stretch: Sizes.one;
spacing: Sizes.no-size;
ShellSideNav {
horizontal-stretch: Sizes.zero;
min-width: root.nav-width;
max-width: root.nav-width;
items: root.nav-items;
active-item: root.active-view;
collapsed: root.nav-collapsed;
navigate(id) => { root.navigate(id); }
toggle-collapsed() => {
root.nav-width = root.nav-collapsed
? Sizes.panel-sm
: Spacing.xl + Spacing.sm;
}
}
DragHandle {
min-width: Spacing.handle-thickness;
max-width: Spacing.handle-thickness;
vertical: false;
dragged(dx, dy) => { root.nav-width = clamp(root.nav-width + dx * Sizes.border-w, Spacing.xl + Spacing.sm, Sizes.panel-xxl); }
}
ShellContentFrame {
horizontal-stretch: Sizes.one;
@children
}
}
// ── StatusBar (bottom) ────────────────────────────────────────────────
ShellStatusBar {
status-text: root.status-text;
progress: root.progress;
}
}