Created
November 26, 2018 21:58
-
-
Save r2dev/3a21e516b8c301f2e61cd16fa51ee56c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from "react"; | |
let keys = { | |
end: 35, | |
home: 36, | |
left: 37, | |
up: 38, | |
right: 39, | |
down: 40, | |
delete: 46, | |
enter: 13, | |
space: 32 | |
}; | |
class App extends Component { | |
render() { | |
return <Tab />; | |
} | |
} | |
class Tab extends Component { | |
state = { | |
active: 0 | |
}; | |
constructor(props) { | |
super(props); | |
this.tabRefs = [React.createRef(), React.createRef(), React.createRef()]; | |
this.tabList = React.createRef(); | |
} | |
handleKeyDown = event => { | |
let key = event.keyCode; | |
switch (key) { | |
case keys.end: | |
{ | |
this.tabRefs[2].current.focus(); | |
} | |
break; | |
case keys.home: | |
{ | |
this.tabRefs[0].current.focus(); | |
} | |
break; | |
case keys.down: | |
case keys.up: | |
{ | |
this.handleArrow(event); | |
} | |
break; | |
default: | |
} | |
}; | |
handleKeyUp = event => { | |
let key = event.keyCode; | |
switch (key) { | |
case keys.left: | |
case keys.right: | |
{ | |
this.handleArrow(event); | |
} | |
break; | |
case keys.enter: | |
case keys.space: | |
{ | |
this.setState({ active: event.target.dataset.index }); | |
} | |
break; | |
default: | |
} | |
}; | |
handleArrow = event => { | |
let key = event.keyCode; | |
let vertical = | |
this.tabList.current.getAttribute("aria-orientation") === "vertical"; | |
let proceed = false; | |
if (vertical) { | |
if (key === keys.up || key === keys.down) { | |
event.preventDefault(); | |
proceed = true; | |
} | |
} else { | |
if (key === keys.left || key === keys.right) { | |
proceed = true; | |
} | |
} | |
if (proceed) { | |
const index = parseInt(event.target.dataset.index); | |
if (key === keys.up || key === keys.left) { | |
if (index === 0) { | |
this.tabRefs[2].current.focus(); | |
} else { | |
this.tabRefs[index - 1].current.focus(); | |
} | |
} else if (key === keys.down || key === keys.right) { | |
if (index === 2) { | |
this.tabRefs[0].current.focus(); | |
} else { | |
this.tabRefs[index + 1].current.focus(); | |
} | |
} | |
} | |
}; | |
handleClick = (event) => { | |
const index = parseInt(event.target.dataset.index); | |
this.setState({active: index}) | |
} | |
render() { | |
const { active } = this.state; | |
return ( | |
<div> | |
<div role="tablist" ref={this.tabList}> | |
<button | |
data-index={0} | |
role="tab" | |
aria-selected={active === 0} | |
id="a-button" | |
tabIndex={active === 0 ? undefined : -1} | |
onClick={this.handleClick} | |
aria-controls="a-tab" | |
onKeyDown={this.handleKeyDown} | |
onKeyUp={this.handleKeyUp} | |
ref={this.tabRefs[0]} | |
> | |
A | |
</button> | |
<button | |
data-index={1} | |
role="tab" | |
aria-selected={active === 1} | |
id="b-button" | |
tabIndex={active === 1 ? undefined : -1} | |
onClick={this.handleClick} | |
aria-controls="b-tab" | |
onKeyDown={this.handleKeyDown} | |
onKeyUp={this.handleKeyUp} | |
ref={this.tabRefs[1]} | |
> | |
B | |
</button> | |
<button | |
data-index={2} | |
role="tab" | |
aria-selected={active === 2} | |
id="c-button" | |
tabIndex={active === 2 ? undefined : -1} | |
onClick={this.handleClick} | |
aria-controls="c-tab" | |
onKeyDown={this.handleKeyDown} | |
onKeyUp={this.handleKeyUp} | |
ref={this.tabRefs[2]} | |
> | |
C | |
</button> | |
</div> | |
<div | |
tabIndex="0" | |
role="tabpanel" | |
hidden={active !== 0} | |
id="a-tab" | |
aria-labelledby="a-button" | |
> | |
A content | |
</div> | |
<div | |
tabIndex="0" | |
role="tabpanel" | |
hidden={active !== 1} | |
id="b-tab" | |
aria-labelledby="b-button" | |
> | |
B content | |
</div> | |
<div | |
tabIndex="0" | |
role="tabpanel" | |
hidden={active !== 2} | |
id="c-tab" | |
aria-labelledby="c-button" | |
> | |
<form> | |
<input type="text" /> | |
<button>submit</button> | |
</form> | |
</div> | |
</div> | |
); | |
} | |
} | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment