pleroma/app/soapbox/components/emoji_selector.js
marcin mikołajczak 13092271de wip accessible emoji picker
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
2021-07-18 12:53:17 +02:00

81 lines
2.1 KiB
JavaScript

import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
import emojify from 'soapbox/features/emoji/emoji';
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
import classNames from 'classnames';
const mapStateToProps = state => ({
allowedEmoji: getSoapboxConfig(state).get('allowedEmoji'),
});
export default @connect(mapStateToProps)
class EmojiSelector extends ImmutablePureComponent {
static propTypes = {
onReact: PropTypes.func.isRequired,
onUnfocus: PropTypes.func,
visible: PropTypes.bool,
focused: PropTypes.bool,
}
static defaultProps = {
onReact: () => {},
onUnfocus: () => {},
visible: false,
}
handleBlur = e => {
const { focused, onUnfocus } = this.props;
if (focused && (!e.relatedTarget || !e.relatedTarget.classList.contains('emoji-react-selector__emoji'))) {
onUnfocus();
}
}
handleKeyUp = i => e => {
switch (e.key) {
case 'Left':
case 'ArrowLeft':
if (i !== 0) {
this.node.querySelector(`.emoji-react-selector__emoji:nth-child(${i})`).focus();
}
break;
case 'Right':
case 'ArrowRight':
if (i !== this.props.allowedEmoji.size - 1) {
this.node.querySelector(`.emoji-react-selector__emoji:nth-child(${i + 2})`).focus();
}
break;
}
}
setRef = c => {
this.node = c;
}
render() {
const { onReact, visible, focused, allowedEmoji } = this.props;
return (
<div
className={classNames('emoji-react-selector', { 'emoji-react-selector--visible': visible, 'emoji-react-selector--focused': focused })}
onBlur={this.handleBlur}
ref={this.setRef}
>
{allowedEmoji.map((emoji, i) => (
<button
key={i}
className='emoji-react-selector__emoji'
dangerouslySetInnerHTML={{ __html: emojify(emoji) }}
onClick={onReact(emoji)}
onKeyUp={this.handleKeyUp(i)}
tabIndex={(visible || focused) ? 0 : -1}
/>
))}
</div>
);
}
}