From a5ab579b03cf8916821afadd4c2388cd39312ba1 Mon Sep 17 00:00:00 2001 From: Damien de Lemeny Date: Mon, 19 Feb 2024 15:56:23 -0500 Subject: [PATCH] Improve LuceneQueryEditor keyboard a11y, fixes #76 --- src/components/LuceneQueryEditor.tsx | 13 +++++++++++-- src/components/QueryEditor/index.tsx | 22 +++++++++++++++++----- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/components/LuceneQueryEditor.tsx b/src/components/LuceneQueryEditor.tsx index 89d193c..03f4593 100644 --- a/src/components/LuceneQueryEditor.tsx +++ b/src/components/LuceneQueryEditor.tsx @@ -4,7 +4,7 @@ import { useObservableCallback, useSubscription } from 'observable-hooks' import { css } from "@emotion/css"; -import CodeMirror, { ReactCodeMirrorRef } from '@uiw/react-codemirror'; +import CodeMirror, { ReactCodeMirrorRef, keymap } from '@uiw/react-codemirror'; import {linter, Diagnostic, lintGutter} from "@codemirror/lint" import {autocompletion, CompletionContext} from "@codemirror/autocomplete" import { LuceneQuery } from "utils/lucene"; @@ -15,6 +15,7 @@ export type LuceneQueryEditorProps = { value: string, autocompleter: (word: string) => any, onChange: (query: string) => void + onSubmit: (query: string) => void } export function LuceneQueryEditor(props: LuceneQueryEditorProps){ @@ -61,6 +62,14 @@ export function LuceneQueryEditor(props: LuceneQueryEditorProps){ placeholder={props.placeholder} value={props.value} onChange={onChange} - extensions={[queryLinter, lintGutter(), autocomplete]} + indentWithTab={false} + extensions={[ + queryLinter, lintGutter(), + autocomplete, + keymap.of([{key:'Shift-Enter', run:(target)=>{ + props.onSubmit(target.state.doc.toString()) + return true; + }}]) + ]} />); } diff --git a/src/components/QueryEditor/index.tsx b/src/components/QueryEditor/index.tsx index 14a978c..9c26b2e 100644 --- a/src/components/QueryEditor/index.tsx +++ b/src/components/QueryEditor/index.tsx @@ -34,7 +34,7 @@ export const QueryEditor = ({ query, onChange, onRunQuery, datasource, range, ap query={query} range={range || getDefaultTimeRange()} > - + ); }; @@ -54,21 +54,33 @@ export const useSearchableFields = getHook(SearchableFieldsContext) interface Props { value: ElasticsearchQuery; + onRunQuery: (query: string) => void } -export const ElasticSearchQueryField = ({ value, onChange }: { value?: string; onChange: (v: string) => void }) => { +type ElasticSearchQueryFieldProps = { + value?: string; + onChange: (v: string) => void + onSubmit: (v: string) => void +} +export const ElasticSearchQueryField = ({ value, onChange, onSubmit }: ElasticSearchQueryFieldProps) => { const styles = useStyles2(getStyles); const datasource = useDatasource() const { getSuggestions } = useDatasourceFields(datasource); return (
- +
); }; -const QueryEditorForm = ({ value }: Props) => { +const QueryEditorForm = ({ value, onRunQuery }: Props) => { const dispatch = useDispatch(); const nextId = useNextId(); const styles = useStyles2(getStyles); @@ -87,7 +99,7 @@ const QueryEditorForm = ({ value }: Props) => {
Lucene Query - dispatch(changeQuery(query))} value={value?.query} /> + dispatch(changeQuery(query))} value={value?.query} onSubmit={onRunQuery} />