desktop_ui_kit 0.2.0 copy "desktop_ui_kit: ^0.2.0" to clipboard
desktop_ui_kit: ^0.2.0 copied to clipboard

Platform-adaptive desktop widgets for Flutter with native OS conventions and keyboard navigation.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:desktop_ui_kit/desktop_ui_kit.dart';

void main() {
  runApp(const MyDesktopApp());
}

class MyDesktopApp extends StatelessWidget {
  const MyDesktopApp({super.key});

  @override
  Widget build(BuildContext context) {
    return DesktopApp(
      themeMode: ThemeMode.system,
      home: const MainScreen(),
    );
  }
}

class MainScreen extends StatefulWidget {
  const MainScreen({super.key});

  @override
  State<MainScreen> createState() => _MainScreenState();
}

class _MainScreenState extends State<MainScreen> {
  int _tabIndex = 0;

  @override
  Widget build(BuildContext context) {
    final theme = DesktopTheme.of(context);
    final colors = theme.colors;

    return Scaffold(
      body: Column(
        children: [
          DesktopMenuBar(groups: [
            DesktopMenuGroup('File', [
              DesktopMenuEntry(label: 'New Project', shortcut: 'Ctrl+N', onPressed: () {}),
              DesktopMenuEntry(label: 'Open...', shortcut: 'Ctrl+O', onPressed: () {}),
              DesktopMenuEntry(label: 'Save', shortcut: 'Ctrl+S', onPressed: () {}),
              DesktopMenuEntry.divider(),
              DesktopMenuEntry(label: 'Exit', shortcut: 'Alt+F4', onPressed: () {}),
            ]),
            DesktopMenuGroup('Edit', [
              DesktopMenuEntry(label: 'Undo', shortcut: 'Ctrl+Z', onPressed: () {}),
              DesktopMenuEntry(label: 'Redo', shortcut: 'Ctrl+Shift+Z', onPressed: () {}),
            ]),
            DesktopMenuGroup('View', [
              DesktopMenuEntry(label: 'Widgets', shortcut: 'Ctrl+1', onPressed: () => setState(() => _tabIndex = 0)),
              DesktopMenuEntry(label: 'Forms', shortcut: 'Ctrl+2', onPressed: () => setState(() => _tabIndex = 1)),
            ]),
            DesktopMenuGroup('Help', [
              DesktopMenuEntry(label: 'About', onPressed: () {}),
            ]),
          ]),
          Expanded(
            child: _tabIndex == 0 ? const _WidgetsPage() : const _FormsPage(),
          ),
          Container(
            height: DesktopTokens.statusBarHeight,
            padding: const EdgeInsets.symmetric(horizontal: 12),
            decoration: BoxDecoration(
              color: colors.surfaceContainer,
              border: Border(top: BorderSide(color: colors.border)),
            ),
            child: Row(
              children: [
                Icon(Icons.info_outline, size: 14, color: colors.textTertiary),
                const SizedBox(width: 6),
                Text('Ready', style: theme.typography.caption),
                const Spacer(),
                Text(_tabIndex == 0 ? 'Widgets' : 'Forms', style: theme.typography.caption),
                const SizedBox(width: 16),
                Text('desktop_ui_kit v0.2.0', style: theme.typography.caption),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

class _WidgetsPage extends StatelessWidget {
  const _WidgetsPage();

  @override
  Widget build(BuildContext context) {
    final theme = DesktopTheme.of(context);
    final colors = theme.colors;
    final typography = theme.typography;

    return Column(
      children: [
        Container(
          padding: const EdgeInsets.all(DesktopTokens.spaceSm),
          color: colors.surface,
          child: Row(
            children: [
              Text('Widgets Demo', style: typography.label),
              const Spacer(),
              DesktopButton(
                label: 'Open Dialog',
                icon: Icons.open_in_new,
                variant: DesktopButtonVariant.secondary,
                onPressed: () {
                  DesktopDialog.show(
                    context,
                    DesktopDialog(
                      title: 'Example Dialog',
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        crossAxisAlignment: CrossAxisAlignment.stretch,
                        children: [
                          const Text('This is an example dialog'),
                          const SizedBox(height: DesktopTokens.spaceLg),
                          DesktopDataTable(
                            columns: [
                              DesktopColumn(
                                header: 'Name',
                                width: 120,
                                sortable: true,
                                cellBuilder: (v) => Text('$v'),
                              ),
                              DesktopColumn(
                                header: 'Value',
                                width: 80,
                                sortable: true,
                                cellBuilder: (v) => Text('$v'),
                              ),
                            ],
                            rows: [
                              {'Name': 'Alpha', 'Value': 100},
                              {'Name': 'Beta', 'Value': 200},
                              {'Name': 'Gamma', 'Value': 300},
                            ],
                          ),
                        ],
                      ),
                      actions: [
                        DesktopButton(
                          label: 'Cancel',
                          variant: DesktopButtonVariant.secondary,
                          onPressed: () => Navigator.of(context).pop(),
                        ),
                        DesktopButton(
                          label: 'Confirm',
                          onPressed: () => Navigator.of(context).pop(),
                        ),
                      ],
                    ),
                  );
                },
              ),
            ],
          ),
        ),
        const Divider(height: 1),
        Expanded(
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Icon(Icons.widgets, size: 48, color: colors.textTertiary),
                const SizedBox(height: DesktopTokens.spaceLg),
                Text('desktop_ui_kit', style: typography.heading3),
                const SizedBox(height: DesktopTokens.spaceSm),
                Text(
                  'A Flutter desktop UI kit for Windows, macOS & Linux',
                  style: typography.body,
                ),
                const SizedBox(height: DesktopTokens.spaceXxl),
                Wrap(
                  spacing: DesktopTokens.spaceMd,
                  children: [
                    DesktopButton(
                      label: 'Primary',
                      icon: Icons.star,
                      onPressed: () {},
                    ),
                    DesktopButton(
                      label: 'Secondary',
                      variant: DesktopButtonVariant.secondary,
                      onPressed: () {},
                    ),
                    DesktopButton(
                      label: 'Ghost',
                      variant: DesktopButtonVariant.ghost,
                      onPressed: () {},
                    ),
                    DesktopButton(
                      label: 'Danger',
                      variant: DesktopButtonVariant.danger,
                      onPressed: () {},
                    ),
                  ],
                ),
              ],
            ),
          ),
        ),
      ],
    );
  }
}

class _FormsPage extends StatefulWidget {
  const _FormsPage();

  @override
  State<_FormsPage> createState() => _FormsPageState();
}

class _FormsPageState extends State<_FormsPage> {
  String? _dropdownValue;
  bool _checkbox1 = true;
  bool _checkbox2 = false;
  bool? _checkbox3;
  String _radioValue = 'option1';
  bool _switch1 = true;
  bool _switch2 = false;

  @override
  Widget build(BuildContext context) {
    final theme = DesktopTheme.of(context);
    final typography = theme.typography;

    return SingleChildScrollView(
      padding: const EdgeInsets.all(DesktopTokens.spaceXl),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('Form Controls', style: typography.heading2),
          const SizedBox(height: DesktopTokens.spaceXxl),

          Text('Text Fields', style: typography.heading4),
          const SizedBox(height: DesktopTokens.spaceLg),
          Wrap(
            spacing: DesktopTokens.spaceXl,
            runSpacing: DesktopTokens.spaceXl,
            children: [
              SizedBox(
                width: 280,
                child: DesktopTextField(
                  label: 'Email',
                  hint: 'you@example.com',
                  prefixIcon: Icons.email,
                  helper: 'We will never share your email',
                ),
              ),
              SizedBox(
                width: 280,
                child: DesktopTextField(
                  label: 'Password',
                  hint: 'Enter password',
                  obscureText: true,
                  prefixIcon: Icons.lock,
                  suffixIcon: Icons.visibility,
                ),
              ),
              SizedBox(
                width: 280,
                child: DesktopTextField(
                  label: 'With Error',
                  hint: 'Invalid input',
                  error: 'This field is required',
                ),
              ),
              SizedBox(
                width: 280,
                child: DesktopTextField(
                  label: 'Disabled',
                  hint: 'Cannot edit',
                  disabled: true,
                ),
              ),
            ],
          ),

          const SizedBox(height: DesktopTokens.spaceXxl),
          Text('Dropdown', style: typography.heading4),
          const SizedBox(height: DesktopTokens.spaceLg),
          SizedBox(
            width: 280,
            child: DesktopDropdown<String>(
              label: 'Country',
              value: _dropdownValue,
              hint: 'Select country',
              options: const [
                DropdownOption(value: 'us', label: 'United States', icon: Icons.flag),
                DropdownOption(value: 'uk', label: 'United Kingdom', icon: Icons.flag),
                DropdownOption(value: 'de', label: 'Germany', icon: Icons.flag),
                DropdownOption(value: 'fr', label: 'France', icon: Icons.flag),
                DropdownOption(value: 'jp', label: 'Japan', icon: Icons.flag),
              ],
              onChanged: (v) => setState(() => _dropdownValue = v),
            ),
          ),

          const SizedBox(height: DesktopTokens.spaceXxl),
          Text('Checkboxes', style: typography.heading4),
          const SizedBox(height: DesktopTokens.spaceLg),
          Wrap(
            spacing: DesktopTokens.spaceXl,
            runSpacing: DesktopTokens.spaceLg,
            children: [
              DesktopCheckbox(
                value: _checkbox1,
                label: 'Enable notifications',
                onChanged: (v) => setState(() => _checkbox1 = v ?? false),
              ),
              DesktopCheckbox(
                value: _checkbox2,
                label: 'Subscribe to newsletter',
                onChanged: (v) => setState(() => _checkbox2 = v ?? false),
              ),
              DesktopCheckbox(
                value: _checkbox3,
                label: 'Indeterminate state',
                onChanged: (v) => setState(() => _checkbox3 = v),
              ),
              const DesktopCheckbox(
                value: false,
                label: 'Disabled',
                disabled: true,
              ),
            ],
          ),

          const SizedBox(height: DesktopTokens.spaceXxl),
          Text('Radio Buttons', style: typography.heading4),
          const SizedBox(height: DesktopTokens.spaceLg),
          Wrap(
            spacing: DesktopTokens.spaceXl,
            runSpacing: DesktopTokens.spaceLg,
            children: [
              DesktopRadio<String>(
                value: 'option1',
                groupValue: _radioValue,
                label: 'Option 1',
                onChanged: (v) => setState(() => _radioValue = v ?? 'option1'),
              ),
              DesktopRadio<String>(
                value: 'option2',
                groupValue: _radioValue,
                label: 'Option 2',
                onChanged: (v) => setState(() => _radioValue = v ?? 'option1'),
              ),
              DesktopRadio<String>(
                value: 'option3',
                groupValue: _radioValue,
                label: 'Option 3',
                onChanged: (v) => setState(() => _radioValue = v ?? 'option1'),
              ),
              const DesktopRadio<String>(
                value: 'disabled',
                groupValue: null,
                label: 'Disabled',
                disabled: true,
              ),
            ],
          ),

          const SizedBox(height: DesktopTokens.spaceXxl),
          Text('Switches', style: typography.heading4),
          const SizedBox(height: DesktopTokens.spaceLg),
          Wrap(
            spacing: DesktopTokens.spaceXl,
            runSpacing: DesktopTokens.spaceLg,
            children: [
              DesktopSwitch(
                value: _switch1,
                label: 'Dark mode',
                onChanged: (v) => setState(() => _switch1 = v),
              ),
              DesktopSwitch(
                value: _switch2,
                label: 'Enable analytics',
                onChanged: (v) => setState(() => _switch2 = v),
              ),
              const DesktopSwitch(
                value: false,
                label: 'Disabled',
                disabled: true,
              ),
            ],
          ),
        ],
      ),
    );
  }
}
0
likes
0
points
378
downloads

Documentation

Documentation

Publisher

unverified uploader

Weekly Downloads

Platform-adaptive desktop widgets for Flutter with native OS conventions and keyboard navigation.

Repository (GitHub)
View/report issues

Topics

#desktop #ui #widget #design-system #cross-platform

Funding

Consider supporting this project:

github.com

License

unknown (license)

Dependencies

flutter

More

Packages that depend on desktop_ui_kit