Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a11y solutions? #19

Closed
kentcdodds opened this issue Jul 5, 2017 · 23 comments
Closed

a11y solutions? #19

kentcdodds opened this issue Jul 5, 2017 · 23 comments

Comments

@kentcdodds
Copy link

I'd like to brainstorm ideas for how to support accessibility better by having a straightforward mechanism for keyboard-only users to be able to tab out of the react-live input somehow. I'm not sure whether there's an accepted/established way to do this....

Here's an example of the experience for a keyboard only user:

tabs

@kentcdodds
Copy link
Author

@hankchizljaw had an idea to bind the escape key to tab out of the input field to the next thing. Thoughts? I think it's pretty good 👍

@Andy-set-studio
Copy link

I think the escape key is the natural choice for a keyboard only user to remove focus / exit out of the current situation they find themselves in.

It'll be good to see feedback from an actual keyboard only user to support or reject this thought though.

@kentcdodds
Copy link
Author

@thejameskyle also had a great idea:

Tab focus through page reaches editor, "return" enters the editor, "exit" escapes the editor and puts it in focus

I like that because it makes the editor less of an interuption and more of an intended action on the part of the user.

Clicking directly into the editor with the mouse would naturally still focus in the editor. But with this proposal, you couldn't actually tab into it.

If you all are on board, I'm sure that I or someone else would love to work on this :)

@kitten
Copy link
Contributor

kitten commented Jul 5, 2017

This sounds like a great addition 👍

@kentcdodds
Copy link
Author

Then @ryanflorence comes in with this useful tip. Thanks Ryan! This will probably be helpful:

import findTabbable from './tabbable';

export default function scopeTab(node, event) {
  const tabbable = findTabbable(node);
  if (!tabbable.length) {
    event.preventDefault();
    return;
  }
  const finalTabbable = tabbable[event.shiftKey ? 0 : tabbable.length - 1];
  const leavingFinalTabbable = (
    finalTabbable === document.activeElement ||
      // handle immediate shift+tab after opening with mouse
      node === document.activeElement
  );
  if (!leavingFinalTabbable) return;
  event.preventDefault();
  const target = tabbable[event.shiftKey ? tabbable.length - 1 : 0];
  target.focus();
}

@kentcdodds
Copy link
Author

Also this tip from @claudiopro referencing this for the benefit of keyboard and screen reader users. Thanks!

@kitten
Copy link
Contributor

kitten commented Jul 5, 2017

So to sum up the desired behaviour:

  • Press Tab (n times)
  • Editor gains focus (should be easily detectable with onFocus of course)
  • Press Enter, (or immediately press Tab again, see below)
  • Now you're able to type freely
  • Press Esc
  • Press Tab
  • Editer loses focus and next focusable element is focused (tabindex should stay optional, but must be respected! Is there a browser API that can be used for this?)

I'm not to keen on implementing this, since I'm a bit busy, but I'll tag this issue

Edit: Duh! ok, we can probably just stop preventing the default behaviour for tabbing to the next focusable element ;)

@kentcdodds
Copy link
Author

kentcdodds commented Jul 5, 2017

I'm also quite busy, not sure when I can get to this. I'll comment here if I'm able to start. In the meantime, I'm fine with anyone else jumping in!

@dfosco
Copy link

dfosco commented Jul 5, 2017

Perhaps it would also be good to have a screen-readable description stating that you've entered a text editor area within the page?

I'm not sure there's enough context as is for blind and low-sighted users.

@kitten
Copy link
Contributor

kitten commented Jul 5, 2017

@dfosco That's true. We need to check what using it feels like on a screen reader. However, I'm pretty sure that it's going to be a terrible experience no matter what we do 😢 As soon as you move around as a blind person in a code editor, it's probably going to be hard to remember the context. Especially since a screen reader will do a terrible job at reading things out aloud.

But, we should look into this anyway, and try to find out what other editors are doing 😄

@Antonio-Laguna
Copy link

I'd add that this special behaviour gets informed with an aria-describedby selector for the textarea. Something in the line of:

<code-editor aria-describedby="code-description"></code>
<div id="code-description" class="sr-only">This is a code editor in which its showcased how Glamorous works. In order to exit press the escape key.</div>

@burge-is
Copy link

burge-is commented Jul 7, 2017

I made a little mockup of the proposed Enter/Escape behavior.

Please review so that I (or anyone interested) can move forward polishing it with an aria alert and such. My thinking is that it'll wrap something that captures input and it will leave that mess to whomever gains control after the "Enter" press (with the exception of the escape key which is captured). This approach leaves your existing code alone, minus the need to wrap your editor component with this new one.

Click below to check it out:
Edit Enterable/Escape Gated Component

@kentcdodds
Copy link
Author

Looks pretty good, though, could you put it in a textarea? Wanna make sure that hitting the tab key will be kept inside the textarea until you hit escape.

@kitten
Copy link
Contributor

kitten commented Jul 8, 2017

@burge-is @kentcdodds this is looking like roughly the right behaviour. The problem is that it's using a wrapper to guard the wrapped inputs. And it programmatically finds the next focusable target.

I'm sure that we can solve it with less code and operations by capturing/blocking the tab key's default behaviour inside the LiveEditor component, depending on whether Enter/Esc have been pressed.

@burge-is
Copy link

burge-is commented Jul 9, 2017

I'll toy with a more minimalist addition directly to the LiveEditor.

For the next target, there is a prop that allows you to specify the id you'd like to focus. The programmatic search for the next focusable child was for backup but proptypes could be used to make it a mandatory inclusion and that code could be cut.

@kentcdodds
Copy link
Author

there is a prop that allows you to specify the id you'd like to focus

Sure would be nice if it just focused on the next focusable element....

The programmatic search for the next focusable child was for backup but proptypes could be used to make it a mandatory inclusion and that code could be cut.

Could you clarify your meaning? I'm confused by this.

@burge-is
Copy link

burge-is commented Jul 9, 2017

@kentcdodds haha I confused myself writing it.

It was in response to @philpl mentioning the programmatic search for next focusable item. Currently my code looks for a prop of idToFocus and if that is not found it searches its children and aborts when it finds a tabIndex >=0 and lastly if this doesnt provide anything it uses itself as the element that will gain focus. I hope that clears it up some.

this.focusTarget = document.getElementById(this.props.idToFocus) || findFirstFocusableChild(this.ref) || this.ref;

there was a mention of using less code so I suggested the second condition of the or could be removed and the idToFocus could be a mandatory prop.

As currently coded the intent is to allow for faster more specific control if demanded, but gracefully solving the issue of where to go if not given an explicit id.

@kentcdodds
Copy link
Author

That sounds great. For me, I pretty much don't want to ever have to pass an idToFocus. I just want it to focus on the <TabGate> thing again when I hit escape, so I can move on myself. 😄

@burge-is
Copy link

burge-is commented Jul 9, 2017

https://github.com/burge-is/react-live/tree/issue19-a11y
I introduced the code to the demo in a branch I've been working on. Please check it out and run the demo to see it's most recent implementation. I've been happy with the behavior in my limited testing of it.

Be warned there is slightly more code now, as I introduced an offscreen navigation tooltip when the TabGate is focused. You can change or delete the styling if you'd rather it be visible.

@kentcdodds
https://github.com/burge-is/react-live/blob/issue19-a11y/demo/components/LiveEdit.js#L79
^ this is where I introduced the Component,

With your familiarity with the code I was thinking you'd know a better home for it, if you wanted it included on all Editor components by default. I kept running into styling issues when I tried to force it into the editor code, due to my introduction of a div wrapper. Rather then bang my head on the existing css or change existing code I wanted to see if you knew a better place to introduce it, or if you were fine using it as implemented in this new demo code.

@kitten
Copy link
Contributor

kitten commented Jul 9, 2017

@burge-is would you like to just open a PR? Then Kent and I can leave our thoughts and feedback there :)

@burge-is
Copy link

burge-is commented Jul 9, 2017

@philpl sounds like the better approach, I'll go ahead and do that.

@kentcdodds
Copy link
Author

We did a workaround on the glamorous website and I think that it's unlikely we'll worry about updating anything at this point, so I'm going to go ahead and close this issue because I don't need it anymore. Feel free to merge it though because I think it's a great idea :)

@josgraha
Copy link

josgraha commented Jul 3, 2018

FWIW there is already a spec for this called WCAG 2.x
https://www.w3.org/TR/2008/REC-WCAG20-20081211/#keyboard-operation-keyboard-operable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants