Accessible components refactored

This commit is contained in:
NikolaBorislavovHristov 2019-08-04 23:30:24 +03:00
parent 238915c76e
commit c108fe2b35
3 changed files with 35 additions and 54 deletions

View file

@ -1,4 +1,5 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const { useFocusable } = require('stremio-navigation');
@ -46,4 +47,17 @@ const Button = React.forwardRef(({ children, ...props }, ref) => {
Button.displayName = 'Button';
Button.propTypes = {
className: PropTypes.string,
tabIndex: PropTypes.number,
href: PropTypes.string,
disabled: PropTypes.bool,
onKeyUp: PropTypes.func,
onMouseDown: PropTypes.func,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
};
module.exports = Button;

View file

@ -5,10 +5,10 @@ const Icon = require('stremio-icons/dom');
const Button = require('../Button');
const styles = require('./styles');
const Checkbox = React.forwardRef(({ className, checked = false, disabled = false, onClick, children }, ref) => {
const Checkbox = React.forwardRef(({ children, ...props }, ref) => {
return (
<Button ref={ref} className={classnames(className, styles['checkbox-container'], { 'checked': checked })} disabled={disabled} onClick={onClick}>
<Icon className={styles['icon']} icon={checked ? 'ic_check' : 'ic_box_empty'} />
<Button {...props} ref={ref} className={classnames(props.className, styles['checkbox-container'], { 'checked': props.checked })}>
<Icon className={styles['icon']} icon={props.checked ? 'ic_check' : 'ic_box_empty'} />
{React.isValidElement(children) ? children : null}
</Button>
);
@ -19,8 +19,6 @@ Checkbox.displayName = 'Checkbox';
Checkbox.propTypes = {
className: PropTypes.string,
checked: PropTypes.bool,
disabled: PropTypes.bool,
onClick: PropTypes.func,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node

View file

@ -1,71 +1,40 @@
const React = require('react');
const PropTypes = require('prop-types');
const classnames = require('classnames');
const { useFocusable } = require('stremio-navigation');
const ENTER_KEY_CODE = 13;
const BUTTON_INPUT_TYPES = ['button', 'link'];
const TEXT_INPUT_TYPES = ['text', 'email', 'password'];
const TAG_NAMES_FOR_TYPE = Object.assign(Object.create(null), {
button: 'div',
link: 'a',
text: 'input',
email: 'input',
password: 'input'
});
const Input = React.forwardRef(({ type, tabIndex, children, ...props }, ref) => {
const Input = React.forwardRef((props, ref) => {
const focusable = useFocusable();
const onKeyUp = React.useCallback((event) => {
if (typeof props.onKeyUp === 'function') {
props.onKeyUp(event);
}
if (!event.nativeEvent.submitPrevented && event.keyCode === ENTER_KEY_CODE) {
if (BUTTON_INPUT_TYPES.includes(type)) {
event.currentTarget.click();
} else if (TEXT_INPUT_TYPES.includes(type)) {
if (typeof props.onSubmit === 'function') {
props.onSubmit(event);
}
}
if (event.keyCode === ENTER_KEY_CODE && !event.nativeEvent.submitPrevented && typeof props.onSubmit === 'function') {
props.onSubmit(event);
}
}, [props.onKeyUp, props.onSubmit, type]);
const onMouseDown = React.useCallback((event) => {
if (typeof props.onMouseDown === 'function') {
props.onMouseDown(event);
}
if (!event.nativeEvent.blurPrevented && BUTTON_INPUT_TYPES.includes(type)) {
event.preventDefault();
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
}
}, [props.onMouseDown, type]);
const tagName = TAG_NAMES_FOR_TYPE[type];
const elementProps = {
...props,
ref,
type: tagName === 'input' ? type : null,
tabIndex: (isNaN(tabIndex) || tabIndex === null) ? (focusable ? 0 : -1) : tabIndex,
onKeyUp,
onMouseDown
};
return React.createElement(tagName, elementProps, children);
}, [props.onKeyUp, props.onSubmit]);
return (
<input
{...props}
ref={ref}
className={classnames(props.className, { 'disabled': props.disabled })}
tabIndex={(props.tabIndex === null || isNaN(props.tabIndex)) ? (focusable ? 0 : -1) : props.tabIndex}
onKeyUp={onKeyUp}
/>
);
});
Input.displayName = 'Input';
Input.propTypes = {
type: PropTypes.oneOf([
...BUTTON_INPUT_TYPES,
...TEXT_INPUT_TYPES
]).isRequired,
className: PropTypes.string,
tabIndex: PropTypes.number,
children: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.node),
PropTypes.node
])
disabled: PropTypes.bool,
onKeyUp: PropTypes.func,
onSubmit: PropTypes.func
};
module.exports = Input;