A more inviting playlist picker

I have been using the Angular Material mat-menu for playlist selection. It’s Material Design’s version of a drop-down select, a classic original GUI prompt concept. There was a problem with long picklists on iPad, maybe due to the modification I did to make the picklist larger – for less scrolling. Also, I wanted a more modern and obvious UI. The user pretty much cannot do anything until picking a playlist. So let’s make picking the playlist a bigger deal up front.

I decided to get rid of the mat-menu and present each playlist as a clickable card. I knew this would be more work, and it was, but it was worth it.

Tabbing

Mat-menu supports the tab key. Once the drop-down appears, the tab key works to move through items. I want the same thing for my cards. So I added tabindex=0 to each card.

A tab key user likely will use the keyboard then to select – either the enter key or the space bar. With tabindex=0 the user can tab to a card, but then neither the enter key nor the space bar work for select. No key does. I solved this by binding to the keyup event, and making my function accept an optional parameter that gives me the keystroke. These lines of code are on each card:

style="margin:10px;cursor:pointer"
tabindex=0
(click)="onSelectPlaylist(PI)"
(keyup)="onSelectPlaylist(PI,$event.key)"

Then, in my function:

onSelectPlaylist(I: number, key?: string): void {
  if (key && !key.match(/^( |Enter)$/)) {return}
  ...

Space bar really does send a single byte blank character through $event.key. The enter key, however, sends the string “Enter”. So my regular expression for space or enter is

/^( |Enter)$/

If the user triggers the function with any key other than space or enter, the function instantly returns, doing nothing.

Toggling

Just as with a classic drop-down select list, we want the cards to disappear when the user makes a selection, and of course reappear if the user wants to make a different selection. I spent a lot of time on this, trying many different user interface ideas. Here are a few things I learned along the way.

Avoid using *ngIf to toggle the existence of Angular Material’s paginator.

I advise this because if the user changes the items-per-page setting, it is lost when *ngIf removes the paginator from the DOM. This may not be a big deal at the time of removal, but be careful if the paginator might be subsequently restored.

Be sure hidden content is not tab selectable

I was using flex size zero to hide sections (eg. fxFlex=”0 1 0″ for the hidden state). I was horrified, however, when eventually I discovered that the user can still tab though, and trigger selection in, this hidden content. It’s much better to show/hide using [fxShow]. If you are unfamiliar with this syntax, it is from the nice flex-layout module that I am using.

Angular 6 Shufflizer

Shufflizer has been updated. There are no new features.

This version of Shufflizer was created with Angular 6. Some obsolete sections of code have been removed. All layouts have been changed from old style html tables to Angular flex-layout (previously it was a mish-mash of these two approaches).

Known issue

Playlist selection does not work on Safari/iPad when the user has enough playlists that the dropdown picklist needs to scroll. This seems to me to be an Angular Material bug. I am considering a more luxury playlist selection interface, and am motivated to make it a priority since it would address this known issue.