dhis2 / ui-core

:no_entry: [DEPRECATED] Please refer to https://github.com/dhis2/ui
BSD 3-Clause "New" or "Revised" License
8 stars 1 forks source link

Select component - first draft feedback #406

Closed cooper-joe closed 4 years ago

cooper-joe commented 4 years ago

It was decided here that we would abandon a native select element in favor of building our own select, compatible with multiple selections and filtering.

I've made a first draft of the design of this component. I would like to run it past you @dhis2/team-apps so that any required changes can be made before I write the usage docs/build specs.

ui-core select

In it's simplest form, a select is basically an input that opens a menu. There are more advanced features, but the composition of the component is based on this idea. Let me run through the features shown in the initial design. Multiple features could be included on one select, so you could have a 'Filterable multiselect with progressive loading'.

Simple single select'

Replaces the native select element. Nothing too fancy here. Selecting an item closes the menu by default.

Filter

The filter is an input inside the menu that filters the available items, or returns matching items from a server (this depends on how items are fetched).

Multiple select

Items in the menu display checkboxes that indicate multiple selection is available. Selecting an item does not close the menu by default. Selected items are displayed as removeable chip atoms inside the main input. The input would need to grow in vertical height to accommodate many selections.

Custom menu items/state

A dev would be able to pass in whatever items they want for selection, it doesn't need to be the basic ui-core menu with a menuList. The example shows some rich content: icons and text. The selected state of menu items could also be customised. My thoughts right now are that the selected state of the input would not be able to be customised - an item will always need to pass a string to display in the input.

Empty state

The component would provide a default empty state along the lines of 'No items found'. This would be customisable, allowing for any content to be shown inside an empty menu.

Clearable non-required single select

One of the issues with native select's is their inability to deselect an item without the inclusion of a dummy blank item. Ideally we would include a smart control that allows the user to clear the selection. The design includes this 'Clear' control inside the main input. I assume this is not possible unless we were making a unique input component here (the standard input components we have do not have this control). If this is an issue it can be solved by including a 'clear' control outside of the input.

Initial load

Load state if 0 items are prefetched from the server. The menu opens and displays a loading message.

Progressive load

Load state if items are returned paginated from the server. Scrolling down would trigger the load of x more items. How much logic for this do we want to include in the component itself? I do see this being used in many select's across DHIS2, so it seems reasonable to include.

Inline label

This is useful for toolbars where there is no room for a label. The placeholder text is persisted and the selection is appended.


I'm going to get started on the usage docs, all feedback is appreciated. I am particularly interested in any features/functionality that we might want to exclude from this component. I think that all of the included features will be used enough in DHIS2 that they warrant inclusion in this component, but I'm interested to see if there are differing opinions.

ismay commented 4 years ago

I'll move my comment from the other issue here:

One thing that I'd prefer is if the multi select doesn't include extra features like filtering, loading from the backend, etc. Basically, to keep it in ui-core and close to a native multi-select, but with better ux. I'd personally prefer to reserve the additional features for a separate, more complicated component that goes in ui-widgets. Not sure if the others feel that way or not?

varl commented 4 years ago

The intent is that the atoms will be in ui-core at least, but where the composed molecules live depends. ui-widgets is a likely candidate for especially heavy components.

Most of this component could be composed using ui-core components already. :thinking:

Looks excellent, @cooper-joe!

cooper-joe commented 4 years ago

Thanks @varl!

The first draft design documentation is now available, PR here. The functionality is described in some more detail there. (Direct link to doc)

Mohammer5 commented 4 years ago

@cooper-joe looks pretty nice already!

I want to get back to my proposed of not displaying this in a dropdown but make the options always visible (with a max-height?).

The advantages are:

Neutral:

The disadvantages are:

varl commented 4 years ago

@Mohammer5 are you referring to dropping native select or do you mean a different proposal entirely?

If dropping native select / option elements: https://github.com/dhis2/notes/issues/58#issuecomment-527905050 and https://github.com/dhis2/notes/issues/58#issuecomment-528269849

Mohammer5 commented 4 years ago

different proposal entirely, not talking about native select. I'm for dropping them, especially if we go for what I've proposed because then keyboard input becomes less relevant

I was thinking about putting the options into the document flow

Mohammer5 commented 4 years ago

The only difference between multi select and single select would be:

  1. Displaying the selected option
  2. You can select multiple in the multiple one Other than that, they'd look the same
cooper-joe commented 4 years ago

@Mohammer5 Thanks for the feedback! I've been thinking about this concept of an 'always visible' select.

I think this is a potentially useful component, but I don't think it should replace the select described in the design docs.

select dropdowns are a staple UI control, and for good reason. They allow selection from a potentially huge list in a tiny space. This is very useful in data intensive and compact applications. Replacing this with an always visible version would negate the main advantage: the compact size. You did raise this yourself:

It'd take more height We could add a "collapse" button (same style as the clear button?) We could collapse initially, it'd take one click to open them, just like the dropdown version

I think collapsing/expanding the control would be a net negative to our current user experience. This would result in a UI jumping around and other areas collapsing/scrolling to accommodate the options list. If we did not auto-collapse the control on selection it would be up to the user to attempt to return the UI back to its original state. This is not an issue on forms or vertically ordered content, but could present major issues in 'static' applications like data-visualizer or pivot-tables.

Multiple selects that are displaying a "loading" state won't be overlapping each other

This is a good point. This is a weakness of dropdown menus. Ideally the data inside a dropdown should not be heavy to load, but we of course are working with non-ideal situations and connections. My initial thought is that we could mitigate this issue by allowing resizable menu cards. 🤔

You can see the available options while filling in other form inputs

True, but I'm not sure this is a worthy trade-off for negatives I outlined above. If the options are important to the rest of the form they should be displayed in a fixed area that is always present on screen.

Consistent style for both single- and multi-selection

The style of single- and multi- selection should not be too consistent, their difference in style implies their difference in functionality. When an experienced user selects an option in a multi-select and sees the 'chip' style, they are subtly reminded that they can make several selections.

It works both on desktop and mobile devices

Yes, there's no arguing that dropdown menus can be annoying on mobile devices. However, I do not think this is an issue we need to address yet. I agree that we should keep this in mind, however I think a 'mobile select' component would be potentially more suitable than trying to get a single solution to bridge the wide gap between 'desktop web application' and 'low model smartphone'.

Overall, I think the positives of the dropdown menu outweigh the negatives. I also think that the inclusion of the transfer component (WIP, fresh off the press today!) will help. This is a component more suited to complex selections where options need to always visible and manipulable.

ismay commented 4 years ago

By the way, I didn't yet comment on the design specs, they look good to me 👍. I'm wondering what api we'd have for it.

I think a 'mobile select' component would be potentially more suitable than trying to get a single solution to bridge the wide gap between 'desktop web application' and 'low model smartphone'.

I would like to have a component that adapts to the environment it's displayed in, if possible (just to increase our compatibility with mobile). I find the native select/multi-select on mobile very nice already. We could maybe just fall back to that on mobile for our simple single/multi select? What do you think @cooper-joe?

cooper-joe commented 4 years ago

I would like to have a component that adapts to the environment it's displayed in, if possible (just to increase our compatibility with mobile). I find the native select/multi-select on mobile very nice already. We could maybe just fall back to that on mobile for our simple single/multi select? What do you think @cooper-joe?

Yes, that could work for the simple single/multi select. We would of course have to forego the advanced filtering/custom list on mobile, but it is potentially a better tradeoff for. I think it would depend on the use case. There would be times you'd want to force the 'full' component to display on mobile, and other times you'd be fine with a native implementation. Is there some way we could allow for that?

ismay commented 4 years ago

I think it would depend on the use case. There would be times you'd want to force the 'full' component to display on mobile, and other times you'd be fine with a native implementation. Is there some way we could allow for that?

I think so. I think we could render the native select on mobile if it's just a simple select/multiselect. If we look at whether any of the props for filtering, fetching, etc. are used, we can then fall back to the native mobile selection only when none of those props are being used. That could be a way maybe.

HendrikThePendric commented 4 years ago

Reg. the filtering and multi-select: I think what we have now works and is a good solution. I just wanted to discuss an alternative, slightly more minimalistic solution. Currently, we have a few UI elements doing the same thing:

Here's a good example of what I mean

I really like this, because there are fewer elements a user has to think about. One area where this solution diverges from the current design is here:

Selecting an item does not close the menu by default.

I think, when going with a solution as in the link above, the menu always needs to close and input needs to be cleared after one item was selected.

Feel free to completely ignore this. Just thought that perhaps offering an alternative approach might spark some ideas....

Mohammer5 commented 4 years ago

Regardless of what the spec will define eventually, I think it'd be good to change the spec in a way that all smaller components are defined independently and the actual select component (with all the features described in the specs) is just a composition of all of them, so we could also use the smaller components if we wanted to / didn't need to use the whole functionality of the select. (@ismay brought that up the other day and I totally agree)

Some of them we already have, like chips, the input field, etc. But it's be good as well to just have the option list, and label, so we could build the whole functionality iteratively.

cooper-joe commented 4 years ago

@HendrikThePendric Thanks for the feedback. You make a valid point that we have UI elements that are providing the same functionality, but these are intentional decisions. Let me address the points:

We show the list with checkboxes + selected options in deletable chips. A user can deselect via both. We could consider getting rid of the checkboxes.

The inclusion of two methods of select/deselect is intentional. The checkboxes provide a mental cue right away of "you can select more than one of these options". This is widely understood and doesn't need to be translated to different languages. This removes the need for an actual explainer text, 'You can select several options in the list below...', for every multi-select. The deletable chips provide functionality to remove options without needing to open the menu and scroll around or filter. While these elements provide similar functionality, the intention behind that functionality is different and I believe warrants the inclusion of both.

We have an "input" with chips, in which a user could type as well. So we could consider removing the filter input.

I went back and forth on this one and ended up on including a filter input. When using the main input as a filter it was not clear to the user that this functionality exists, or what the consequences of it were. This would require placeholder text of "Type to filter options" which would override other, potentially useful, placeholder text.

When testing other examples of using the main input as a filter, it was ambiguous what happens to text typed into the field. What happens if I type "dog", but do not select an option and click away from the input? Some of the examples persisted the filter text inside the main input, giving the impression I'd created a new option for myself. This confusion could lead to users being unsure whether their text was a filter or a new option. The simplest way to avoid this potential confusion is to 'keep it simple', and include an obvious filtering control.

I think if we add some smart functionality, auto-focus the cursor in the filter input when opening a filterable select for example, then users will appreciate the clarity and any potential trade-offs around space/repeated elements will not be a problem.

Feel free to completely ignore this. Just thought that perhaps offering an alternative approach might spark some ideas....

I appreciate the feedback and suggestions of alternative solutions, this is really useful. Please continue in the future! Being the only designer means I don't necessarily get to bounce ideas around with others, so this is a good chance to do that, making sure each design decision is justified and making sure we're building the right thing.

HendrikThePendric commented 4 years ago

Thanks for explaining your decision process @cooper-joe, makes perfect sense 👍

cooper-joe commented 4 years ago

The build specs for this component are complete, there is a JIRA ticket with all of the details: https://jira.dhis2.org/browse/TECH-212

Thanks for all of the feedback. There will certainly be some questions underway, but I think we are ready to start work on this.

ismay commented 4 years ago

We discussed switching this component out for a native single- / multi- select on mobile. I think this could be the best method, but I'd like to test the desktop component on mobile first. So in the first iteration let's leave out the mobile adaptability and do some testing. I'm also concerned about loss of functionality: custom list types and filtering for example, so I'd like to see if we can get the full component usable on mobile before removing features.

That seems nice actually. Looking at the component I can imagine that at least visually it can adapt nicely to a smaller screen. 👍

varl commented 4 years ago

This depends on #427.

ismay commented 4 years ago

I think we can safely close this as the new (Multi/Single) Select has been released with 4.0.0