Window | CoUI

Window

Multi-window manager with draggable, resizable, snapping windows.

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
Desktop
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#

PropTypeDefaultDescription
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#

PropTypeDefaultDescription
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,
  ),
);