Focusable component implemented

This commit is contained in:
NikolaBorislavovHristov 2019-01-21 13:33:00 +02:00
parent 51854561b7
commit 5e43c94b59
5 changed files with 79 additions and 1 deletions

View file

@ -0,0 +1,12 @@
import React from 'react';
import FocusableContext from './FocusableContext';
const Focusable = ({ children }) => {
return (
<FocusableContext.Consumer>
{focusable => React.cloneElement(React.Children.only(children), { tabIndex: focusable ? 0 : -1 })}
</FocusableContext.Consumer>
);
};
export default Focusable;

View file

@ -0,0 +1,3 @@
import React from 'react';
export default React.createContext(false);

View file

@ -0,0 +1,53 @@
import React, { Component } from 'react';
import FocusableContext from './FocusableContext';
class FocusableProvider extends Component {
constructor(props) {
super(props);
this.childElementRef = React.createRef();
this.containerClildListObserver = new MutationObserver(this.containerClildListOnChange);
this.state = {
focusable: false
};
}
componentDidMount() {
this.containerClildListOnChange();
this.containerClildListObserver.observe(this.childElementRef.current.parentElement, {
childList: true
});
}
componentWillUnmount() {
this.containerClildListObserver.disconnect();
}
shouldComponentUpdate(nextProps, nextState) {
return nextProps.children !== this.props.children ||
nextState.focusable !== this.state.focusable;
}
containerClildListOnChange = () => {
for (let i = this.childElementRef.current.parentElement.children.length - 1; i >= 0; i--) {
const child = this.childElementRef.current.parentElement.children[i];
const tagName = child.tagName.toLowerCase();
if (tagName !== 'script' && tagName !== 'style') {
this.setState({
focusable: this.childElementRef.current === child
});
break;
}
}
}
render() {
return (
<FocusableContext.Provider value={this.state.focusable}>
{React.cloneElement(React.Children.only(this.props.children), { ref: this.childElementRef })}
</FocusableContext.Provider>
);
}
}
export default FocusableProvider;

View file

@ -0,0 +1,7 @@
import Focusable from './Focusable';
import FocusableProvider from './FocusableProvider';
export {
Focusable,
FocusableProvider
};

View file

@ -9,6 +9,7 @@ import MetaItem from './MetaItem';
import ShareAddon from './ShareAddon';
import UserPanel from './UserPanel';
import Slider from './Slider';
import { Focusable, FocusableProvider } from './Focusable';
export {
Checkbox,
@ -21,5 +22,7 @@ export {
MetaItem,
ShareAddon,
UserPanel,
Slider
Slider,
Focusable,
FocusableProvider
};