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

How to focus on primary button when modal loads? #51

Closed
kevhou opened this issue Jun 29, 2015 · 21 comments
Closed

How to focus on primary button when modal loads? #51

kevhou opened this issue Jun 29, 2015 · 21 comments

Comments

@kevhou
Copy link

kevhou commented Jun 29, 2015

I can't seem to use jquery .focus() inside componentdidmount.

Someone please help!

@olegshilov
Copy link

@kevhou try using Refs

@arasmussen
Copy link
Contributor

I'm having a similar problem with not being able to .focus something inside componentDidMount. I'm using refs.

var VIEWER_REF = 'VIEWER';
var PhotoViewer = React.createClass({
  componentDidMount: function() {
    this.refs[VIEWER_REF].getDOMNode().focus();
  },
  render: function() {
    return (
      <div tabIndex="0" ref={VIEWER_REF}>
        {contents}
      </div>
    );
  },
});

I've verified that this.refs[VIEWER_REF].getDOMNode().focus() is defined and being called. It worked before I put my PhotoViewer inside react-modal.

@arasmussen
Copy link
Contributor

Also worth noting that document.activeElement (currently focused element) after my PhotoViewer opens is the ReactModal__Content element, so it seems like it's stealing focus from me. Why does the modal need focus?

@arasmussen
Copy link
Contributor

Can we get a prop (default true) so that we can disable this functionality? I don't see why the Modal needs focus. I'm happy to manually pipe through ESC to changing isOpen to false.

@arasmussen
Copy link
Contributor

Also sorry for the quadruple post, but a temporary workaround is the following:

componentDidMount: function() {
  setTimeout(function() {
    this.refs[MY_REF].getDOMNode().focus();
  }.bind(this), 0);
},

@brandly
Copy link

brandly commented Jul 30, 2015

In case anyone else comes across this, as of v0.13, getDOMNode() is deprecated. The above example would be changed to this:

componentDidMount: function() {
  setTimeout(function() {
    React.findDOMNode(this.refs[MY_REF]).focus();
  }.bind(this), 0);
},

@brandly
Copy link

brandly commented Sep 10, 2015

if you want to focus on an input, you should just be able to put autoFocus on it, unless you need more control over it

@tazsoulis
Copy link

i have the same problem http://prntscr.com/8f6cve

@brandly
Copy link

brandly commented Sep 14, 2015

i think you just put <input autoFocus />. source

@tomhirschfeld
Copy link

I'm also having the issue where the react-modal becomes the active element upon opening and I need a way to prevent this from happening. Using doesn't work correctly. What happens is, the focus is set on the input initially, but then set on the modal within <100 ms after mounting.

@SebT
Copy link

SebT commented Oct 2, 2015

autoFocus doesn't work because it focuses the input when the modal is mounted.

We need to focus the input every time the modal opens instead:

componentDidUpdate: function(prevProps, prevState) {
  if (prevState.yourVar !== this.state.yourVar && this.state.yourVar === true) {
    setTimeout(function() {
      React.findDOMNode(this.refs.yourInput).focus();
    }.bind(this), 0);
  }
}

yourVar is the variable you give to the modal as isOpen.

This works perfectly fine for me.

@wader
Copy link

wader commented Dec 23, 2015

@SebT Thanks. Do you know why setTimeout is needed? if i log in a ref callback i see that componentDidUpdate is called before the ref callback... is that how it is suppose to work?

@ryanflorence
Copy link
Contributor

Let's say you are a screen reader user, when the modal opens, and you folks go and focus the primary button, how does the user know what the content of the modal says? They don't. They also don't know if they should move the virtual cursor up or down to find out.

I can't remember why it's in a setTimeout, but I guess it's nice that it keeps you from confusing blind folks :P

If there's a good accessibility argument here, I'll reopen, but as far as I can tell we are doing the most accessible thing, which is the primary goal of this component.

@vvlevykin
Copy link

@ryanflorence can you please point to a guide that says this?

This article contradicts what you said: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_dialog_role#Focus_management

@kpdecker
Copy link

@ryanflorence It seems to me that @vvlevykin has a compelling a11y argument for at least allowing this behavior to be conditionally controlled. For use cases where we do need to have this behavior, i.e. a properly labeled and annotated form, we have to either have a focus+blur+focus cycle that causes validation issues under redux-forms, or we have to play the game of using setTimeout to avoid a race condition with this code and hoping that it works in all situations.

@gertig
Copy link

gertig commented Mar 24, 2016

Thanks @SebT for the hack around the setTimeout!

@ryanflorence can you explain why forcing the content to be focused is preferred over allowing autoFocus to work on inputs?

@bl-nero
Copy link

bl-nero commented Apr 20, 2016

This bites me heavily on iOS/Safari. The Safari developers decided to be smarter than everyone, and decided that you can't focus() an input anytime else than when consuming a click event. This means that the setTimeout() hack won't work there. :(

@bl-nero
Copy link

bl-nero commented Apr 20, 2016

@ryanflorence Would you consider reopening this bug because of what I wrote above?

@bl-nero
Copy link

bl-nero commented Jun 8, 2016

@ryanflorence Ping. This is still a problem, and I still haven't found a compelling solution (other than not using react-modal in the first place).

@fritz-c
Copy link
Contributor

fritz-c commented Jul 21, 2016

componentDidMount/componentDidUpdate weren't working for me, but then I used the onAfterOpen prop as described in this PR's code (using the ref callback rather than the deprecated string notation they used), and I was able to focus on a text input.

@dspnorman
Copy link

This appears to be fixed in #222

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

No branches or pull requests