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

initial autofocus, e.g. in modal overlay #25

Closed
loopmode opened this issue Feb 2, 2016 · 10 comments
Closed

initial autofocus, e.g. in modal overlay #25

loopmode opened this issue Feb 2, 2016 · 10 comments

Comments

@loopmode
Copy link

loopmode commented Feb 2, 2016

Hi.
I need to use hotkeys inside a modal overlay.
After the overlay is rendered, currently, the user must click into the container element once to give it focus, after that the hotkeys work as expected.
However, what I need is to have the hotkeys ready right away after the modal has opened up, without further mouse interaction.

This is kinda what I have, and I also tried manually focussing an element inside HotKeys, but it doesn't work. How can this be achieved?

componentDidMount() {
    setTimeout(() => {
        this.refs.video.focus();
        //this.refs.dummyInput.focus();
        //neither way, works, timeout doesn't make a difference either
    }, 500);
}
render() {
    return (
        <div className='MediaPlayer'>
            <HotKeys keyMap={this.hotKeys} handlers={this}>
                <video ref='video' src={this.props.videoSrc}/>
                {/*<input type='hidden' ref='dummyInput' />*/}
            </HotKeys>
        </div>
    );
}

I guess i could make it work by using HotKeys further up the component tree, but I guess I would have to define some part of the logic outside of the target component as well? (keyMap, handlers), should be encapsulated inside the 'app' running inside the modal overlay, shouldn't be known outside of it.

I tried the focused prop too, but it didn't help.

@chrisui
Copy link
Contributor

chrisui commented Feb 3, 2016

Interesting one. Thanks for the report! I think this may be down to the browser not thinking the element is truly in focus and so not firing the keyboard events on the correct element. I would've thought that manually calling DOMElement.prototype.focus() would work here though!

I don't have the time to investigate this right now but I will give it a shot either on the train home this evening or tomorrow!

@chrisui
Copy link
Contributor

chrisui commented Feb 3, 2016

Just to make sure there's nothing odd about the <video> element have you tried calling focus() on the div outputted by the <HotKeys /> component?

<HotKeys ref={el => el.focus()} />

@mako-taco
Copy link

I am experiencing the same sort of issue. My initial app is contained in a <HotKeys>, but the node is not in focus when the app loads, and instead requires a user to click somewhere on the screen to start using hotkeys.

Trying to focus the element on componentDidMount or inside a ref callback also does not seem to help, as the FocusTrap is not getting focus.

EDIT

Actually, if the ref callback is changed a little bit, it works.

const autofocus = (el) => {
    const found = ReactDOM.findDOMNode(el);
    if (found) {
        found.focus();
    }
};

return (
    <HotKeys
        keyMap={keyMap}
        handlers={this.handlers}
        ref={autofocus}>
        ...

@chrisui chrisui mentioned this issue Mar 29, 2016
8 tasks
@chrisui
Copy link
Contributor

chrisui commented Mar 29, 2016

@mako-taco Do you have the examples of both working & non-working focus on mounts?

Seems odd that focus could be called somewhere but hotkeys not be aware of it.

@mako-taco
Copy link

Sorry, I have pushed passed it, and no longer have those examples off hand. I don't consider this to be an issue anymore.

@loopmode
Copy link
Author

loopmode commented Apr 18, 2016

Hey, sorry I didn't reply at all... I consider the callback solution proposed by @mako-taco totally fine. I think it's not even a workaround, just proper usage :) Thanks

Works fine for me too

@chrisui
Copy link
Contributor

chrisui commented Apr 18, 2016

👍 Thanks for the update :)

@darsee
Copy link

darsee commented Apr 20, 2016

Would it be feasible to add an autofocus prop to <HotKeys> that could do this? I guess internally it would focus the DOM element corresponding to the FocusTrap?

@mendelk
Copy link

mendelk commented Aug 16, 2016

This is how I implemented this, based on @mako-taco's solution:

const Autofocus = (WrappedComponent) => {
  return class extends Component {
    setFocused(el){
      let found = findDOMNode(el);
      if (found) found.focus()
    }
    render() {
      return <WrappedComponent {...this.props} ref={this.setFocused} />
    }
  }
}

const AutofocusedHotKeys = Autofocus(HotKeys);

@tbranyen
Copy link

tbranyen commented Feb 8, 2017

You can shorten the ref callback to be a one liner with:

const autofocus = el => el && findDOMNode(el).focus();

// ...

<HotKeys ref={autofocus} ... />

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