Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement command bars and dynamic overflow layout #232

Merged
merged 15 commits into from
Mar 21, 2022

Conversation

klondikedragon
Copy link
Contributor

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

  • I have updated CHANGELOG.md with my changes
  • I have run "optimize/organize imports" on all changed files
  • I have added/updated relevant documentation

* Need to be able to control whether TreeView uses the primary
  ScrollController or uses a custom scroll controller
* If TreeView has shrinkWrap set, then do not use the primary scroll
  controller

These changes are needed so that if a parent ListView contains a
TreeView and the ListView has a custom scroll controller, then we
can avoid using the primary scroll controller and avoid exceptions
like "The provided ScrollController is currently attached to more
than one ScrollPosition".
A variant of SingleChildScrollView that provides horizontal scrolling
via the mouse wheel.

This is needed due to changes in Flutter 2.5, where the mouse can no
longer be used to drag and scroll horizontally on web/desktop platforms.

https://docs.flutter.dev/release/breaking-changes/default-scroll-behavior-drag
A `CommandBar` control provides quick access to common tasks. This
could be application-level or page-level commands.

See https://docs.microsoft.com/en-us/windows/apps/design/controls/command-bar

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.
@henry2man
Copy link
Contributor

I am very interested in this component. I also have an implementation, different but perhaps it can contribute things.For example, in my version I distinguish two groups of buttons, one of which is automatically hidden when there is no horizontal space.If you want we can mark it as a draft and spend a few days reviewing it together.

Copy link
Owner

@bdlukaa bdlukaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a basic review. Documentation and formatting needs to be improved.

Also, something like CommandBarDivider can be added?

lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
lib/src/utils/horizontal_scroll_view.dart Outdated Show resolved Hide resolved
Also changed cross-axis alignment for items within a CommandBar to be
center-aligned. Needed so that items will be properly vertically aligned
(including separators) if items are of different heights.
@klondikedragon
Copy link
Contributor Author

klondikedragon commented Mar 19, 2022

@bdlukaa - addressed comments and added CommandBarSeparator (corollary to PaneItemSeparator).

@henry2man - all help would be welcome! this could be added as an enhancement to this (whether in this PR or a follow-on) by:

  • Adding a new type of CommandBarOverflowBehavior (something like dynamicOverflow)
  • Adding a new CommandBar widget field secondaryItems (defaults to empty)
  • In build if secondaryItems (including any dynamic changes to it if overflow mode is dynamicOverflow) is not empty to automatically add a button using the FluentIcons.more icon that when clicked will present a flyout with the secondaryItems
  • Adding logic to somehow calculate during build or layout of CommandBar (if overflow mode is dynamicOverflow) which of the normal items should instead be considered part of secondaryItems

Do you have any code to reference that demonstrates how to figure out which of the items can fit vs which ones should be hidden into a secondary menu?

@henry2man
Copy link
Contributor

henry2man commented Mar 19, 2022

Do you have any code to reference that demonstrates how to figure out which of the items can fit vs which ones should be hidden into a secondary menu?

I have a very simple code: a width parameter in px that is evaluated during the execution of the "build" method. A LayoutBuilder could be used:

"if width is less than x then hide buttons and show menú button"

This approach is quite simple but can be extended/adapted if buttons have a constant width

* A CommandBar now takes a list of primary and secondary command bar
  items. The secondary command bar items do not yet appear anywhere.
* The primary command bar items are intended to be displayed on the
  horizontal area of the command bar.
* Conceptually similar to PaneItem, CommandBarItem is now given a
  "display mode" when building the widget. The display mode indicates
  if the item is being rendered on the primary (horizontal) area
  (and if it should display in "compact" mode) or the secondary
  (flyout menu when "more" button is pushed) area.
* A CommandBar can be given a `compcatBreakpointWidth` that indicates
  that if the widget is rendered with a smaller width, then it should
  render all of the items on the primary area in "compact" mode.
* Foundation is laid for supporting the secondary area and an overflow
  behavior mode of "dynamic", but is not yet implemented.
Similar to Wrap, but only displays widgets on a single run, and then
hides widgets that would have overflown. If widgets are hidden, then it
will display the specified "overflow widget".

This is useful to implement the dynamic overflow mode of command bars.

It could also be useful if a vertical nav bar wanted to implement a "more"
button instead of vertical scrolling.
Also add mainAxisAlignment and crossAxisAlignment fields
* Illustrates right-alignment and dynamic overflow modes.
* Moves command bar examples into a new navbar pane to avoid clutter.
@klondikedragon
Copy link
Contributor Author

@henry2man @bdlukaa -- After some research, I figured out how to implement a fully featured command bar, including:

  • Support for separate primary vs secondary command bar items, with secondary items shown in a flyout menu behind a "more" button
  • Dynamic overflow behavior to put overflowing primary command bar items into the secondary area (flyout menu)
  • A "compact" mode for primary command bar items, which is automatically selected if the width of the command bar is less than a specified breakpoint (off by default).
  • Support for right-aligned command bars (the fluent UI spec seems to prefer this in some contexts).

This was implemented with a new DynamicOverflow layout widget that supports both horizontal and vertical layouts. The code for this was carefully adapted from the standard Wrap widget. This widget could potentially be useful in the future to implement a "more" button for horizontal or vertical navbar pane items (instead of scrolling).

In the example app, with additional examples for command bars added, it was getting cluttered on the others pane, so I added another navbar pane. I could move it back to others if you want, it was just a little awkward testing the wrapping behavior with a lot of stuff above it.

All the new functionality is best illustrated with a video:
fluent_ui_commandbar_dynamic_overflow

@klondikedragon klondikedragon changed the title Implement basic command bars Implement command bars and dynamic overflow layout Mar 20, 2022
@bdlukaa
Copy link
Owner

bdlukaa commented Mar 20, 2022

SO COOL! This will open possibilities for the same thing on NavigationView! I'll review ASAP

Copy link
Owner

@bdlukaa bdlukaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome job!

lib/src/controls/surfaces/commandbar.dart Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
lib/src/controls/surfaces/commandbar.dart Outdated Show resolved Hide resolved
@klondikedragon
Copy link
Contributor Author

@bdlukaa - I've addressed comments and cleaned up the concept of widgetBuilder to move it into a separate type of command bar item. See if you like the approach better.

Copy link
Owner

@bdlukaa bdlukaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome work! LGTM

@bdlukaa bdlukaa merged commit d08d1d0 into bdlukaa:master Mar 21, 2022
@klondikedragon klondikedragon deleted the commandbar branch March 22, 2022 03:11
@WinXaito
Copy link
Collaborator

Incredible !

@WinXaito WinXaito linked an issue Mar 22, 2022 that may be closed by this pull request
@WinXaito WinXaito mentioned this pull request Mar 22, 2022
@bdlukaa bdlukaa mentioned this pull request Apr 9, 2022
3 tasks
@bdlukaa
Copy link
Owner

bdlukaa commented Apr 22, 2022

@klondikedragon Hello! I'm having issues with #277. It uses DynamicOverflow, but I need to ensure the current selected item is being displayed. Can you help me on that? If you want, we can talk on discord :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement command bars
4 participants