Skip to content

Conversation

@devongovett
Copy link
Member

@devongovett devongovett commented Sep 21, 2021

Closes #1638. Closes #1905. Closes #2013. Closes #2018. Relates to: #2266. Relates to: #789.

This implements two features across all collection components (currently TableView and ListView):

  • Highlight selection – this allows checkboxes to be hidden, and a highlight style to be applied to the row to indicate selection instead. It also changes the selection behavior, so that clicking an item replaces the entire selection with that item rather than toggling it. Multiple items can be selected using modifier keys like Ctrl/Cmd and Shift. On touch, highlight selection behaves like toggle because there are no modifiers available. This can be enabled using the selectionBehavior="replace" prop (TBD).
  • onAction – this prop allows a separate action to be defined for rows in addition to selection. For mouse, this is double click. For keyboard, it's the Enter key. On touch, the action becomes the primary tap interaction, and a long press enters into selection mode. Deselecting all items exits selection mode. The useLongPress hook has been added to @react-aria/interactions to implement this.

This also required moving the usePress call into useSelectableItem rather than calling it from each usage site, so there are many changes related to that.

To do:

  • Talk to a11y about iOS Safari not announcing aria-describedby on grid rows/cells. Possible put the long press description on the grid instead.
  • Determine if we want both onRowAction and onCellAction for tables. Answer: keep onAction on row, add onCellAction later if needed.
  • Decide on API for enabling highlight selection in Spectrum (e.g. selectionStyle="highlight" vs selectionBehavior="replace"`). Answer: update to use selectionStyle.

snowystinger and others added 27 commits June 11, 2021 15:12
add demo stories
fix clicking without shift
* Mobile updates for selection

* Move mobile awareness to the component

* fix lint

* move to touch/vo detection
* Select on focus first time in collection

* fix lint

* Only start selecting on first focus if selectOnFocus is on

* add a test

* fix aria

* fix lint

* remove dead code

* fix lint
…/react-spectrum-v3 into highlight-selection

# Conflicts:
#	packages/@react-spectrum/table/stories/Table.stories.tsx
@adobe-bot
Copy link

Build successful! 🎉

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

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

Menus also look weird after the merge with main:
image

Comment on lines +191 to +196
onLongPress(e) {
if (e.pointerType === 'touch') {
onSelect(e);
manager.setSelectionBehavior('toggle');
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Say there is the following scenario:

  1. The user long presses on a ListView in mobile and selects a couple row to perform some bulk action.
  2. The user then presses some button outside of the ListView to execute said bulk action.

How is the user supposed to exit from the "toggle" selection behavior? I know that you mentioned deselecting all the rows will flip it back to the original "replace" behavior, perhaps we should provide a "select all" checkbox like TableView has if selectionMode is "multiple".
Hmm, perhaps the external bulk action action would set selected keys to an empty array, aka handled by the application

Copy link
Member

Choose a reason for hiding this comment

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

Also, should this have an accessibilityDescription added here?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah setting the selectedKeys back to empty should clear it. As for accessibilityDescription, that's one of my questions in the pr description. Unfortunately, VoiceOver doesn't read aria-describedby on a gridcell...

// Pressing the Enter key with selectionBehavior = 'replace' performs an action (i.e. navigation).
let onKeyDown = hasSecondaryAction ? (e: KeyboardEvent) => {
if (e.key === 'Enter') {
onAction();
Copy link
Member

Choose a reason for hiding this comment

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

Should onAction be fired if the user pressed option + Enter? I figured that would toggle selection only

Copy link
Member Author

Choose a reason for hiding this comment

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

Hmm, where did you get that assumption?

Copy link
Member

Choose a reason for hiding this comment

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

Well, it just felt a bit inconsistent that other interaction modes have onAction and selection as separate actions (e.g. w/ mouse, you double click to trigger onAction in highlight selection mode and change selection with single click. onAction doesn't fire on single click here).

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

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

Still haven't tested tableview on mobile, preliminary review

Comment on lines +191 to +193
onLongPress(e) {
if (e.pointerType === 'touch') {
onSelect(e);
Copy link
Member

Choose a reason for hiding this comment

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

In the "selectionStyle: highlight, onAction" ListView story:
using talkback on android, I'm able to toggle selection on a ListView item via double tapping it a couple of times. This triggers onAction a couple of times (which is expected) and then the item gets the selected styles. If you then perform a long press via tap + tap and hold on a different item, you'll be able to see that the previous item is indeed selected.

For highlight selection + onAction, selection of a list item shouldn't be possible without entering the selection mode view via long press right?

Copy link
Member

Choose a reason for hiding this comment

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

This seems to happen in the TableView "selectionStyle: highlight, onAction" story as well

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds like a great bug to follow up on. 😉

Copy link
Member

Choose a reason for hiding this comment

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

😄 I'll make a note

Comment on lines +162 to +164
&.spectrum-Table-row--highlightSelection {
border-bottom-color: var(--spectrum-global-color-blue-500);
}
Copy link
Member

Choose a reason for hiding this comment

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

Noticed that the top border is missing when the top most row is selected:
image

TBH, do we really want this border color when it is selected? It kinda looks strange IMO with the focus ring also applying a border:
image

Copy link
Member Author

Choose a reason for hiding this comment

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

First one will be interesting because it's the border of the whole table, not of the row... Second one is spectrum question

.add(
'selectionStyle: highlight',
() => (
<TableView aria-label="TableView with dynamic contents" selectionMode="multiple" selectionStyle="highlight" width={500} height={400} onSelectionChange={s => onSelectionChange([...s])}>
Copy link
Member

Choose a reason for hiding this comment

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

Should onSelectionChange be firing with the same selection when navigating within the currently selected row (e.g. focusing the cells via keyboard) or hitting space a bunch of times? Kinda like how Tabs work I guess so this might be fine

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah it's weird. I tried to get rid of this behavior but it seems a bunch of components rely on it... :/

Comment on lines +284 to +286
'selectionStyle: highlight',
() => (
<TableView aria-label="TableView with dynamic contents" selectionMode="multiple" selectionStyle="highlight" width={500} height={400} onSelectionChange={s => onSelectionChange([...s])}>
Copy link
Member

Choose a reason for hiding this comment

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

In the "selectionStyle: highlight" TableView story, multiple row selection via Talkback only works if you double tap when focusing a cell. If the entire row is focused and you double tap to select it, it actually unselects all previously selected rows and only selects the current row.

Comment on lines +191 to +193
onLongPress(e) {
if (e.pointerType === 'touch') {
onSelect(e);
Copy link
Member

Choose a reason for hiding this comment

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

This seems to happen in the TableView "selectionStyle: highlight, onAction" story as well

Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

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

Tested TableView stories on Android, found 1 extra thing

let {elementType: ElementType = 'div', onPress, onPressStart, onPressEnd, ...otherProps} = props;
let {longPressProps} = useLongPress(otherProps);
let {pressProps} = usePress({onPress, onPressStart, onPressEnd});
return <ElementType {...mergeProps(longPressProps, pressProps)} tabIndex="0">test</ElementType>;
Copy link
Member

Choose a reason for hiding this comment

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

Order matters here, if longPress is first in the merge, then longPress events will happen first, but if press is first, then press events will happen first
This could be troublesome if we're not careful with it everywhere and consistent, maybe we should have a hook that combines them in the right order? I can't think of a great solution off the top of my head

Copy link
Member Author

Choose a reason for hiding this comment

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

You mean onPressStart and onLongPressStart? Where would you expect this to be problematic?

Copy link
Member

Choose a reason for hiding this comment

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

Just trying to think if others combine it on other components, it might be different component to component

<ComponentA onPressStart={onPressStart} onLongPressStart={onLongPressStart} />
vs
<ComponentB onPressStart={onPressStart} onLongPressStart={onLongPressStart} />
might yield
onPressStart then onLongPressStart for ComponentA
but onLongPressStart then onPressStart for ComponentB

@adobe-bot
Copy link

Build successful! 🎉

@matthewdeutsch matthewdeutsch changed the title Add support for highlight selection and onAction to TableView and ListView #2353 Oct 15, 2021
@devongovett devongovett changed the title #2353 Add support for highlight selection and onAction to TableView and ListView Oct 15, 2021
LFDanLu
LFDanLu previously approved these changes Oct 15, 2021
Copy link
Member

@LFDanLu LFDanLu left a comment

Choose a reason for hiding this comment

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

Approving, other comments to be handled in followup

@adobe-bot
Copy link

Build successful! 🎉

@adobe-bot
Copy link

Build successful! 🎉

@dannify
Copy link
Member

dannify commented Oct 15, 2021

Some follow up tickets will be added for this.

Copy link
Member

@snowystinger snowystinger left a comment

Choose a reason for hiding this comment

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

yep, looks good to me

@dannify dannify merged commit 885b5e6 into main Oct 15, 2021
@dannify dannify deleted the highlight-selection branch October 15, 2021 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

7 participants