Skip to content

Conversation

@JustAboutJeff
Copy link
Contributor

@JustAboutJeff JustAboutJeff commented Aug 4, 2018

allow default TableRow keypress event behavior (#211)

Thanks for creating evergreen! 🌲

tl;dr remove the e.preventDefault() function call so that input and change events can be fired normally after the keypress event .

if (this.props.isSelectable) {
if (e.key === 'Enter' || e.key === ' ') {
this.props.onSelect()
e.preventDefault()
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice! Should we find another way to allow consumers to opt-in to preventing scroll of the page upon these key presses?

Copy link
Contributor Author

@JustAboutJeff JustAboutJeff Aug 6, 2018

Choose a reason for hiding this comment

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

@mshwery Thanks for the feedback and additional context on the original implementation here. Appreciate it!

As an alternative to additional configuration for opt-in behavior, it occurred to me that we could instead continue to invoke preventDefault but first wrap the function call within a conditional that would check if the event target is in fact the TableRow itself.

This way, if consumers of 🌲 decide to nest additional UI that can take focus or accept user input within an isSelectable TableRow, the browser can and will scroll and direct focus to these child UI elements when the event originates there. This is good, and helps with web accessibility standards. This is the scenario captured from the original issue report here.

Alternatively, for an isSelectable TableRow that contains text or other children that do not provide a target to fire a keyPress event, preventDefault will be called and browser scrolling will not occur when selecting a row. This scenario is captured in the existing storybook example here

>
{children}
</Pane>
<div ref={this.handleRef}>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm using a wrapping div here so that we can attach a ref to the underlying node and avoid a call to findDOMNode which is discouraged for React 16 onward.

Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why we would need to do to this? If you need the ref of the Pane you can use innerRef={ref => this.paneRef = ref}. Eslint will probably complain, so you might have to create a func to do it innerRef={this.onRef}

Copy link
Contributor Author

@JustAboutJeff JustAboutJeff Aug 9, 2018

Choose a reason for hiding this comment

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

Thanks @jeroenransijn. I took this approach because using a wrapping div was seemingly the easiest way preserve encapsulation. However, as you pointed out, Pane (via ui-box) has already been wired up to expose a ref prop that we can use. I wasn't aware of this, and that approach would work just fine as well.

For reference:
https://github.com/segmentio/ui-box/blob/master/src/box.js#L50-L54

I'll amend my commit to use this approach, and include a new storybook example that will make it easier to verify the bug has been fixed.

// NOTE: In scenarios where the target for key press is our
// tabIndex <Pane> below, prevent the default event action
// so that browser scroll will not occur.
if (e.target.parentNode === this.node) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because of the wrapping div below, we compare the event target's parent node to our ref node here. If they match, the event was fired while keyboard focus was on the tabIndex <Pane> below and we should stop browser scroll by preventing the default event action.

If the event target was some other node, then the user has interacted with other types of nested UI, and we should not prevent the default action so that input and change events can fire normally

Copy link
Contributor

@jeroenransijn jeroenransijn left a comment

Choose a reason for hiding this comment

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

I will have to take a bit more of a look at this, and potentially add this to a v4 branch to see if the expected behavior is good. Hopefully next week!

>
{children}
</Pane>
<div ref={this.handleRef}>
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why we would need to do to this? If you need the ref of the Pane you can use innerRef={ref => this.paneRef = ref}. Eslint will probably complain, so you might have to create a func to do it innerRef={this.onRef}

Copy link
Contributor

@mshwery mshwery left a comment

Choose a reason for hiding this comment

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

Awesome! Nice update. LGTM 🚢

@jeroenransijn jeroenransijn merged commit 4563c27 into segmentio:master Aug 13, 2018
@jeroenransijn
Copy link
Contributor

jeroenransijn commented Aug 13, 2018

Thanks for the work @JustAboutJeff ! Highly appreciated! Will take a look soon to move this in v4 as well. 🌲 💯 🎉

evergreen-ui 3.2.6 published 🎉

Rowno added a commit that referenced this pull request Sep 24, 2018
* master: (25 commits)
  Remove storybook-deployer
  v3.2.7
  Fix typo in Tooltip proptypes (#321)
  fix githubLink pathname on ComponentReadme (#310)
  Use `rm -rf` in prepublishOnly
  Run the babel builds concurrently
  circleci: fix the gh-pages ignore config
  circleci: fix the gh-pages ignore
  Migrate to circleci 2.0
  Adding a link to Synapse
  Fix wording in Toaster docs (#294)
  v3.2.6
  allow default TableRow keypress events (#221) (#276)
  Fix misspelling of ListItem component name (#268)
  🌲 CI status image (#263)
  Add link to v4 docs and PR
  Add more spacing
  Add Hero image
  Add GitHub hero
  Add note to v4
  ...

# Conflicts:
#	README.md
#	docs/src/components/ComponentReadme.js
#	package.json
#	src/segmented-control/src/SegmentedControl.js
#	src/segmented-control/src/SegmentedControlRadio.js
#	src/segmented-control/src/styles/SegmentedControlAppearances.js
#	src/select-menu/src/OptionsList.js
#	src/select-menu/src/SelectMenuContent.js
#	src/table/src/TableRow.js
#	src/table/stories/index.stories.js
#	src/toaster/docs/index.js
#	yarn.lock
Rowno added a commit that referenced this pull request Sep 25, 2018
* v4: (30 commits)
  Tracking fix (#338)
  add segment tracking (#337)
  Upgrade dependencies v4 (#336)
  V4  Docs (#335)
  Remove storybook-deployer
  Remove storybook-deployer
  v3.2.7
  Fix typo in Tooltip proptypes (#321)
  fix githubLink pathname on ComponentReadme (#310)
  Use `rm -rf` in prepublishOnly
  Run the babel builds concurrently
  circleci: fix the gh-pages ignore config
  circleci: fix the gh-pages ignore
  Migrate to circleci 2.0
  Adding a link to Synapse
  Fix wording in Toaster docs (#294)
  v3.2.6
  allow default TableRow keypress events (#221) (#276)
  Fix misspelling of ListItem component name (#268)
  🌲 CI status image (#263)
  ...

# Conflicts:
#	package.json
prateekgoel pushed a commit to prateekgoel/evergreen that referenced this pull request Oct 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants