Open SavoySchuler opened 5 years ago
Made a few minor updates Savoy:
Great proposal.
I feel like with this display mode:
The First & Last buttons are redundant, so the default state could be None. That is assuming the first and last index are displayed by default, which seems to be the case: "Visibility of the first/last index can be disabled."
Regarding these open questions:
Should numerals in the button panel be replaceable with glyphs?
Seems to be a popular design choice, and I'd like to have the option.
Will some scenarios require the glyphs to not be clickable (buttons not needed and spacing may be narrowed)?
I'm sure some designers might want this option, but as a user I pretty much always dislike when I can't interact with them.
Should a timer and wrap-around feature be added?
Would be useful, but low priority IMO.
I think it's important to highlight the 'not in scope' part in the rationale a bit better, as that was my first question/thought:
The scope of this proposal is not provide a data paging solution at this time but to start with UI paging as a foundation on top of which data paging may be integrated.
So, to clarify, this is a UI element only, but the developer is still responsible for manipulating the source to the GridView/ListView/etc... to make the pages work? It'd be good to provide a code sample here about how that's expected to be accomplished to see how this scenario would work end-to-end.
(Also, in the sample XAML, don't indent the pager control as it makes it look like it goes in the GridView component not next to it in the tree.)
@kmgallahan Great feedback, thank you! I agree it reduces redundancy to only have the LastButton/FirstButton or the range bounds visible. Upon reviewing several example implementations, it appears most actually have neither - which I will update the default behavior to be. I have left the redundancy of these optional components in the Usage Examples to help communicate what they are and how they look.
I agree that glyph panels are a popular design. I am not sure if I would if it would make more sense to have "GlyphPanel" as a DisplayMode, subclass of a pager parent, or just as an option to replace numerals with glyphs in the ButtonPanel DisplayMode. When you think of wanting to create a glyph panel for these kind of displays, are one of these options where you would think to start?
@michael-hawker Thank you for the great feedback! That is correct - by developing both sides of this solution as distinct but cooperative components, we can allow PagerControl to be more flexible for developers. I will refine this proposal with clear examples that show end-to-end solutions for these scenarios and I will tag you in a comment when new Usage Examples are posted. Thanks for the code catch, I have it updated!
@SavoySchuler My initial thought was that a subclass would somewhat defeat the purpose of the DisplayMode
property. However, looking over the properties & proposed features, it seems many of them would only be applicable to a particular display mode.
GlyphMode
would not use:
NumberOfIndicesShowing
(assuming most use cases involve a small fixed number of glyphs)LastButton
* et al.FirstButton
* et al.Ellipsis
* et al.PrefixText
NumberOfPages
While it would be the exclusive use case for a built-in timer function (based on 'normal' design choices of not auto-cycling through paged data).
Similarly ButtonPanel
mode doesn't need:
PrefixText
NumberOfPages
and similar situation for the EditableComboBox
mode.
So using a DisplayMode
property vs. base class / subclass approach would result in a rotating set of irrelevant properties, depending on the selected mode. Not that having a subclass for every mode seems like an amazing approach either... classic programming dilemma.
@kmgallahan I agreed! The button panel and combobox scenarios certainly have more in common with each other than either of them do with glyphs. Consider a pager base class with two subclasses: one for glyphs and another for both ButtonPanel + ComboBox (which uses the display mode property to set the core indexing component). Does this feel like an ideal compromise to pair the two display modes with common properties as one sublass and to share all the methods and events common to all three from the base class? I feel like this the reduces redundancy of a sublcass-only approach and adds clarity by removing atavistic properties left by the DisplayMode only approach, but I also want to make sure I am not adding complexity with out benefit.
@SavoySchuler Seems like a good compromise yes. Having the base class also provides an opportunity for reuse in the future, if there were ever some 4th/5th modes that one might want to introduce (without having to always propose more DisplayMode
s and bloating the single class with properties).
Some interesting iterations here. I just want to add that you want to be sure to think about freeway scenarios for both sighted and blind users. The numbers are definitely more helpful for both the blind and sighted, however the combo box is much easier to understand for blind users. That said, I would not offer the version with just pips instead of numbers, and I would suggest making the combobox version default.
@betrue-final-final Thank you for this feedback! I will set the default display mode to be ComboBox.
Regarding the glyphic display mode, do you think it would it be an appropriate compromise for it to visually display pips but read out numerals to narrator? In this case, you could think of them as the same display mode that differs only in whether glyphs or numerals are visually displayed on the button panel but all other accessiblity navigation and output would be the same. This glyphic display pops up in a lot of store applications and are often custom implementations that are not accessibility inclusive. I believe we have an opportunity to create an accessible version of this control where there have previously been few. Please let me know if you see things differently as inclusion of the glyphic display mode is still an open question. Thanks again for starting this conversation!
An additional open question I think would be great to have answered from the community is whether anyone has encountered situations other than a FlipView UX that required the use of the dots / glyphs? The FlipView's design guidance refers to it as a type of context indicator. If it's only used with a FlipView UX then should FlipView just provide that as a built-in option?
@micahl Great question! I have updated the Open Questions section to include this.
Is this something we could use for Forms? See the last comment in Issue #82.
@LucasHaines I assume you mean this comment? (As "last" will potentially change.) As it's just a UI element with no functionality, I see no reason why it couldn't be used with a form. Why you'd want it to be used for all forms, I'm not sure.
@SavoySchuler Regarding the open question about custom glyphs for indicators, I have known brands who were really keen to do that customization for added brand identity flourishes. I have also seen different icons used for different pages but that seems like a very niche need and not something I'd encourage by prioritizing.
How will this control react to a lack of space for all sub-elements having space to be displayed? -- Will the number of options displayed be reduced? Will the control be clipped if it overflows the available space? Will the space between sub-elements be further padded when there is additional space to expand into?
I think when talking about the forms control, a pagination control of this complexity would not be ideal, and could encourage complexity where it need not be.
When I commented on pagination I was thinking more about the Xbox or Windows OOBE style of pagination or grouping of steps - so you see how far into the form process you are.
Maybe this type of simple pagination can be part of the control proposed - perhaps it could be seen as a primitive used by various controls - but pagination as a form of progress indication.
@LucasHaines, @mrlacey is correct that this control would accomodate your scenario and the core functionality of the ones surfaced by by @mdtauk (noting we would need to expand on the visual styling to meet these scenarios fully).
@mrlacey Your question is one that I am actively exploring. I am starting to believe that offering this widget without built-in data paging capabilities will not be enough to fully enable the experiences we would like to help developers create for their customers. I am thinking that this proposal might benefit from being expanded to include an optional data paging component that would handle data paging, displaying content, and window resizing. Leaving this data paging component optional would also still allow for more advanced and custom scenarios that make use of only the UI component like @LucasHaines might need for forms or @mdtauk might need for grouping set up steps.
@mrlacey Thanks for your feedback on the glyphic display mode! Do you happen to have any of those examples of brands using custom glyphs that you can point me toward?
Hey everyone. As we're working on the pagination control over in Fabric, we were considering building a more primitive "pager" control that is mostly this:
It'd maintain state, have first/prev/next/last controls, have a public interface for changing state etc, but wouldn't be concerned with how the paging view was represented (numbers, numbers with ellipsis, glyphs, or even pivot buttons). It would also include an optional child view (above or below) to render content based on current page, making it foundation for carousels, FREs, pivots etc.
Do you typically do similar abstractions in UWP? Is this something you're considering with this control?
@SavoySchuler Sorry, nothing public I can point to anymore. Maybe it's a trend that's passed now but I have memories of re-templating lots of low-level things like a progress ring so it used different shapes, instead of circles, etc. When this issue came up I immediately thought of designers I've worked with in the past who would love the ability to easily change these glyphs.
If the glyphs for each button are exposed as a DependencyProperty with default values set for the SegoeMDL2 fonts - then creating a style with new FontFamily and Glyph values set should provide the flexibility and ease of change devs who need it, would want.
It would also include an optional child view (above or below) to render content based on current page, making it foundation for carousels, FREs, pivots etc. Do you typically do similar abstractions in UWP?
@micahgodbolt - No, UWP controls tend to be complete and ready to use out of the box rather than being smaller building blocks. Molecules rather than atoms, if that analogy makes sense. We have a Pivot control which is in no way related to the proposed PagerControl.
@YuliKl totally understand. In React we're always looking for ways to reuse smaller controls, or to breaking up a single control into smaller reusable pieces. As i'm less familiar with UWP, I'm not sure how well the platform supports that type of sharing.
I think you'd find in practice that there's more similarity than differences. Bigger controls (molecules) that contain a lot of built-in policy are made up of smaller controls (atoms) that have less policy. Molecules are easy to use. Atoms are more flexible and simple. Expectations around a given scenario and its similarity to others heavily influence the approach taken to solve it. @micahgodbolt It would be useful to understand what scenarios you've encountered.
@micahl When I look at pager controls I see three things, 1 stateful container with controls to go to first, prev, next last, and secondly a view to display the current page and give UI for selecting the page, and lastly an optional content region to render content associated with that page. So if we built a paging control that only worried about state, the inner and outer view, and controls/public methods for changing the page, then we'd have a really flexible control that could be used to create carousels, first run experiences, pivots, and pagination.
This way everything that was built on this control would share a common public interface, and could easily be customized to add functionality, or change the way in which the UI is displayed. It also means that when we go to add functionality, we can add it in one place and everything else gains the same functionality. We already have too many similar controls where a feature is added to one of them, and then someone asks for that feature to be added to others.
Great example, we have an underlined TextField variant (just an underline, no box border), and there's a request to add that variant to datepicker, dropdown and comobobox (it's already added to search). https://github.com/OfficeDev/office-ui-fabric-react/issues/5631
So you can see it would have been better for all of those controls to be built off of TextField, so that they could each benefit from that design variant.
Fabric and FluentWeb are all seemingly isolated Web implementations of the Fluent Design ideals.
The Windows XAML controls were separate and part of the OS until Windows UI Library.
So as the Windows UI Library slowly takes over as the default way to handle XAML controls, maybe the XAML control templates can slowly adopt the alternative styles and other controls to match the Web implementations.
The CommandBarFlyout, DropDownButton, etc which were added in 1803-1809 were the result of the Office UWP team folding back work they did for all devs to use. So lets keep our fingers crossed
It would also include an optional child view (above or below) to render content based on current page, making it foundation for carousels, FREs, pivots etc. Do you typically do similar abstractions in UWP?
@micahgodbolt - No, UWP controls tend to be complete and ready to use out of the box rather than being smaller building blocks. Molecules rather than atoms, if that analogy makes sense. We have a Pivot control which is in no way related to the proposed PagerControl.
There is a Primitives namespace, and I there are controls like the NavigationView which creates its own sub controls like NavigationViewItem - or Pivot and its PivotHeaderItem, PivotViewItem.
So it is perfectly possible to create sub controls designed to be consumed and used by a "full control" which a dev places onto the design view.
Yeah, I don't think XAML controls have to be all encompassing. In fact I feel there can be cases where large controls should be made out of smaller controls which could be consumed elsewhere as well.
For instance part of a NavigationView could be a TabView control. And the InkToolbar is made up of various Buttons and things.
So I think there's places and patterns for both.
In terms of a pager control, I could see the 'visualization' of numbers or dots be a some other visualization component that could be restyled or such vs. the pieces that control the actual navigation.
Having done this a few years, and worked with a lot of partner teams using our framework, I'm quite familiar with all of the customization requests that we get. "I want to use your control, but swap in this piece for that piece". So we really try to create controls with that functionality in mind. That can be best done by creating the controls via composition of many smaller, single function pieces.
@micahgodbolt Thank you for surfacing this conversation! The intention for this control would be to develop it in the way you are suggesting where we would have a basic parent class that would offer states, events, and maybe first/back/next/last buttons from which we could subclass a numerical button panel pager, a glyphic pager, and ComboBox pager. This will allow developers to leverage the states and events class while still having the option for a free range of customization with the core pager control.
This is exactly why I included imports/exports into our new control proposal issue. I recognize that very few controls we build are a single control, and that most are composed of several others which may or may not have yet been created.
Agreed. Thanks again, @micahgodbolt! I have updated our Requirements section to reflect this componentization as a core priority for the control.
The DisplayMode property could be used to enable a simple step based representation, as used by Windows and XBox OOBE sequences - and could be useful for onboarding scenarios for app developers.
You could even allow it to be template-able, but as a default appearance, something like this would fit with UWP patterns.
There could be properties to hide or show the labels, or it could be part of the template.
@mdtauk Exactly, under the current proposal, your scenario is one that would be enabled by a base parent class designed to handle states and events.
As for including a sequence based display as you have suggested, I have added this to the Open Questions section to collect feedback on whether this would be a popular out-of-the-box addition for developers.
:) @SavoySchuler That primitive control could also be used by a Form control that has been proposed, as well as for any future "Wizard" control
@mdtauk Nice catch! The proposed Form control paired with a step based pager would make for a fantastically smooth experience creating those scenarios.
Thank you again for your feedback, everyone! In response to some earlier comments and to better support more traditional scenarios where this control can be used, I have posted a separate proposal for adding a data paging component to PagerControl. This addition would make PagerControl functionally comparable to Silverlight's DataPager with an improved user experience via dynamic resizing and state tracking.
These proposals are distinct because I believe a flexible UI paging widget can valuable in its own right - which I believe is supported by the similar developments of the Fabric team/@micahgodbolt. This means if the data paging add-on is something you would like to see for this control, please go comment or thumbs-up here!
So a Pagination control, which includes ProgressSteps, and Pager controls which would be shared by a DataPager control, which could be an extended DataGrid control?
Hi, @mdtauk! You're right, this is getting a little messy. Here's a breakdown of everything proposed here and in Proposal #268 with each class' unique features listed as sub-bullets.
Base class:
Sub classes:
Sister class to PagerControl:
@mdtauk, I looked into the ProgressSteps scenario (commonly called "First Run Experience" or FRE) more and I am wondering if you think the Pivot Control paired with the PagerControl base class would adequately solve the FRE scenario for you? Pivot can have its tabs programmatically enabled/disabled and the navigation events between Pivot and PagerControl could be synced. Is there anything Pivot is missing that you would need?
In the Windows and Xbox OOBEs that use that type of paging/progress - there is no swiping to go back and forth, instead they have a back button and a Next command button.
I think it may need to be an inactive control to show the progress, but also to keep track of the inputs entered in previous steps, so you can go back and change your inputs.
I see it more as a basic readout of the "pages" in a linear fashion, so moving forward through pages, equals progressing through steps.
Related to this UserVoice item as well.
@mdtauk and @michael-hawker, I met with my team today and we scoped this development down to focus on the core pager scenarios which are now shown in the summary.
@mdtauk, would you please open a new proposal for the ProgressSteps/FRE scenario you brought up? I am happy to do it, but I would prefer we capture this scenario fully in your own words. Plus, this way ensures you get due credit! I am happy to fill out any remaining details.
All, I have opened a new proposal for glyphic index displays associated with FlipView. Please thumbs up this proposal separately if you are interested in seeing this feature added to FlipView.
Please feel encouraged to continue high-level discussion here on the proposal. More detailed discussion will occur on the Spec and the associated PR once it is available.
Will there be support for pages of content without data binding?
Something like:
<PagerControl>
<PagerControl.Page>
<TextBlock Text="Section 1" />
<Button Content="Next" />
</PagerControl.Page>
<PagerControl.Page>
<TextBlock Text="Section 2" />
<Button Content="Cancel" />
<Button Content="Confirm" Style="{ThemeResource AccentButton}" />
</PagerControl.Page>
</PagerControl>
It would be useful for Custom Controls like signup or login forms, which could be used throughout an app
Will there be support for pages of content without data binding?
This is a must (I have heard the same ask from internal customers) and I have updated the Requirements list to reflect this. My current understanding is that the API can (mostly) look the same as it will in solutions that leverage data binding, the distinguishing work will need to be handled in the navigation events that would require some special casing to handle navigation calls to content that may or may not exist + possible logic to update the UI if a determinate page count is established.
@mdtauk @SavoySchuler correct me if I'm wrong, but the PagerControl isn't going to own the content it's paging through, correct? I think hosting content is out-of-scope for the purpose of the PagerControl? In Martin's case I'd see the PagerControl just managing a Frame or FlipView to swap between the content defined outside of the PagerControl.
I noticed in the spec there's a lot of commands for first/next/prev/last... it'd be cool if a control could implement an interface and hook itself in to the Pager somehow? (Thinking of TargetInkCanvas
type model from InkToolbar
.) The interface would provide details to the pager on the number of items/pages/current page and can be called upon to move to the page requested by the pager control on user interaction?
Then it'd be helpful for certain controls like FlipView
to implement this interface (in WinUI 3) so that these scenarios can just work together automatically for some of the standard UX experiences (like the context indicator called out as a sample currently here would become much easier).
<muxc:FlipView x:Name="itemFlipView" ItemsSource="{Binding Source={StaticResource itemsViewSource}}"/>
<muxc:PagerControl TargetControl="{Binding itemFlipView}"/>
Also, I didn't notice an Orientation
property called out, I would think that you could want a PagerControl
on the side as well as top/bottom?
Thinking of a case of having a side-by-side page preview but with the pager in the middle (or on the sides):
Also, I didn't notice an
Orientation
property called out, I would think that you could want aPagerControl
on the side as well as top/bottom?Thinking of a case of having a side-by-side page preview but with the pager in the middle (or on the sides):
This feels like a pretty different scenario to me... and I don't think the design takes this scenario into account.
The WinUI Team has opened a Spec for this feature.
Proposal: New UI Pagination Widget
Summary
This widget would provide a customizable pager UI, generic states, and generic events that can be configured to navigate pages for several view controls.
Rationale
The absence of a standard UI pager control, last seen as DataPager in Silverlight, has been a pain point in both WPF and UWP that has forced a variety of unfavorable workarounds for developers. Inclusion of this control in UWP would resolve an ecosystem gap and enable developers to efficiently deliver UI paging experiences in their applications. Through XAML Islands, it may also provide an opportunity to benefit WPF developers working with DataGrid or ListView. The scope of this proposal is not provide a data paging solution at this time but to start with UI paging as a foundation on top of which data paging may be later integrated.
Requirements
Important Notes
Here are how the three configurations could look:
ComboBox configuration
NumberBox configuration:
Button panel configuration:
Usage Examples
Using a button panel as the display mode.
Using an editable ComboBox as the display mode.
Visual Components
When set to be a button panel, the number of visible indices can be specified.
Automatically disabled when at last index.
* Can be set to not be visible when at the last index.
Automatically disabled when at first index.
* Can be set to not be visible when at the first index.
Automatically disabled when at last index.
* Can be set to not be visible when at the last index.
Automatically disabled when at first index.
* Can be set to not be visible when at the first index.
MaxBefore and MaxAfter properties can be used to set how many indices appear between the current page and the ellipsis before/after it.
Visibility of the first/last index can be disabled.
Only visible when using button panel as the display mode.
Accessibility
Will go through all actionable items in order without regard to groups.
Arrow keys:
Will be able to explore groups in the specified directions. Pressing the down arrow key at the bottom of the ComboBox will wrap the user to the top.
Escape:
Will escape UI pager.
Enter and Spacebar:
Will select the component focused on.
Home:
Will move focus to "go back" elements. In the ComboBox, it will jump the user to the first index.
End:
Will move focus to "go forward" elements. In the ComboBox, it will jump the user to the last index.
“first page button”
“previous page button”
“1st page”
“current page”
"page selection drop down menu: current page is 1”
API Surface Example
Related
Proposal: Data Paging for PagerControl #268