microsoft-ui-xaml icon indicating copy to clipboard operation
microsoft-ui-xaml copied to clipboard

Proposal: Adding a Expander Control to the set of WinUI controls.

Open eduardoaguacate opened this issue 3 years ago • 86 comments

Proposal: WinUI Expander Control

A spec has been opened with a PR for this issue. Feel free to continue general discussion in this proposal!

Summary

Throughout Windows, different expander controls are used by Windows Security, Settings, Photos, Paint 3D, the Notification Center, 3D Viewer, Toasts and the UWP Onedrive app. There’s currently no consistent "Windows" way of addressing this common UX pattern. An Expander control is motivated by both its use in many app scenarios and achieving parity with WPF.

Rationale

  • There should be a built-in and consistent Fluent way to expand and collapse content.
  • Expander scenarios exist across many surfaces that are not aligned in behavior and style, including being Narrator-friendly, keyboard controls, animations, designs, and high contrast changes.

Scope

Capability Priority
Provide consistent expander behavior across WinUI apps Must
Expand in size (pushing other content) and collapse based on user interaction with the control Must
Support controls like Button, ToggleSwitch in the unexpanded and expanded content Must
Support Expanding in all 4 directions Should*
Support modifying all content (including the header) in expanded state Could
Support expanding an InfoBar (open question on implementation) Could
Include "accordion behavior" logic between Expanders Won't
Be light dismissible Won't

*The v1 Expander could be scoped to only expand in the downwards direction, with default down and ExpandDirection added later.

Important Notes

Proposed API

Public enum ExpandDirection 
{ 
Down = 0 
Up = 1 
Left = 2 
Right = 3 
} 

public class Expander : ContentControl 
{ 
Expander(); 

public object Header {get;set;} 
public DataTemplate HeaderTemplate { get;set; } 
public DataTemplate HeaderTemplateSelector {get;set;} 

public static readonly DependencyProperty HeaderProperty; 
public static readonly DependencyProperty HeaderTemplateProperty; 
public static readonly DependencyProperty HeaderTemplateSelectorProperty {get;} 

public bool IsExpanded { get;set} 
public ExpandDirection ExpandDirection { get;set;} 

protected virtual void OnExpanded(); 
protected virtual void OnCollapsed();

public event Expanded; 
public event Collapsed; 

public static readonly DependencyProperty IsExpandedProperty; 
public static readonly DependencyProperty ExpandDirectionProperty; 
} 

Visual States:  
ExpandStates: Expanded/Collapsed 

Accessibility: 
Support Expand/Collapse pattern (IExpandCollapseProvider) 

Expander Controls Elsewhere

Examples of Expander Scenarios

expandcontrol-4 1 expandcontrol-2

Open Questions

  • In discussion with the WinUI team, it was brought up that a V1 scoped to expand downward would shorten development time and make Expander available for developers sooner (as the scenarios for Expander thus far have all been downward), and a planned V2 could add ExpandDirection soon after. In your apps, are there any scenarios where Expander would need to expand in directions other than downward?

  • How should Expander work with InfoBar? Adding expanding functionality to InfoBar? Putting InfoBar as the content of an Expander? The reverse?

eduardoaguacate avatar Sep 11 '20 20:09 eduardoaguacate

Expander is very useful and I've been using the Windows Community Toolkit version since it was added. I wouldn't re-invent the wheel too much though, just porting over the code from the toolkit would be perfect for version 1.0 in my opinion.

Another example: the ColorPicker with it's 'MoreButton' could use this.

robloo avatar Sep 13 '20 03:09 robloo

Thanks so much for submitting this proposal! I'm going to make some edits, including differentiating between what I think are true Expander scenarios and what are more like Flyout/MenuFlyout uses.

kat-y avatar Sep 21 '20 17:09 kat-y

I've updated this proposal to include more details on the scope, a proposed API, and the following open question.

  • Do we need to support ExpandDirection in a v1 Expander? Are there common app scenarios where Expander would need to expand in directions other than downward?

Would love feedback on how these fit or don't fit with your use cases for Expander!

kat-y avatar Sep 24 '20 22:09 kat-y

I've updated this proposal to include more details on the scope, a proposed API, and the following open question.

  • Do we need to support ExpandDirection in a v1 Expander? Are there common app scenarios where Expander would need to expand in directions other than downward?

Would love feedback on how these fit or don't fit with your use cases for Expander!

It does seem like a basic function of the control

mdtauk avatar Sep 24 '20 23:09 mdtauk

It does seem like a basic function of the control

@mdtauk do you see ExpandDirection other than downward being a common app scenario? The examples of Expander behaviors that I see are far more often expanding downwards - I would definitely like Expander to have ExpandDirection but is it necessary in a v1?

kat-y avatar Sep 24 '20 23:09 kat-y

Yes, we need expand direction. There are many cases for using it and it would be an unnecessary breaking change to the control template after a v1 release to add it. The Expander API hasn't changed much since WPF and the proposal here has all the necessary properties/events/methods already. I would just implement it all in one shot and we can be done with this control. Design-wise the UWP Community Toolkit made the necessary changes to better work with touch. I think we have all the pieces and there is no need to re-invent anything.

Edit: The community toolkit also has a ContentOverlay property. That might be something to skip in a V1.

robloo avatar Sep 24 '20 23:09 robloo

Yes, we need expand direction. There are many cases for using it and it would be an unnecessary breaking change to the control template after a v1 release to add it.

@robloo Could you elaborate on how this would be a breaking change? My understanding is we could avoid it being breaking with V1 having downward expansion, and V2 could add ExpandDirection and default to downward.

kat-y avatar Sep 24 '20 23:09 kat-y

It does seem like a basic function of the control

@mdtauk do you see ExpandDirection other than downward being a common app scenario? The examples of Expander behaviors that I see are far more often expanding downwards - I would definitely like Expander to have ExpandDirection but is it necessary in a v1?

Chat apps which load new list content from the bottom up being one of them maybe.

Beyond the very basic essential:

  • IsCollapsed
  • IsExpanding
  • IsExpanded
  • IsCollapsing

As well as IsEnabled

The next core thing is where to expand to.

  • ExpandUp
  • ExpandDown
  • ExpandLeft
  • ExpandRight

mdtauk avatar Sep 24 '20 23:09 mdtauk

Chat apps which load new list content from the bottom up being one of them maybe.

@mdtauk I don't fully understand what you mean with this chat apps example - could you elaborate? As for the properties - the proposed API is based off the WPF Expander so I think IsExpanded and ExpandDirection would cover them. What would IsEnabled be used for - is there an app scenario where you'd want to disable an Expander?

kat-y avatar Sep 24 '20 23:09 kat-y

Another example I've used in the past are secondary, editable properties that should usually be hidden. These are shown at the bottom of an editor only when clicking an 'options' button and the expander opens upwards. It's really just up to the design you are going for. There are many useful cases for expanding different directions and it seems unnecessary to artificially restrict this especially when past convention is so strong. I don't think any of this would be too difficult in a V1 of the control especially since all the problems have already been solved in the community toolkit and WPF.

@robloo Could you elaborate on how this would be a breaking change? My understanding is we could avoid it being breaking with V1 having downward expansion, and V2 could add ExpandDirection and default to downward.

https://github.com/windows-toolkit/WindowsCommunityToolkit/blob/master/Microsoft.Toolkit.Uwp.UI.Controls/Expander/Expander.xaml

I suppose if you are very careful in designing the template and visual states it is possible to make it non-breaking. However, to do that you really need to design the functionality anyway so you might as well implement it. This is all fairly basic and there is no reason for a V2 plan from the get-go on this control.

I know its enticing to re-invent the wheel. But please keep it so people porting apps from WPF to WinUI can do it without anything but absolutely necessary code changes. WinUI needs to start correcting some of the mistakes with UWP.

robloo avatar Sep 24 '20 23:09 robloo

What would IsEnabled be used for - is there an app scenario where you'd want to disable an Expander?

@mdtauk Is correct, this needs to support IsEnabled as well. Disabling controls is pretty strong convention anytime there is the possibility of input or state change. Please don't make us defend that.

robloo avatar Sep 24 '20 23:09 robloo

In the screenshots above, windows security has an expander for the antivirus section as well as the left navigation menu. This shows a very realistic use of the expander in more than one direction that a lot of apps would need to support. My vote is for supporting multiple directions in V1.

JustABearOz avatar Sep 25 '20 01:09 JustABearOz

@robloo

Another example I've used in the past are secondary, editable properties that should usually be hidden. These are shown at the bottom of an editor only when clicking an 'options' button and the expander opens upwards.

Could you elaborate with a screenshot or specific app where this happens so I can understand the scenario more? I can think of editors where a options button opens a popup with more buttons, but in the ones I'm familiar with the other content isn't pushed upwards - a popup/flyout behavior rather than an expansion.

I suppose if you are very careful in designing the template and visual states it is possible to make it non-breaking. However, to do that you really need to design the functionality anyway so you might as well implement it. This is all fairly basic and there is no reason for a V2 plan from the get-go on this control. I know its enticing to re-invent the wheel. But please keep it so people porting apps from WPF to WinUI can do it without anything but absolutely necessary code changes.

I agree with you that porting apps from WPF to WinUI should be as smooth as possible! In discussion with the WinUI team, it was brought up that a V1 scoped to expand downward would shorten development time and make Expander available for developers sooner (as the scenarios for Expander thus far have all been downward), and a planned V2 could add ExpandDirection soon after. (I'll edit the open question to have this additional context) This is why I'm hoping to understand if there are specific use cases developers have for non-downward Expander! 😄

Disabling controls is pretty strong convention anytime there is the possibility of input or state change. Please don't make us defend that.

Thanks for explaining this, it totally makes sense that disabling the state change is a desired feature for this kind of control!

kat-y avatar Sep 25 '20 02:09 kat-y

In the screenshots above, windows security has an expander for the antivirus section as well as the left navigation menu. This shows a very realistic use of the expander in more than one direction that a lot of apps would need to support. My vote is for supporting multiple directions in V1.

@JustABearOz I think the left navigation menu is a NavigationView, actually. 😃 I agree that the antivirus section is an Expander scenario, in this case expanding downwards. Would love to know any specific use cases you have for non-downward Expander!

kat-y avatar Sep 25 '20 03:09 kat-y

@kat-y Ok, that takes away a need for left/right, but 2 examples in windows that seem to expand up that could easily apply to apps: 1: The screenshot above with the quick actions menu. Pretty sure that expands up. 2: In windows, the popup calendar form the system tray has a section which expand up to show agenda/appointments.

Is it possible to support Up/Down for V1 instead of just Down?

JustABearOz avatar Sep 25 '20 03:09 JustABearOz

1: The screenshot above with the quick actions menu. Pretty sure that expands up.

@JustABearOz thanks so much for bringing up these examples! For 1: I think this is an interesting edge case - the expansion is 'downwards' from the 'header' (the expand button), but the control itself is positioned at the bottom of the surface so the header (and the expanded content) has to 'shift' upwards (otherwise it would run off the screen!). Seems like a good way to handle having an expanding item at the 'bottom' of an app, do you agree?

2: In windows, the popup calendar form the system tray has a section which expand up to show agenda/appointments. Is it possible to support Up/Down for V1 instead of just Down?

I agree with you, this is a scenario where the header is at the bottom of the area and expands up! In this case the calendar's expander (and the popup as a whole) is tied to the taskbar - have you encountered scenarios in apps where expanders have a similar tied positioning that necessitates upward expansion?

kat-y avatar Sep 25 '20 03:09 kat-y

@kat-y I mean no offense but I feel like we are having to re-explain things that were known 15 years ago. I don't understand why you are asking us to give examples of expand direction in real-world usage. I expect internally you have to take this to spec review and defend it to management. But the explanation can simply be (1) you need to empower users to achieve their design targets, it's not up to Microsoft to say what is/is-not possible to do with controls it's up to app developers/designers to discover what is best for their use-case (a critical concept for look-less controls) (2) Most importantly, this is not a new idea at all. You are copying over an existing API in this area and need to maintain app compatiblity. Again, if this was a new idea I would understand more why we have to defend it -- it's good to make sure features are useful before investing the time in them.

Aside from the header there are literally two properties in this control and if it was C# I could write it in a few hours using the WCT base. We will spend more man-hours just talking about it than implementing it as it exists today in WPF/WCT.

robloo avatar Sep 25 '20 04:09 robloo

Thanks @robloo for the input, I'm reaching out to the WinUI team to discuss how we can make these proposals more robust initially when they exist in other third-party libraries like the Toolkit. I definitely think it should be something part of the issue template to call out existing examples.

FYI @ranjeshj @ryandemopoulos @stmoy

michael-hawker avatar Sep 25 '20 16:09 michael-hawker

@robloo Thank you for being honest with me! I understand that app developers should be able to determine what fits their use-case best, and that app compatibility is important. I'm hoping that discussion with @michael-hawker and the WinUI team will help us move forward productively in scoping Expander!

Previously I didn't have any concrete examples of Expanders being used in non-downward direction. I will bring any examples from the WinUI community (including the calendar flyout that @justABearOz pointed out) and any that I learn from Michael to discussions with the WinUI Team as evidence for keeping ExpandDirection in v1 of Expander.

I've updated the proposal with a list of Expander controls I'm aware of - let me know if I've missed something.

kat-y avatar Sep 25 '20 16:09 kat-y

I've taken a look at both the WPF source code and WCT source code. I'm confident this can be implemented in WinUI in a few hours as well. The control should follow the WCT implementation from what I've seen although the ContentOverlay property probably should be renamed or left out of V1.

WPF: https://github.com/dotnet/wpf/blob/master/src/Microsoft.DotNet.Wpf/src/Themes/XAML/Expander.xaml https://github.com/dotnet/wpf/blob/master/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/Expander.cs

WCT: https://github.com/windows-toolkit/WindowsCommunityToolkit/tree/master/Microsoft.Toolkit.Uwp.UI.Controls/Expander

As both of these sources are from Microsoft and licensed MIT they should be the base, don't start from zero. Xamarin Forms does not align with the concepts of WPF->WinUI so should probably be disregarded (there is no additional functionality either). The 3rd party solutions also don't have any groundbreaking new ideas from what I've seen. This control has largely stood the test of time.

robloo avatar Sep 25 '20 16:09 robloo

@robloo Thank you for being honest with me! I understand that app developers should be able to determine what fits their use-case best, and that app compatibility is important. I'm hoping that discussion with @michael-hawker and the WinUI team will help us move forward productively in scoping Expander!

Previously I didn't have any concrete examples of Expanders being used in non-downward direction. I will bring any examples from the WinUI community (including the calendar flyout that @JustABearOz pointed out) and any that I learn from Michael to discussions with the WinUI Team as evidence for keeping ExpandDirection in v1 of Expander.

Well, my point is there really shouldn't be too many discussions about this. I'm choosing to voice my frustrations here as this control is a perfect example. The new pager control or bread crumb controls do need more oversight and it's important to follow the process. However, the overhead of a large process is showing through here and again, you will spend far more man-hours doing non value-added paperwork and discussions that just implementing the control from WCT. I've also yet to see the WinUI team use other, prior work which is somewhat of a concern. There is no need to re-engineer the XAML control template.

robloo avatar Sep 25 '20 17:09 robloo

Welcome to the WinUI project @kat-y - Xaml has a long history but can be a little quirky to those new to it. While WinUI is an opportunity to rethink how things work, in this case, expander is a relatively simple control and so a simple move from WPF to WinUI should suffice.

@robloo I disagree with your assertion that there is no need to re-engineer the XAML control template. WPF AFAIR has a number of chrome like elements which would be out of place in WinUI/Fluent.

Handling the Chevron and touch target sizes, as well as using the font scaling sizes. The Chevron should be easy to remove, or to add.

image This example has a chevron in line with the text.

image This example has no chevron at all

image This example has a preceding side facing chevron


As for the implementation, there should be an animated transition when opening and closing, unless the user has turned off animations, then it just switches states.

mdtauk avatar Sep 25 '20 17:09 mdtauk

As for the implementation, there should be an animated transition when opening and closing, unless the user has turned off animations, then it just switches states.

I was just about to ask about animations. Should there be a way to disable them for the control, e.g. in scenarios where animating layouts would be too expensive? Not all users/developers want animations for such things as it might feel a bit to unresponsive or just not wanted (e.g. TreeView). Having to not retemplate the control to customize that point might be better. Another thing that could be customizable is the animation duration, in some cases short animations are better then longer ones.

marcelwgn avatar Sep 25 '20 17:09 marcelwgn

Thanks for all the great discussions. some thoughts

  • We will need to update the template as @mdtauk mentions to account for new design as well as opportunities to reduce the elements/improve performance if possible.
  • IsEnabled is inherited from Control, so I would expect that to work.

ranjeshj avatar Sep 25 '20 18:09 ranjeshj

As for the implementation, there should be an animated transition when opening and closing, unless the user has turned off animations, then it just switches states.

I was just about to ask about animations. Should there be a way to disable them for the control, e.g. in scenarios where animating layouts would be too expensive? Not all users/developers want animations for such things as it might feel a bit to unresponsive or just not wanted (e.g. TreeView). Having to not retemplate the control to customize that point might be better. Another thing that could be customizable is the animation duration, in some cases short animations are better then longer ones.

I believe some controls have a Transition property that could be assigned to. So if a non-animated storyboard was included as a resource, it could be applied and that handles that without any retemplating.

You would have to override the transition when the system setting turns animations off.

UIElement.Transitions? https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.uielement.transitions?view=winrt-19041

Also with the IsEnabled property, there needs to be a Disabled state. Should there be a Disabled Expanded, and Disabled Collapsed, or is Disabled always collapsed?

mdtauk avatar Sep 25 '20 18:09 mdtauk

Interesting point about animations. We turn off all animations with the system setting, but I don't think we expose knobs to turn off animations other than by re-templating currently.

ranjeshj avatar Sep 25 '20 18:09 ranjeshj

Interesting point about animations. We turn off all animations with the system setting, but I don't think we expose knobs to turn off animations other than by re-templating currently.

I believe you could add a Style that overwrites the Transition collection with null in the case that you want to turn animations off, assuming there is a Transition collection to overwrite.

stmoy avatar Sep 25 '20 18:09 stmoy

Including an ExpandTransition and CollapseTransition, that can use the direction set by the control's property - which could allow the dev to set the transition for each.

I like the idea, but I don't think there is a way today to create custom theme transitions which would limit the ability to customize. This would allow easily disable it though by removing it.

mdtauk avatar Sep 25 '20 18:09 mdtauk

Also with the IsEnabled property, there needs to be a Disabled state. Should there be a Disabled Expanded, and Disabled Collapsed, or is Disabled always collapsed?

Why not mirror the TreeView control where you can use the IsExpanded and IsEnabled properties to create whatever combination you need of the two? If disabled expanded works best in some case, that can be done. If you need disabled collapsed, that is possible too this way.

Felix-Dev avatar Sep 25 '20 18:09 Felix-Dev

@robloo I disagree with your assertion that there is no need to re-engineer the XAML control template. WPF AFAIR has a number of chrome like elements which would be out of place in WinUI/Fluent.

@mdtauk Well, my recommendation was we "should follow the WCT implementation" here: https://docs.microsoft.com/en-us/windows/communitytoolkit/controls/expander. The design changes to adapt to touch and a more modern interface were already made. Of course no one can do designs as good as you so I'm sure there is room for improvement. Still changing the 'design' wouldn't require re-engineering the template to support all expand directions. WCT should be the base and then if we have new styling to apply, very well, it can be done quickly but not from scratch.

robloo avatar Sep 25 '20 19:09 robloo