Skip to content

Commit

Permalink
add keyboard navigation help text to CodeEditor
Browse files Browse the repository at this point in the history
  • Loading branch information
keithjgrant committed Feb 17, 2021
1 parent 8332692 commit 8203471
Showing 1 changed file with 76 additions and 42 deletions.
118 changes: 76 additions & 42 deletions awx/ui_next/src/components/CodeEditor/CodeEditor.jsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,28 @@
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 ReactAce from 'react-ace';
import 'ace-builds/src-noconflict/mode-json';
import 'ace-builds/src-noconflict/mode-javascript';
import 'ace-builds/src-noconflict/mode-yaml';
import 'ace-builds/src-noconflict/mode-django';
import 'ace-builds/src-noconflict/theme-github';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
import styled from 'styled-components';

const LINE_HEIGHT = 24;
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)`
font-family: var(--pf-global--FontFamily--monospace);
max-height: 90vh;
Expand Down Expand Up @@ -45,16 +57,21 @@ function CodeEditor({
rows,
fullHeight,
className,
i18n,
}) {
const [isKeyboardFocused, setIsKeyboardFocused] = useState(false);
const wrapper = useRef(null);
const editor = useRef(null);

useEffect(function removeTextareaTabIndex() {
const editorInput = editor.current.refEditor?.querySelector('textarea');
if (editorInput) {
editorInput.tabIndex = -1;
}
}, []);
useEffect(
function removeTextareaTabIndex() {
const editorInput = editor.current.refEditor?.querySelector('textarea');
if (editorInput && !readOnly) {
editorInput.tabIndex = -1;
}
},
[readOnly]
);

const listen = useCallback(event => {
if (
Expand Down Expand Up @@ -88,43 +105,60 @@ function CodeEditor({
const numRows = fullHeight ? value.split('\n').length : rows;

return (
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
<div ref={wrapper} tabIndex={0}>
<AceEditor
mode={aceModes[mode] || 'text'}
className={`pf-c-form-control ${className}`}
theme="github"
onChange={onChange}
value={value}
name={id || 'code-editor'}
editorProps={{ $blockScrolling: true }}
fontSize={16}
width="100%"
height={`${numRows * LINE_HEIGHT + PADDING}px`}
hasErrors={hasErrors}
setOptions={{
readOnly,
useWorker: false,
<>
<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);
}
}}
commands={[
{
name: 'escape',
bindKey: { win: 'Esc', mac: 'Esc' },
exec: () => {
wrapper.current.focus();
>
<AceEditor
mode={aceModes[mode] || 'text'}
className={`pf-c-form-control ${className}`}
theme="github"
onChange={onChange}
value={value}
name={id || 'code-editor'}
editorProps={{ $blockScrolling: true }}
fontSize={16}
width="100%"
height={`${numRows * LINE_HEIGHT + PADDING}px`}
hasErrors={hasErrors}
setOptions={{
readOnly,
useWorker: false,
}}
commands={[
{
name: 'escape',
bindKey: { win: 'Esc', mac: 'Esc' },
exec: () => {
wrapper.current.focus();
},
},
},
{
name: 'tab escape',
bindKey: { win: 'Shift-Tab', mac: 'Shift-Tab' },
exec: () => {
wrapper.current.focus();
{
name: 'tab escape',
bindKey: { win: 'Shift-Tab', mac: 'Shift-Tab' },
exec: () => {
wrapper.current.focus();
},
},
},
]}
ref={editor}
/>
</div>
]}
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>
)}
</>
);
}
CodeEditor.propTypes = {
Expand All @@ -146,4 +180,4 @@ CodeEditor.defaultProps = {
className: '',
};

export default CodeEditor;
export default withI18n()(CodeEditor);

0 comments on commit 8203471

Please sign in to comment.