add keyboard navigation help text to CodeEditor

This commit is contained in:
Keith J. Grant
2021-02-16 16:57:36 -08:00
parent 070c67ffe8
commit 19f4de0d05

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useRef, useCallback } from 'react'; import React, { useEffect, useRef, useCallback, useState } from 'react';
import { oneOf, bool, number, string, func } from 'prop-types'; import { oneOf, bool, number, string, func } from 'prop-types';
import ReactAce from 'react-ace'; import ReactAce from 'react-ace';
import 'ace-builds/src-noconflict/mode-json'; import 'ace-builds/src-noconflict/mode-json';
@@ -6,11 +6,23 @@ import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/mode-yaml'; import 'ace-builds/src-noconflict/mode-yaml';
import 'ace-builds/src-noconflict/mode-django'; import 'ace-builds/src-noconflict/mode-django';
import 'ace-builds/src-noconflict/theme-github'; import 'ace-builds/src-noconflict/theme-github';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components'; import styled from 'styled-components';
const LINE_HEIGHT = 24; const LINE_HEIGHT = 24;
const PADDING = 12; const PADDING = 12;
const FocusWrapper = styled.div`
&& + .pf-c-form__helper-text {
display: none;
}
&:focus-within + .pf-c-form__helper-text {
display: block;
}
`;
const AceEditor = styled(ReactAce)` const AceEditor = styled(ReactAce)`
font-family: var(--pf-global--FontFamily--monospace); font-family: var(--pf-global--FontFamily--monospace);
max-height: 90vh; max-height: 90vh;
@@ -45,16 +57,21 @@ function CodeEditor({
rows, rows,
fullHeight, fullHeight,
className, className,
i18n,
}) { }) {
const [isKeyboardFocused, setIsKeyboardFocused] = useState(false);
const wrapper = useRef(null); const wrapper = useRef(null);
const editor = useRef(null); const editor = useRef(null);
useEffect(function removeTextareaTabIndex() { useEffect(
function removeTextareaTabIndex() {
const editorInput = editor.current.refEditor?.querySelector('textarea'); const editorInput = editor.current.refEditor?.querySelector('textarea');
if (editorInput) { if (editorInput && !readOnly) {
editorInput.tabIndex = -1; editorInput.tabIndex = -1;
} }
}, []); },
[readOnly]
);
const listen = useCallback(event => { const listen = useCallback(event => {
if ( if (
@@ -88,8 +105,19 @@ function CodeEditor({
const numRows = fullHeight ? value.split('\n').length : rows; const numRows = fullHeight ? value.split('\n').length : rows;
return ( return (
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */ <>
<div ref={wrapper} tabIndex={0}> <FocusWrapper
ref={wrapper}
tabIndex={readOnly ? -1 : 0}
onFocus={e => {
if (e.target === e.currentTarget) {
setIsKeyboardFocused(true);
}
if (e.target.className.includes('ace_scrollbar')) {
setIsKeyboardFocused(false);
}
}}
>
<AceEditor <AceEditor
mode={aceModes[mode] || 'text'} mode={aceModes[mode] || 'text'}
className={`pf-c-form-control ${className}`} className={`pf-c-form-control ${className}`}
@@ -124,7 +152,13 @@ function CodeEditor({
]} ]}
ref={editor} ref={editor}
/> />
</FocusWrapper>
{isKeyboardFocused && (
<div className="pf-c-form__helper-text" aria-live="polite">
{i18n._(t`Press Enter to edit. Press ESC to stop editing.`)}
</div> </div>
)}
</>
); );
} }
CodeEditor.propTypes = { CodeEditor.propTypes = {
@@ -146,4 +180,4 @@ CodeEditor.defaultProps = {
className: '', className: '',
}; };
export default CodeEditor; export default withI18n()(CodeEditor);