Window#
CoWindow + CoWindowNavigator together form a desktop-style window
manager. Windows are draggable by their title bar, resizable from every
edge and corner, snap to screen edges, and support minimize / maximize /
always-on-top layers — identical API and behaviour on Flutter and Web.
Web
Flutter
Loading Flutter...
class WindowDefaultExample extends StatefulComponent {
const WindowDefaultExample({super.key});
@override
State<WindowDefaultExample> createState() => _WindowDefaultExampleState();
}
class _WindowDefaultExampleState extends State<WindowDefaultExample> {
late List<CoWindow> _windows = [
CoWindow(
bounds: const CoreWindowRect.fromLTWH(0, 0, 200, 200),
title: Component.text('Window 1'),
content: div(
[Component.text('Window 1')],
classes: 'flex items-center justify-center w-full h-full',
),
),
CoWindow(
bounds: const CoreWindowRect.fromLTWH(200, 0, 200, 200),
title: Component.text('Window 2'),
content: div(
[Component.text('Window 2')],
classes: 'flex items-center justify-center w-full h-full',
),
),
];
@override
Component build(BuildContext context) {
return div(
[
CoOutlinedContainer(
containerStyle: const CoreOutlinedContainerStyle(height: 600),
child: CoWindowNavigator(
initialWindows: _windows,
child: div(
[Component.text('Desktop')],
classes: 'flex items-center justify-center w-full h-full',
),
),
),
CoGap(size: CoreSpace.space8),
CoButton(
onPressed: () {
final index = _windows.length + 1;
setState(() {
_windows = [
..._windows,
CoWindow(
bounds: const CoreWindowRect.fromLTWH(0, 0, 200, 200),
title: Component.text('Window $index'),
content: div(
[Component.text('Window $index')],
classes:
'flex items-center justify-center w-full h-full',
),
),
];
});
},
child: Component.text('Add Window'),
),
],
classes: 'flex flex-col w-full',
);
}
}
class WindowDefaultExample extends StatefulWidget {
const WindowDefaultExample({super.key});
@override
State<WindowDefaultExample> createState() => _WindowDefaultExampleState();
}
class _WindowDefaultExampleState extends State<WindowDefaultExample> {
final GlobalKey<CoWindowNavigatorHandle> _navigatorKey = GlobalKey();
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
CoOutlinedContainer(
containerStyle: const CoreOutlinedContainerStyle(height: 600),
child: CoWindowNavigator(
key: _navigatorKey,
initialWindows: [
CoWindow(
bounds: const CoreWindowRect.fromLTWH(0, 0, 200, 200),
title: const Text('Window 1'),
content: const Center(child: Text('Window 1')),
),
CoWindow(
bounds: const CoreWindowRect.fromLTWH(200, 0, 200, 200),
title: const Text('Window 2'),
content: const Center(child: Text('Window 2')),
),
],
child: const Center(child: Text('Desktop')),
),
),
const CoGap(size: CoreSpace.space8),
CoButton(
onPressed: () {
final nav = _navigatorKey.currentState;
if (nav == null) return;
final index = nav.windows.length + 1;
nav.pushWindow(
CoWindow(
bounds: const CoreWindowRect.fromLTWH(0, 0, 200, 200),
title: Text('Window $index'),
content: Center(child: Text('Window $index')),
),
);
},
child: const Text('Add Window'),
),
],
);
}
}
Import#
import 'package:coui_flutter/coui_flutter.dart';
import 'package:coui_web/coui_web.dart';
import 'package:jaspr/jaspr.dart';
Basic usage#
CoWindowNavigator(
initialWindows: [
CoWindow(
bounds: const CoreWindowRect.fromLTWH(0, 0, 240, 180),
title: const Text('Window 1'),
content: const Text('Content'),
),
],
child: const Center(child: Text('Desktop')),
)
Props — CoWindow#
| Prop | Type | Default | Description |
|---|---|---|---|
title |
Widget? / Component? |
null |
Title slot inside the title bar. |
actions |
Widget? / Component? |
Default actions | Overrides the minimize/maximize/close row. |
content |
Widget? / Component? |
null |
Body content area. |
controller |
CoreWindowController? |
null |
External reactive state controller. |
bounds |
CoreWindowRect? |
required when no controller |
Initial floating bounds. |
maximized |
CoreWindowRect? |
null |
Relative (0..1) maximized rect. |
minimized |
bool? |
false |
Whether the window starts minimized. |
alwaysOnTop |
bool? |
false |
Pins to the always-on-top layer. |
enableSnapping |
bool? |
true |
Drag-to-edge snapping. |
resizable |
bool? |
true |
8-way edge/corner resize handles. |
draggable |
bool? |
true |
Title bar drag. |
closable |
bool? |
true |
Close control. |
maximizable |
bool? |
true |
Maximize control. |
minimizable |
bool? |
true |
Minimize control. |
constraints |
CoreWindowConstraints? |
200×200 min |
Min/max size enforced during resize. |
Props — CoWindowNavigator#
| Prop | Type | Default | Description |
|---|---|---|---|
initialWindows |
List<CoWindow> |
required | Windows to render on mount. |
child |
Widget? / Component? |
null |
Background (desktop) content. |
showTopSnapBar |
bool |
true |
Render the preset-tile snap bar. |
Programmatic control#
final controller = CoreWindowController(
bounds: CoreWindowRect.fromLTWH(0, 0, 320, 240),
);
controller.bounds = CoreWindowRect.fromLTWH(100, 100, 320, 240);
controller.maximized = const CoreWindowRect.fromLTWH(0, 0, 1, 1);
controller.minimized = true;
Theme#
Override defaults through CoreWindowTheme:
const CoreComponentTheme(
window: CoreWindowTheme(
titleBarHeight: 36,
resizeThickness: 10,
),
);