Implements Microsoft's Fluent Design System in Flutter.

Last update: Jun 22, 2022

fluent_ui

Design beautiful native windows apps using Flutter

Unofficial implementation of Fluent UI for Flutter. It's written based on the official documentation

You can check the web version of it here

Content

Motivation

Since flutter has Windows support (currently in stable under an early release flag as of 30/03/2021), it's necessary to have support to its UI guidelines to build apps with fidelity, since it has support for Material and Cupertino. See this for more info on the offical fluent ui support

See also:

Installation

Add the package to your dependencies:

dependencies:
  fluent_ui:
    git: https://github.com/bdlukaa/fluent_ui.git

You can see the example app here

Finally, run dart pub get to downlaod the package.

Projects using this library should use the stable channel of Flutter

Badge

Are you using this library on your app? You can use a badge to tell others:

Add the following code to your README.md or to your website:

<a title="Made with Fluent Design" href="https://github.com/bdlukaa/fluent_ui">
  <img
    src="https://img.shields.io/badge/fluent-design-blue?style=flat-square&color=7A7574&labelColor=0078D7"
  />
</a>

Style

Learn more about Fluent Style

You can use the FluentTheme widget to, well... theme your widgets. You can style your widgets in two ways:

  1. Using the FluentApp widget
FluentApp(
  title: 'MyApp',
  theme: ThemeData(
    ...
  ),
)
  1. Using the FluentTheme widget
FluentTheme(
  theme: ThemeData(
    ...
  ),
  child: ...,
),

Icons

Icons Preview

Inside your app, you use icons to represent an action, such as copying text or navigating to the settings page. This library includes an icon library with it, so you can just call FluentIcons.[icon_name] in any Icon widget:

Icon(FluentIcons.add),

Colors

This library also includes the Fluent UI colors with it, so you can just call Colors.[color_name]:

TextStyle(color: Colors.black),

Avaiable colors:

  • Colors.transparent
  • Colors.white
  • Colors.black
  • Colors.grey
  • Colors.yellow
  • Colors.orange
  • Colors.red
  • Colors.magenta
  • Colors.purple
  • Colors.blue
  • Colors.teal
  • Colors.green

Accent color

Common controls use an accent color to convey state information. Learn more.

By default, the accent color is Colors.blue. However, you can also customize your app's accent color to reflect your brand:

ThemeData(
  accentColor: Colors.blue,
)

To use the system's accent color, you can use the plugin system_theme made by me :). It has support for (04/01/2021) Android, Web and Windows.

import 'package:system_theme/system_theme.dart';

ThemeData(
  accentColor: SystemTheme.accentInstance.accent.toAccentColor(),
)

Brightness

You can change the theme brightness to change the color of your app to

  1. Brightness.light

    Light theme

  2. Brightness.dark

    Dark theme

It defaults to the brightness of the device. (MediaQuery.of(context).brightness)

ThemeData(
  brightness: Brightness.light, // or Brightness.dark
),

Visual Density

Density, in the context of a UI, is the vertical and horizontal "compactness" of the components in the UI. It is unitless, since it means different things to different UI components.

The default for visual densities is zero for both vertical and horizontal densities. It does not affect text sizes, icon sizes, or padding values.

For example, for buttons, it affects the spacing around the child of the button. For lists, it affects the distance between baselines of entries in the list. For chips, it only affects the vertical size, not the horizontal size.

ThemeData(
  visualDensity: VisualDensity.adaptivePlatformDensity,
),

The following widgets make use of visual density:

  • Chip
  • PillButtonBar
  • Snackbar

Typography

To set a typography, you can use the ThemeData class combined with the Typography class:

ThemeData(
  typography: Typography(
    caption: TextStyle(
      fontSize: 12,
      color: Colors.black,
      fontWeight: FontWeight.normal,
    ),
  ),
)

Font

You should use one font throughout your app's UI, and we recommend sticking with the default font for Windows apps, Segoe UI. It's designed to maintain optimal legibility across sizes and pixel densities and offers a clean, light, and open aesthetic that complements the content of the system.

Font Segoe UI Showcase

Learn more

Type ramp

The Windows type ramp establishes crucial relationships between the type styles on a page, helping users read content easily. Learn more

Windows Type Ramp

Reveal Focus

Reveal Focus is a lighting effect for 10-foot experiences, such as Xbox One and television screens. It animates the border of focusable elements, such as buttons, when the user moves gamepad or keyboard focus to them. It's turned off by default, but it's simple to enable. Learn more

Reveal Focus calls attention to focused elements by adding an animated glow around the element's border:

Reveal Focus Preview

This is especially helpful in 10-foot scenarios where the user might not be paying full attention to the entire TV screen.

Enabling it

Reveal Focus is off by default. To enable it, change the focusStyle in your app ThemeData:

theme: ThemeData(
  focusTheme: FocusStyle(
    glowFactor: 4.0,
  ),
),

To enable it in a 10 foot screen, use the method is10footScreen:

import 'dart:ui' as ui;

theme: ThemeData(
  focusStyle: FocusStyle(
    glowFactor: is10footScreen(ui.window.physicalSize.width) ? 2.0 : 0.0,
  ),
),

Go to the example project to a full example

Why isn't Reveal Focus on by default?

As you can see, it's fairly easy to turn on Reveal Focus when the app detects it's running on 10 foot screen. So, why doesn't the system just turn it on for you? Because Reveal Focus increases the size of the focus visual, which might cause issues with your UI layout. In some cases, you'll want to customize the Reveal Focus effect to optimize it for your app.

Customizing Reveal Focus

You can customize the focus border, border radius and glow color:

focusTheme: FocusStyle(
  borderRadius: BorderRadius.zero,
  glowColor: theme.accentColor?.withOpacity(0.2),
  glowFactor: 0.0,
  border: BorderSide(
    width: 2.0,
    color: theme.inactiveColor ?? Colors.transparent,
  ),
),

To customize it to a single widget, wrap the widget in a FocusTheme widget, and change the options you want:

FocusTheme(
  data: FocusThemeData(...),
  child: Button(
    text: Text('Custom Focus Button'),
    onPressed: () {},
  )
),

Motion

This package widely uses animation in the widgets. The animation duration and curve can be defined on the app theme.

Page transitions

Page transitions navigate users between pages in an app, providing feedback as the relationship between pages. Page transitions help users understand if they are at the top of a navigation hierarchy, moving between sibling pages, or navigating deeper into the page hierarchy.

It's recommended to widely use page transitions on NavigationView, that can be implemented using the widget NavigationBody.

This library gives you the following implementations to navigate between your pages:

Entrance

Entrance is a combination of a slide up animation and a fade in animation for the incoming content. Use entrance when the user is taken to the top of a navigational stack, such as navigating between tabs or left-nav items.

The desired feeling is that the user has started over.

Avaiable with the widget EntrancePageTransition, it produces the following effect:

Entrance Page Transition Preview

Drill In

Use drill when users navigate deeper into an app, such as displaying more information after selecting an item.

The desired feeling is that the user has gone deeper into the app.

Avaiable with the widget DrillInPageTransition, it produces the following effect:

Drill Page Transition Preview

Horizontal

It's avaiable with the widget HorizontalSlidePageTransition.

Navigation

The default Flutter Navigation is available on the FluentApp widget, that means you can simply call Navigator.push and Navigator.pop to navigate between routes. See navigate to a new screen and back

Navigation View

The NavigationView control provides top-level navigation for your app. It adapts to a variety of screen sizes and supports both top and left navigation styles.

Navigation Panel

App Bar

The app bar is the top app bar that every desktop nowadays have.

NavigationView(
  appBar: NavigationAppBar(
    title: Text('Nice App Title :)'),
    actions: Row(children: [
      /// These actions are usually the minimize, maximize and close window
    ]),
    /// If automaticallyImplyLeading is true, a 'back button' will be added to
    /// app bar. This property can be overritten by [leading]
    automaticallyImplyLeading: true,
  ),
  ...
)

Navigation Pane

The pane is the pane that can be displayed at the left or at the top.

NavigationView(
  ...,
  pane: NavigationPane(
    /// The current selected index
    selected: index,
    /// Called whenever the current index changes
    onChanged: (i) => setState(() => index = i),
    displayMode: PaneDisplayMode.auto,
  ),
  ...
)

You can change the displayMode to make it fit the screen.

Name Screenshot Info
Top The pane is positioned above the content. We recommend top navigation when:
- You have 5 or fewer top-level navigation categories that are equally important, and any additional top-level navigation categories that end up in the dropdown overflow menu are considered less important.
- You need to show all navigation options on screen. - You want more space for your app content.
- Icons cannot clearly describe your app's navigation categories.
Open The pane is expanded and positioned to the left of the content. We recommend open navigation when:
- You have 5-10 equally important top-level navigation categories.
- You want navigation categories to be very prominent, with less space for other app content.
Compact The pane shows only icons until opened and is positioned to the left of the content.
Minimal Only the menu button is shown until the pane is opened. When opened, it's positioned to the left of the content.
Auto By default, displayMode is set to auto. In Auto mode, the NavigationView adapts between minimal when the window is narrow, to compact, and then open as the window gets wider.

You can customize the selected indicator. By default StickyNavigationIndicator is used, but you can also use the old windows indicator:

pane: NavigationPane(
  indicatorBuilder: ({
    required BuildContext context,
    /// The current selected index
    int? index,
    /// A function that, when executed, returns the position of all the
    /// PaneItems. This function must be called after the widget was
    /// rendered at least once
    required List<Offset> Function() offsets,
    /// A function that, when executed, returns the size of all the
    /// PaneItems. This function must be called after the widget was
    /// rendered at least once
    required List<Size> Function() sizes,
    /// Corresponds to the current display mode. If top, Axis.vertical
    /// is passed, otherwise Axis.vertical
    required Axis axis,
    /// Corresponds to the pane itself as a widget. The indicator is
    /// rendered over the whole pane.
    required Widget child,
  }) {
    if (index == null) return child;
    assert(debugCheckHasFluentTheme(context));
    final theme = NavigationPaneThemeData.of(context);
    return EndNavigationIndicator(
      index: index,
      offsets: offsets,
      sizes: sizes,
      child: child,
      color: theme.highlightColor,
      curve: theme.animationCurve ?? Curves.linear,
      axis: axis,
    );
  },
)

Navigation body

A navigation body is used to implement page transitions into a navigation view. It knows what is the current display mode of the parent NavigationView, if any, and define the page transitions accordingly.

For top mode, the horizontal page transition is used. For the others, drill in page transition is used.

You can also supply a builder function to create the pages instead of a list of widgets. For this use the NavigationBody.builder constructor.

int _currentIndex = 0;

NavigationView(
  ...,
  content: NavigationBody(index: _currentIndex, children: [...]),
)

ScaffoldPage is usually used with the navigation body as its children:

NavigationBody(
  index: _currentIndex,
  children: [
    ScaffoldPage(
      topBar: PageTopBar(header: Text('Your Songs'))
    )
  ],
)

Tab View

The TabView control is a way to display a set of tabs and their respective content. TabViews are useful for displaying several pages (or documents) of content while giving a user the capability to rearrange, open, or close new tabs. Learn more

Here's an example of how to create a tab view:

SizedBox(
  height: 600,
  child: TabView(
    currentIndex: currentIndex,
    onChanged: (index) => setState(() => currentIndex = index),
    onNewPressed: () {
      setState(() => tabs++);
    },
    tabs: List.generate(tabs, (index) {
      return Tab(
        text: Text('Tab $index'),
        closeIcon: Tooltip(
          message: 'Close tab',
          child: IconButton(
            icon: Icon(FluentIcons.close),
            onPressed: () {
              setState(() => tabs--);
              if (currentIndex > tabs - 1) currentIndex--;
            },
          ),
        ),
      );
    }),
    bodies: List.generate(
      tabs,
      (index) => Container(
        color: index.isEven ? Colors.red : Colors.yellow,
      ),
    ),
  ),
),

The code above produces the following:

TabView Preview

Bottom Navigation

The bottom navigation displays icons and optional text at the bottom of the screen for switching between different primary destinations in an app. This is commomly used on small screens. Learn more

Here's an example of how to create a bottom navigation:

int index = 0;

ScaffoldPage(
  content: NavigationBody(index: index, children: [
    Container(),
    Container(),
    Container(),
  ]),
  bottomBar: BottomNavigation(
    index: index,
    onChanged: (i) => setState(() => index = i),
    items: [
      BottomNavigationItem(
        icon: Icon(Icons.two_k),
        selectedIcon: Icon(Icons.two_k_plus),
        title: Text('Both'),
      ),
      BottomNavigationItem(
        icon: Icon(Icons.phone_android_outlined),
        selectedIcon: Icon(Icons.phone_android),
        title: Text('Android'),
      ),
      BottomNavigationItem(
        icon: Icon(Icons.phone_iphone_outlined),
        selectedIcon: Icon(Icons.phone_iphone),
        title: Text('iOS'),
      ),
    ],
  )
)

Inputs

Inputs are widgets that reacts to user interection. On most of the inputs you can set onPressed or onChanged to null to disable it.

Button

A button gives the user a way to trigger an immediate action. Learn more

Here's an example of how to create a basic button:

Button(
  text: Text('Standard XAML button'),
  // Set onPressed to null to disable the button
  onPressed: () {
    print('button pressed'),
  }
)

The code above produces the following:

Button

You can also use some alternative buttons:

Icon Button

This button is used to display an Icon as content. It's optmized to show icons.

IconButton(
  icon: Icon(FluentIcons.add),
  onPressed: () {
    print('pressed icon button');
  },
),

Split Button

A Split Button has two parts that can be invoked separately. One part behaves like a standard button and invokes an immediate action. The other part invokes a flyout that contains additional options that the user can choose from. Learn more

You can use a SplitButtonBar to create a Split Button. It takes two Buttons in the buttons property. You can also customize the button spacing by changing the property interval in its theme.

Here's an example of how to create a split button:

const double splitButtonHeight = 25.0;

SplitButtonBar(
  theme: SplitButtonThemeData(
    interval: 1, // the default value is one
  ),
  // There need to be at least 2 items in the buttons, and they must be non-null
  buttons: [
    SizedBox(
      height: splitButtonHeight,
      child: Button(
        text: Container(
          height: 24,
          width: 24,
          color: FluentTheme.of(context).accentColor,
        ),
        onPressed: () {},
      ),
    ),
    IconButton(
      icon: const SizedBox(
        height: splitButtonHeight,
        child: const Icon(FluentIcons.chevron_down, size: 10.0),
      ),
      onPressed: () {},
    ),
  ],
)

The code above produces the following button:

SplitButtonBar Preview

Toggle Button

A button that can be on or off.

Here's an example of how to create a basic toggle button:

bool _value = false;

ToggleButton(
  child: Text('Toggle Button'),
  checked: _value,
  onChanged: (value) => setState(() => _value = value),
)

Checkbox

A check box is used to select or deselect action items. It can be used for a single item or for a list of multiple items that a user can choose from. The control has three selection states: unselected, selected, and indeterminate. Use the indeterminate state when a collection of sub-choices have both unselected and selected states. Learn more

Here's an example of how to create a checkbox:

bool _checked = true;

Checkbox(
  checked: _checked,
  onChanged: (value) => setState(() => _checked = value),
)

Handling its states

State Property Value
checked checked true
unchecked checked false
indeterminate checked null
enabled onChanged non-null
disabled onChanged null

Toggle Switch

The toggle switch represents a physical switch that allows users to turn things on or off, like a light switch. Use toggle switch controls to present users with two mutually exclusive options (such as on/off), where choosing an option provides immediate results. Learn more

Here's an example of how to create a basic toggle switch:

bool _checked = false;

ToggleSwitch(
  checked: _checked,
  onChanged: (v) => setState(() => _checked = v),
  content: Text(_checked ? 'On' : 'Off');
)

Radio Buttons

Radio buttons, also called option buttons, let users select one option from a collection of two or more mutually exclusive, but related, options. Radio buttons are always used in groups, and each option is represented by one radio button in the group.

In the default state, no radio button in a RadioButtons group is selected. That is, all radio buttons are cleared. However, once a user has selected a radio button, the user can't deselect the button to restore the group to its initial cleared state.

The singular behavior of a RadioButtons group distinguishes it from check boxes, which support multi-selection and deselection, or clearing.

Learn more

Here's an example of how to create a basic set of radio buttons:

int _currentIndex = -1;

final List<String> radioButtons = <String>[
  'RadioButton 1',
  'RadioButton 2',
  'RadioButton 3',
];

Column(
  children: List.generate(radioButtons.length, (index) {
    return RadioButton(
      checked: _currentIndex == index,
      // set onChanged to null to disable the button
      onChanged: () => setState(() => _currentIndex = index),
      content: Text(radioButtons[index]),
    );
  }),
),

The code above produces the following:

Radio Buttons

Slider

A slider is a control that lets the user select from a range of values by moving a thumb control along a track. Learn more

A slider is a good choice when you know that users think of the value as a relative quantity, not a numeric value. For example, users think about setting their audio volume to low or medium—not about setting the value to 2 or 5.

Don't use a slider for binary settings. Use a toggle switch instead.

Here's an example of how to create a basic slider:

double _value = 0;

SizedBox(
  // The default width is 200.
  // The slider does not have its own widget, so you have to add it yourself.
  // The slider always try to be as big as possible
  width: 200,
  child: Slider(
    max: 100,
    value: _value,
    onChanged: (v) => setState(() => value = v),
    // Label is the text displayed above the slider when the user is interacting with it.
    label: '${sliderValue.toInt()}',
  ),
)

The code above produces the following:

Slider Preview

Choosing between vertical and horizontal sliders

You can set vertical to true to create a vertical slider

Horizontal Vertical
If the control is used to seek within media, like in a video app. if the slider represents a real-world value that is normally shown vertically (such as temperature).

Rating Bar

The property starSpacing was not implemented yet

The rating control allows users to view and set ratings that reflect degrees of satisfaction with content and services. Learn more

Example

double rating = 0.0;

RatingBar(
  rating: rating,
  onChanged: (v) => setState(() => rating = v),
)

You can set amount to change the amount of stars. The rating must be less than the stars and more than 0. You can also change the icon, its size and color. You can make the bar read only by setting onChanged to null.

Forms

A form is a group of controls that collect and submit data from users. Forms are typically used for settings pages, surveys, creating accounts, and much more.

TextBox

A Text Box lets a user type text into an app. It's typically used to capture a single line of text, but can be configured to capture multiple lines of text. The text displays on the screen in a simple, uniform, plaintext format. Learn more

TextBox Preview

You can use the Forms screen in the example app for reference.

You can use the widget TextBox to create text boxes:

TextBox(
  controller: ...,
  header: 'Notes',
  placeholder: 'Type your notes here',
),

Which produces the following:

TextBox Example Preview

Auto Suggest Box

Use an AutoSuggestBox to provide a list of suggestions for a user to select from as they type. Learn more

Example

final autoSuggestBox = TextEditingController();

AutoSuggestBox<String>(
  controller: autoSuggestBox,
  items: [
    'Blue',
    'Green',
    'Red',
    'Yellow',
    'Grey',
  ],
  onSelected: (text) {
    print(text);
  },
  textBoxBuilder: (context, controller, focusNode, key) {
    const BorderSide _kDefaultRoundedBorderSide = BorderSide(
      style: BorderStyle.solid,
      width: 0.8,
    );
    return TextBox(
      key: key,
      controller: controller,
      focusNode: focusNode,
      suffixMode: OverlayVisibilityMode.editing,
      suffix: IconButton(
        icon: Icon(FluentIcons.close),
        onPressed: () {
          controller.clear();
          focusNode.unfocus();
        },
      ),
      placeholder: 'Type a color',
      decoration: BoxDecoration(
        border: Border(
          top: _kDefaultRoundedBorderSide,
          bottom: _kDefaultRoundedBorderSide,
          left: _kDefaultRoundedBorderSide,
          right: _kDefaultRoundedBorderSide,
        ),
        borderRadius: focusNode.hasFocus
            ? BorderRadius.vertical(top: Radius.circular(3.0))
            : BorderRadius.all(Radius.circular(3.0)),
      ),
    );
  },
)

The code above produces the following:

Auto suggest box example

Screenshots

Combo Box

Use a combo box (also known as a drop-down list) to present a list of items that a user can select from. A combo box starts in a compact state and expands to show a list of selectable items. A ListBox is similar to a combo box, but is not collapsible/does not have a compact state. Learn more

Here's an example of how to create a basic combo box:

final values = ['Blue', 'Green', 'Yellow', 'Red'];
String? comboBoxValue;

SizedBox(
  width: 200,
  child: Combobox<String>(
    header: 'Colors',
    placeholder: 'Selected list item',
    isExpanded: true,
    items: values
        .map((e) => ComboboxItem<String>(
              value: e,
              child: Text(e),
            ))
        .toList(),
    value: comboBoxValue,
    onChanged: (value) {
      // print(value);
      if (value != null) setState(() => comboBoxValue = value);
    },
  ),
),

The code above produces the following:

Combo box Preview

Widgets

Tooltip

A tooltip is a short description that is linked to another control or object. Tooltips help users understand unfamiliar objects that aren't described directly in the UI. They display automatically when the user moves focus to, presses and holds, or hovers the mouse pointer over a control. The tooltip disappears after a few seconds, or when the user moves the finger, pointer or keyboard/gamepad focus. Learn more

To add a tooltip to a widget, wrap it in a Tooltip widget:

Tooltip(
  message: 'Click to perform an action',
  child: Button(
    text: Text('Button with tooltip'),
    onPressed: () {
      print('pressed button with tooltip');
    }
  ),
)

It's located above or below the child widget. You can specify the preffered location when both locations are available using the preferBelow property.

Tooltip Preview

Content Dialog

Dialogs are modal UI overlays that provide contextual app information. They block interactions with the app window until being explicitly dismissed. They often request some kind of action from the user. Learn more

You can create a Dialog with the widget ContentDialog:

ContentDialog(
  title: Text('No WiFi connection'),
  content: Text('Check your connection and try again'),
  actions: [
    Button(
      text: Text('Ok'),
      onPressed: () {
        Navigator.pop(context);
      }
    )
  ],
),

The code above produces the following:

No Wifi Connection Dialog

You can display the dialog as an overlay by calling the function showDialog:

showDialog(
  context: context,
  builder: (context) {
    return ContentDialog(...);
  },
);

Delete File Dialog
Subscribe to App Service Dialog\

Flyout

A flyout is a light dismiss container that can show arbitrary UI as its content. Flyouts can contain other flyouts or context menus to create a nested experience.

Example

final flyoutController = FlyoutController();

Flyout(
  controller: flyoutController,
  contentWidth: 450,
  content: FlyoutContent(
    child: Text(
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.'),
  ),
  child: Button(
    text: Text('Open flyout'),
    onPressed: () {
      flyoutController.open = true;
    },
  ),
);

@override
void dispose() {
  flyoutController.dispose();
  super.dispose();
}

The code above produces the following:

Screenshots


Acrylic

Acrylic is a type of Brush that creates a translucent texture. You can apply acrylic to app surfaces to add depth and help establish a visual hierarchy. Learn more

Acrylic

Do Don't
Do use acrylic as the background material of non-primary app surfaces like navigation panes. Don't put desktop acrylic on large background surfaces of your app - this breaks the mental model of acrylic being used primarily for transient surfaces.
Do extend acrylic to at least one edge of your app to provide a seamless experience by subtly blending with the app’s surroundings. Don’t place in-app and background acrylics directly adjacent to avoid visual tension at the seams.
Don't place multiple acrylic panes with the same tint and opacity next to each other because this results in an undesirable visible seam.
Don’t place accent-colored text over acrylic surfaces.
Acrylic(
  child: Button(
    text: Text('Mom it\'s me hehe <3'),
    onPressed: () {
      print('button inside acrylic pressed');
    }
  ),
  color: ...,
  width: ...,
  height: ...,
),

Acrylic preview

InfoBar

The InfoBar control is for displaying app-wide status messages to users that are highly visible yet non-intrusive. There are built-in Severity levels to easily indicate the type of message shown as well as the option to include your own call to action or hyperlink button. Since the InfoBar is inline with other UI content the option is there for the control to always be visible or dismissed by the user.

You can easility create it using the InfoBar widget and theme it using InfoBarThemeData. It has built-in support for both light and dark theme:

bool _visible = true;

if (_visible)
  InfoBar(
    title: Text('Update available'),
    content: Text('Restart the app to apply the latest update.'), // optional
    severity: InfoBarSeverity.info, // optional. Default to InfoBarSeverity.info
    onClose: () {
      // Dismiss the info bar
      setState(() => _visible = false);
    }
  ),

Which produces the following:

InfoBar Preview

Date Picker

The date picker gives you a standardized way to let users pick a localized date value using touch, mouse, or keyboard input. Learn more

The entry point displays the chosen date, and when the user selects the entry point, a picker surface expands vertically from the middle for the user to make a selection. The date picker overlays other UI; it doesn't push other UI out of the way.

We use intl to format the dates. You can change the current locale to change formatting

Here's an example of how to create a basic date picker:

DateTime date = DateTime.now();

SizedBox(
  width: 295,
  child: DatePicker(
    header: 'Date of birth',
    selected: date,
    onChanged: (v) => setState(() => date = v),
  ),
);

Which produces the following:

DatePicker Preview

Time Picker

The time picker gives you a standardized way to let users pick a time value using touch, mouse, or keyboard input. Learn more

Use a time picker to let a user pick a single time value.

Here's an example of how to create a basic time picker:

DateTime date = DateTime.now();

SizedBox(
  width: 240,
  child: TimePicker(
    header: 'Arrival time',
    selected: date,
    onChanged: (v) => setState(() => date = v),
  ),
),

The code above produces the following:

Time Picker Preview

Progress Bar and Progress Ring

A progress control provides feedback to the user that a long-running operation is underway. It can mean that the user cannot interact with the app when the progress indicator is visible, and can also indicate how long the wait time might be, depending on the indicator used.

Here's an example of how to create a ProgressBar:

ProgressBar(value: 35)

Determinate Progress Bar

You can omit the value property to create an indeterminate progress bar:

Indeterminate Progress Bar

Indeterminate Progress Bar is a courtesy of @raitonubero. Show him some love

Here's an example of how to create a progress ring:

ProgressRing(value: 35)

Determinate Progress Ring

You can omit the value property to create an indeterminate progress ring:

Indeterminate Progress Ring

Both Indeterminate ProgressBar and Indeterminate ProgressRing is a courtesy of @raitonubero. Show him some love

Scrollbar

A scrollbar thumb indicates which portion of a [ScrollView] is actually visible. Learn more

Depending on the situation, the scrollbar uses two different visualizations, shown in the following illustration: the panning indicator (left) and the traditional scrollbar (right).

Note that the arrows aren't visible. See this and this issues for more info.

Scrollbar Panning Indicator Traditional Scrollbar

When the scrollbar is visible it is overlaid as 16px on top of the content inside your ScrollView. In order to ensure good UX design you will want to ensure that no interactive content is obscured by this overlay. Additionally if you would prefer not to have UX overlap, leave 16px of padding on the edge of the viewport to allow for the scrollbar.

Here's an example of how to add a scrollbar to a ScrollView:

final _controller = ScrollController();

Scrollbar(
  controller: controller,
  child: ListView.builder(
    /// You can add a padding to the view to avoid having the scrollbar over the UI elements
    padding: EdgeInsets.only(right: 16.0),
    itemCount: 100,
    builder: (context, index) {
      return ListTile(title: Text('$index'));
    }
  ),
)

Which produces the following:

Scrollbar Preview

You can change the isAlwaysVisible property to either enable or disable the fade effect. It's disabled by default.

List Tile

You can use a ListTile in a ListView.

Example

final people = {
  'Mass in B minor': 'Johann Sebastian Bach',
  'Third Symphony': 'Ludwig van Beethoven',
  'Serse': 'George Frideric Hendel',
};

ListView.builder(
  itemCount: people.length,
  itemBuilder: (context, index) {
    final title = people.keys[index];
    final subtitle = people[title];
    return ListTile(
      leading: CircleAvatar(),
      title: Text(title),
      subtitle: Text(subtitle),
    );
  }
),

The code above produces the following:

Double Line Example

If you want to create a tappable tile, use TappableListTile instead.

Info Header

You can use an InfoHeader to tell the user the purpose of something

Here's an example of how to add an info header to a combobox:

InfoHeader(
  header: 'Control header',
  child: ComboBox(...),
),

The code above produces the following:

InfoHeader Preview

Some widgets, such as ComboBox and TextBox, already come with a header property, so you can use them easily with them:

ComboBox(
  header: 'Control header',
  ...
)

This will produce the same as the image above.

Mobile Widgets

Widgets with focus on mobile. Based on the official documentation and source code for iOS and Android. Most of the widgets above can adapt to small screens, and will fit on all your devices.

Bottom Sheet

Bottom Sheet is used to display a modal list of menu items. They slide up over the main app content as a result of a user triggered action. Learn more

Here's an example of how to display a bottom sheet:

showBottomSheet(
  context: context,
  builder: (context) {
    return BottomSheet(
      // header: ...,
      description: Text('Description or Details here'),
      children: [
        ...,
        // Usually a `ListTile` or `TappableListTile`
      ],
    );
  },
),

To close it, just call Navigator.of(context).pop()

Bottom Sheet Showcase

Chip

Chips are compact representations of entities (most commonly, people) that can be clicked, deleted, or dragged easily.

Here's an example of how to create a chip:

Chip(
  image: CircleAvatar(size: 12.0),
  text: Text('Chip'),
),
Chip.selected(
  image: FlutterLogo(size: 14.0),
  text: Text('Chip'),
)

Light Chips

Dark Chips

Pill Button Bar

A Pill Button Bar is a horizontal scrollable list of pill-shaped text buttons in which only one button can be selected at a given time.

Here's an example of how to create a pill button bar:

int index = 0;

PillButtonBar(
  selected: index,
  onChanged: (i) => setState(() => index = i),
  items: [
    PillButtonBarItem(text: Text('All')),
    PillButtonBarItem(text: Text('Mail')),
    PillButtonBarItem(text: Text('Peopl')),
    PillButtonBarItem(text: Text('Events')),
  ]
)

Light PillButtonBar

Dark PillButtonBar

Snackbar

Snackbars provide a brief message about an operation at the bottom of the screen. They can contain a custom action or view or use a style geared towards making special announcements to your users.

Here's an example of how to display a snackbar at the bottom of the screen:

showSnackbar(
  context,
  Snackbar(
    content: Text('A new update is available!'),
  ),
);

Snackbar Example


Equivalents with the material library

The list of equivalents between this library and flutter/material.dart

Material Fluent
TextButton Button
IconButton IconButton
Checkbox Checkbox
RadioButton RadioButton
- RatingBar
- SplitButton
- ToggleButton
Switch ToggleSwitch
TextField TextBox
DropdownButton Combobox
- AutoSuggestBox
AlertDialog ContentDialog
MaterialBanner InfoBar
Tooltip Tooltip
- Flyout
Drawer NavigationPane
BottomNavigation BottomNavigation
Divider Divider
VerticalDivider Divider
Material Acrylic
ListTile ListTile
CheckboxListTile CheckboxListTile
SwitchListTile SwitchListTile
LinearProgressIndicator ProgressBar
CircularProgressIndicator ProgressRing
_DatePickerDialog DatePicker
_TimePickerDialog TimePicker
Scaffold ScaffoldPage
AppBar NavigationAppBar
Drawer NavigationView
Chip Chip
Snackbar Snackbar
- PillButtonBar

Contribution

Feel free to file an issue if you find a problem or make pull requests.

All contributions are welcome :)

Acknowledgements

Irrespective of order, thanks to all the people below for contributing with the project. It means a lot to me :)

GitHub

https://github.com/bdlukaa/fluent_ui
Comments
  • 1. FluentUI Widgets Localization Support

    This PR adds support for onboard widgets localization support using intl package.

    Related with https://github.com/bdlukaa/fluent_ui/issues/213

    I've included a wide list of most spoken languages: ~~Arabic, Bengali, English, Spanish, French, Hindi, Indonesian, Portuguese, Russian and Simplified Chinese using Google Translate.~~ UPDATE: ⭐️ @bdlukaa and I (@henry2man) agreed that we prefer confirmed localizations vs "Google Translate" ones, so we need some help!

    How to contribute:

    • Get any of the already verified translation files like https://github.com/bdlukaa/fluent_ui/pull/216/files#diff-d38a1072799c0e0b8936fb54ea8bcc732c76241afed954d025815eb8369aad32R1-R27
    • Get the file you want to review: for example: https://github.com/bdlukaa/fluent_ui/pull/216/files#diff-613ee02ebb6ae3d3300afd6f00fe30255b8e37336c5d89170bbbf9cee108c1daR1-R27
    • Review and copy the contents of your reviewed file and leave a comment!
    • Then we will merge them into the branch 👍🏻

    Current status:

    • [x] English ✅
    • [X] Spanish ✅ - Verified by @henry2man
    • [X] French ✅ - Already verified by @WinXaito
    • [x] Portuguese ✅ - Reviewed by @bdlukaa
    • [x] Russian ✅ - Reviewed by @raitonoberu
    • [x] German ✅ - Reviewed by @Larsb24
    • [x] Hindi ✅ - Reviewed by @alexmercerind
    • [x] Simplified Chinese ✅ - Reviewed by @zacksleo
    • Other languages are welcomed!

    I've added detailed instructions for adding new localizations in the README.md: https://github.com/bdlukaa/fluent_ui/pull/216/files?short_path=b335630#diff-b335630551682c19a781afebcf4d07bf978fb1f8ac04c6bf87428ed5106870f5


    If you run the example app and change the language of the browser, the corresponding messages are shown.

    Also I've done some little tweaks to shortcuts label implementation. AFAIK they aren't strictly that needs a translation (Ctrl or Cmd are standards names for corresponding keys).

    Please take notice of changes here: https://github.com/bdlukaa/fluent_ui/pull/216/files#diff-3705042816f3bd9d24304192811bed9d5104fa569a36f063a4166cfea97b845aR376-R377 and here https://github.com/bdlukaa/fluent_ui/pull/216/files#diff-8b7e9df87668ffa6a04b32e1769a33434999e54ae081c52e5d943c541d4c0d25R13-R14 in order to support multilanguage material localizations.

    Lastly, take a look at this List<Locale> constant: https://github.com/bdlukaa/fluent_ui/pull/216/files#diff-ccec5c5fa2c4d7bf6bc0e9748a8836c4bc5ff4a8c59461448d14047f6b242617R128-R139

    As the note says, this would be defined into DefaultFluentLocalizations but I cannot be able to make it work, so this was a working workarround.

    Pre-launch Checklist

    • [x] I have run dartfmt on all changed files
    • [x] I have updated CHANGELOG.md with my changes
    • [x] I have run "optimize/organize imports" on all changed files
    • [x] I have addressed all analyzer warnings as best I could
    • [x] I have added/updated relevant documentation
    • [ ] I have run flutter pub publish --dry-run and addressed any warnings
    Reviewed by henry2man at 2022-03-07 09:31
  • 2. [Question/Proposal] NavigationBody and state preservation

    I'm using NavigationView, a NavigationPane with menu entries and a NavigationBody.

    Looking into the source code, it looks that every time I change the main index the associated children[index] is rebuilt from scratch. But, in my case, I wish there were some kind of state preservation.

    I've added AutomaticKeepAliveClientMixin to every children but every time I change the page using the menu the previous state is lost.

    Is there a known way to preserve state when switching between menu options? If not, I think it would be great to add this option to NavigationBody.

    At the moment I think I am going to try to use a PageView, where I do have experience maintaining the state between changes.

    Here it is a sample code:

    import 'package:fluent_ui/fluent_ui.dart';
    
    void main() {
      runApp(MainScreenTest());
    }
    
    class MainScreenTest extends StatefulWidget {
      MainScreenTest({Key? key}) : super(key: key);
    
      @override
      State<MainScreenTest> createState() => _MainScreenTestState();
    }
    
    class _MainScreenTestState extends State<MainScreenTest> {
      int index = 0;
    
      @override
      Widget build(BuildContext context) {
        return FluentApp(
          home: NavigationView(
              content: NavigationBody(
                index: index,
                children: [
                  StatefulPage(title: "Screen 1"),
                  StatefulPage(title: "Screen 2"),
                  StatefulPage(title: "Screen 3")
                ],
              ),
              pane: NavigationPane(
                selected: index,
                onChanged: (i) => setState(() => index = i),
                // displayMode: PaneDisplayMode.top,
                items: [
                  PaneItem(icon: Icon(FluentIcons.home), title: Text("Screen 1")),
                  PaneItem(icon: Icon(FluentIcons.read), title: Text("Screen 2")),
                  PaneItem(icon: Icon(FluentIcons.event), title: Text("Screen 3")),
                ],
              )),
        );
      }
    }
    
    class StatefulPage extends StatefulWidget {
      const StatefulPage({Key? key, required this.title}) : super(key: key);
      final String title;
    
      @override
      _StatefulPageState createState() => _StatefulPageState();
    }
    
    class _StatefulPageState extends State<StatefulPage>
        with AutomaticKeepAliveClientMixin {
      int counter = 0;
    
      @override
      bool get wantKeepAlive => true;
    
      @override
      Widget build(BuildContext context) {
        super.build(context);
        return Mica(
          child: Column(
            children: [
              Text(widget.title),
              Button(
                child: Text("Current: $counter - Press to increment!"),
                onPressed: () => setState(() => counter++),
              ),
            ],
          ),
        );
      }
    }
    
    
    Reviewed by henry2man at 2021-11-17 06:35
  • 3. DateTimePicker update

    Fixes #306

    Pre-launch Checklist

    • [x] I have updated CHANGELOG.md with my changes
    • [x] I have run "dart format ." on the project
    • [x] I have added/updated relevant documentation
    Reviewed by bdlukaa at 2022-06-25 15:45
  • 4. Theming buttons and pane items

    Hello, I was trying this library together with the flutter_acrylic library, and I tried to apply an "app-wide" mica effect.

    I got some pretty decent results, but encountered some limitations, especially when trying to theme elements like buttons, pane items, text input boxes etc..

    image

    It isn't clear whether it is possible to chage these colors, in the specific case of pill buttons and pane items I wanted to use a translucent shade of white for dark theme and a translucent shade of gray for light theme instead of the default opaque colors.

    Reviewed by alesimula at 2021-12-04 22:55
  • 5. 🐛 Scrollbar This widget has been unmounted, so the State no longer has a context (and should be considered defunct).

    I get the following error message using a NavigationBody (which contains two views):

    The following assertion was thrown during a scheduler callback: This widget has been unmounted, so the State no longer has a context (and should be considered defunct).

    Consider canceling any active work during "dispose" or using the "mounted" getter to determine if the State is still active. When the exception was thrown, this was the stack: #0 State.context. (package:flutter/src/widgets/framework.dart:909:9) #1 State.context (package:flutter/src/widgets/framework.dart:915:6) #2 RawScrollbarState._maybeTriggerScrollbar. (package:flutter/src/widgets/scrollbar.dart:1236:98) #3 SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:1143:15) #4 SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:1088:9) #5 SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:996:5) #9 _invoke (dart:ui/hooks.dart:166:10) #10 PlatformDispatcher._drawFrame (dart:ui/platform_dispatcher.dart:270:5) #11 _drawFrame (dart:ui/hooks.dart:129:31) (elided 3 frames from dart:async)

    To be honest, I'm a little baffled. The error seems to be related to the NavigationBody (since I don't get the error when using a regular Material Scaffold). I tried adding AutomaticKeepAliveClientMixins to the views of the NavigationBody but that didn't help.

    Have any of you ever experienced something similar?

    Reviewed by slimyjimmy at 2021-09-21 10:08
  • 6. 🐛 TabView - shortcutsEnabled is not working

    Describe the bug I'm not able to enable TabView shortcuts using shortcutsEnabled: true. I've tested both on Chrome and MacOS native.

    To Reproduce Steps to reproduce the behavior:

    1. Setup a TabView with shortcutsEnabled: true
    2. Create some tabs
    3. Press 1-8 (first to eighth tab), nothing happens
    4. Press 9 (last tab), nothing happens
    5. Press Ctrl + W (using MacOS), nothing happens

    Expected behavior As documented, the shortcuts lets the user navigate through the tabs.

    Screenshots N/A

    Additional context N/A

    Reviewed by henry2man at 2021-11-11 16:36
  • 7. Implement command bars and dynamic overflow layout

    This is a first implementation of command bars as described in #231.

    A CommandBar control provides quick access to common tasks. This could be application-level or page-level commands.

    Refer to the spec.

    The current implementation does not implement the open/closed state, nor does it implement the secondary commands "more" button with dynamic overflow of items into the secondary commands menu.

    Also, during implementation of the example, I realized that I needed control over the primary and controller properties of the ListView inside of the TreeView, so this also adds these properties to TreeView.

    Here is what the examples look like with the various overflow behaviors:

    image

    And here is what it looks like alongside the large TreeView:

    image

    Pre-launch Checklist

    • [X] I have updated CHANGELOG.md with my changes
    • [X] I have run "optimize/organize imports" on all changed files
    • [X] I have added/updated relevant documentation
    Reviewed by klondikedragon at 2022-03-19 03:36
  • 8. FR: Dialog: Actions & Keybindings

    I think the dialogues can be improved a bit.

    After working with other frameworks and component palettes I think we could have the following improvements.

    • Actions: Instead of having a wide-open "List <Widget>? actions" we could have some specific class like DialogAction that allows having a title, maybe an (optional) icon, an onTap / onClick callback and more importantly, attributes like isDefaultAction or isDestructiveAction. The presentation would be as is usually done now with Button elements but we would already have semantics and the ability to work better with the UI (the default action is highlighted in color, the destructive action is red, RTL support ...)

    • Related to the above, I miss some key combinations:

      • Esc to close the active dialog
      • Enter to "execute the isDefaultAction=true action callback"
      • Tab to rotate the focus between the available actions, always starting with the default action

    What do you think?

    Reviewed by henry2man at 2022-01-12 11:08
  • 9. build issue

    /AppData/Local/Pub/Cache/hosted/pub.dartlang.org/fluent_ui-3.4.1/lib/src/controls/form/selection_controls.dart(35,52): error G366B1FB5: Too few positional arguments: 2 required, 1 given. [C:\Users\Jack Selvam\Downloads\fluent_ui-master (1)\fluent_ui-master\example\build\windows\flutter\flutter_assemble.vcxproj]

    Flutter 2.6.0-12.0.pre.825 • channel master • https://github.com/flutter/flutter.git Framework • revision 6a3ea7eb83 (27 hours ago) • 2021-11-23 17:38:02 -0800 Engine • revision 635b4202d7 Tools • Dart 2.16.0 (build 2.16.0-38.0.dev) • DevTools 2.8.0

    Reviewed by selvam920 at 2021-11-25 04:47
  • 10. 🐛 NavigationView UI artifacts on 125% DPI scaling

    This can also be observed on the example project, the app looks fine on 100% scaling, but a black line will appear between the navigation pane and the navigation body on 125% scaling; I've tried changing the clip behaviour to hardEdge and antiAliasWithSaveLayer to no avail

    image

    Reviewed by alesimula at 2021-11-18 08:45
  • 11. Error with upgrade from 2.0.3 to 2.2.1🐛

    Describe the bug After updating the package from 2.0.3 to 2.2.1 i get the following error message:

    ════════ Exception caught by rendering library ═════════════════════════════════ Expected a value of type 'SkDeletable', but got one of type 'Null' The relevant error-causing widget was NavigationView lib\app.dart:41

    Exception caught by acrylic.dart._generateImageTileRects -> (something with the assignment of colorFilter to paint.colorFilter. colorFilter is not in the correct internal state.

    To Reproduce I do not have the acrylic or system_theme packages.

    Reviewed by detroxx92 at 2021-06-29 13:24
  • 12. ComboBox menu overflows🐛

    Describe the bug ComboBox menu overflows when displayed in showDialog -> Content Dialog -> content

    To Reproduce Steps to reproduce the behavior: showDialog( context: context, builder: (context) => ContentDialog( content: ComboBox<String>( items: List.generate( 256, (index) => CPComboBoxItem( child: Text((index < 16 ? '0' : '') + index.toRadixString(16).toUpperCase()), value: index)), onChanged: (String? value) => setState(() => selectedConfig = value), value: selectedConfig, isExpanded: true, ), )

    Expected behavior I expect the ComboBox menu to have a scroll bar and it should stay in the viewport of the app.

    Screenshots App window size is 1280 x 720, I cropped the screenshots. Bug: image Expected: image

    Additional context

    Reviewed by khanliKU at 2022-07-01 07:20
  • 13. Teaching tips

    Reviewed by bdlukaa at 2022-06-29 23:13
  • 14. Rework split buttons

    SplitButton

    Is your feature request related to a problem? Please describe. The current implementation of Fluent's Split Button is very... verbose. It takes so much lines of code to make a simple split button.

    Describe the solution you'd like According to the native documentation:

    A SplitButton control has two parts that can be invoked separately. One part behaves like a standard button and invokes an immediate action. The other part invokes a flyout that contains additional options that the user can choose from.

    Which means SplitButtonBar should not take Button as an argument in the children list. Instead, there should be parameters that makes the configuration of both buttons (such as onPressed, style) and the flyout (such as content, openMode, position).

    The focus should be handled by the SplitButton.

    Describe alternatives you've considered N/A

    Additional context

    ToggleSplitButton

    A ToggleSplitButton control has two parts that can be invoked separately. One part behaves like a toggle button that can be on or off. The other part invokes a flyout that contains additional options that the user can choose from.

    Basically, it'd be a SplitButton with accent style applied to it, when on.

    Additional context

    • https://docs.microsoft.com/en-us/windows/apps/design/controls/buttons#create-a-toggle-split-button ToggleSplitButton open
    Reviewed by bdlukaa at 2022-06-29 23:05
  • 15. Selectable ListTile

    Additional context Original issue: #317 Theme resources: https://github.com/microsoft/microsoft-ui-xaml/blob/main/dev/CommonStyles/ListViewItem_themeresources.xaml

    Selected tile on ListView

    Reviewed by bdlukaa at 2022-06-29 21:59
  • 16. add japanese localization

    add japanese localization

    Pre-launch Checklist

    • [ ] I have updated CHANGELOG.md with my changes
    • [x] I have run "dart format ." on the project
    • [ ] I have added/updated relevant documentation
    Reviewed by chari8 at 2022-06-27 23:40
  • 17. 🐛Scrollable Horizontal List within a Scrollable Vertical List doesn't scroll

    Describe the bug I am trying to achieve a very common behavior nowadays which is to have a Scroll-able Horizontal List within a Scroll-able Vertical List.

    However, that doesn't seem to work while using FluentUI. It may be something that I'm doing wrong, but I've tried multiple ways to do it, and they all don't work.

    The Inner Horizontal List doesn't scroll, and just crops the remaining items inside

    To Reproduce Steps to reproduce the behavior:

    1. Go to This Repo
    2. Clone it
    3. Run 'flutter create .' in the terminal to generate the platform specific builds
    4. Run 'flutter run' to start the App

    Expected behavior Example of what it should do MRXOq

    Screenshots HorizontalBug

    Reviewed by bariccattion at 2022-06-22 14:52

Related

Easy form building in Flutter with a fluent schema API.
Easy form building in Flutter with a fluent schema API.

former - Easy form building in Flutter Motivation Formik is one of my favorite React libraries. It is a form library that drastically reduces boilerpl

May 17, 2022
A fluent API for generating valid Dart source code

A fluent, builder-based library for generating valid Dart code. Usage code_builder has a narrow and user-friendly API. See the example and test folder

Jun 22, 2022
Implements GTK Widgets, themes and titlebar buttons in Flutter. Based on the GNOME HIG
Implements GTK Widgets, themes and titlebar buttons in Flutter. Based on the GNOME HIG

GTK ❤️ Flutter Unofficial implementation of GTK Widgets, themes and titlebar buttons in Flutter. Based on the GNOME Human Interface Guidelines. Featur

Jun 12, 2022
Flutter plugin that implements Android's SMS User Consent API
Flutter plugin that implements Android's SMS User Consent API

sms_user_consent Request user's phone number (supports dual sim) and/or consent to read SMS without adding any permissions, using Android's SMS User C

Apr 9, 2022
This is an apps that implements fundamental features of Flutter (Android Apps Only)

rpl_apps_flutter A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started

Dec 28, 2021
Design system flutter - A framework contains SBB (Swiss Federal Railways) UI elements for Flutter Apps

Design System Mobile for Flutter Design System Mobile in Flutter (yes, it could

Jun 10, 2022
Flutter UI library based on IBM's Carbon Design System 💎
Flutter UI library based on IBM's Carbon Design System 💎

Flutter Carbon ‌Carbon is IBM’s open-source design system for products and experiences. With the IBM Design Language as its foundation, the system con

Jun 3, 2022
A Dart client for the NATS messaging system. Design to use with Dart and Flutter.

Dart-NATS A Dart client for the NATS messaging system. Design to use with Dart and flutter. Flutter Web Support by WebSocket client.connect(Uri.parse(

Jun 7, 2022
Stacked UI design system built for Flutter.

TODO: Put a short description of the package here that helps potential users know whether this package might be useful for them. Features TODO: List w

Jan 2, 2022
Provide powerfull tools to help you build your Flutter design system.
Provide powerfull tools to help you build your Flutter design system.

Provide powerfull tools to help you build your design system. About flutter_design contains packages to help you bootstrap your design system with a w

Jun 20, 2022
The company's design system

TODO: Put a short description of the package here that helps potential users know whether this package might be useful for them. Features TODO: List w

Nov 23, 2021
It's OK to love Flutter and hate hand-coding design elements. Parabeac-Core converts design files into Flutter code.
It's OK to love Flutter and hate hand-coding design elements. Parabeac-Core converts design files into Flutter code.

Parabeac-Core Parabeac-Core converts design files into Flutter code driven by open-source & community. Contribute · Discord Community · Designer Proto

Jun 14, 2022
NesPad-design-in-flutter - Create a design in flutter for a NesPad
NesPad-design-in-flutter - Create a design in flutter for a NesPad

NesPad Design in Flutter Diseño de un NesPad usando flutter nativo. Se hizo util

Jan 3, 2022
Excersises-app - Flutter excersises app design with 2 design pages
Excersises-app - Flutter excersises app design with 2 design pages

About The Project Flutter excersises app design with 2 design pages only Design

Jan 2, 2022
Glass-Design - Glass Design on one page writing in Flutter
Glass-Design - Glass Design on one page writing in Flutter

glassdesign writing in Flutter framework / GlassDesign fait en Flutter framework

Jun 15, 2022
A grid-based layout system for Flutter, inspired by CSS Grid Layout
A grid-based layout system for Flutter, inspired by CSS Grid Layout

Flutter Layout Grid A powerful grid layout system for Flutter, optimized for complex user interface design. Click images to see their code ✨ Featuring

Jun 20, 2022
RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices.
RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices.

RelativeScale is a simple custom sizing system for flutter widgets to achieve the same physical sizes across different devices. Usage It is VERY easy

Feb 14, 2022
Flutter control system widgets, like on-off controller.

control_system Flutter control system widgets, like on-off controller. Introduction A control system manages, commands, directs, or regulates the beha

Jan 9, 2022
A grid-based layout system for Flutter, inspired by CSS Grid Layout
A grid-based layout system for Flutter, inspired by CSS Grid Layout

Flutter Layout Grid A powerful grid layout system for Flutter, optimized for complex user interface design. Click images to see their code ✨ Featuring

Jun 20, 2022