Bug 1551945 - Ensure search inputs receive focus r=jlast

The previous patch for focus CSS was to aggressive -- this reverts that change and better focuses the feature

Differential Revision: https://phabricator.services.mozilla.com/D31327

--HG--
extra : moz-landing-system : lando
This commit is contained in:
David Walsh 2019-05-28 14:03:56 +00:00
Родитель 9904baeded
Коммит 52443a5de3
8 изменённых файлов: 114 добавлений и 4 удалений

Просмотреть файл

@ -53,6 +53,7 @@ type State = {
selectedResultIndex: number,
count: number,
index: number,
inputFocused: boolean,
};
type Props = {
@ -82,6 +83,7 @@ class SearchBar extends Component<Props, State> {
selectedResultIndex: 0,
count: 0,
index: -1,
inputFocused: false,
};
}
@ -146,7 +148,7 @@ class SearchBar extends Component<Props, State> {
e.stopPropagation();
e.preventDefault();
}
this.setState({ query: "" });
this.setState({ query: "", inputFocused: false });
};
toggleSearch = (e: SyntheticKeyboardEvent<HTMLElement>) => {
@ -162,10 +164,10 @@ class SearchBar extends Component<Props, State> {
const query = editor.codeMirror.getSelection() || this.state.query;
if (query !== "") {
this.setState({ query });
this.setState({ query, inputFocused: true });
this.doSearch(query);
} else {
this.setState({ query: "" });
this.setState({ query: "", inputFocused: true });
}
}
};
@ -198,6 +200,14 @@ class SearchBar extends Component<Props, State> {
return this.doSearch(e.target.value);
};
onFocus = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: true });
};
onBlur = (e: SyntheticFocusEvent<HTMLElement>) => {
this.setState({ inputFocused: false });
};
onKeyDown = (e: any) => {
if (e.key !== "Enter" && e.key !== "F3") {
return;
@ -320,11 +330,14 @@ class SearchBar extends Component<Props, State> {
summaryMsg={this.buildSummaryMsg()}
isLoading={false}
onChange={this.onChange}
onFocus={this.onFocus}
onBlur={this.onBlur}
showErrorEmoji={this.shouldShowErrorEmoji()}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleNext={e => this.traverseResults(e, false)}
handlePrev={e => this.traverseResults(e, true)}
shouldFocus={this.state.inputFocused}
showClose={false}
/>
<div className="search-bottom-bar">

Просмотреть файл

@ -10,12 +10,15 @@ exports[`SearchBar should render 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -80,12 +83,15 @@ exports[`showErrorEmoji false if no query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query=""
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -148,12 +154,15 @@ exports[`showErrorEmoji false if query + results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={false}
size=""
@ -216,12 +225,15 @@ exports[`showErrorEmoji true if query + no results 1`] = `
handlePrev={[Function]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in file…"
query="test"
selectedItemId=""
shouldFocus={false}
showClose={false}
showErrorEmoji={true}
size=""

Просмотреть файл

@ -56,6 +56,7 @@ type Item = Result | Match;
type State = {
inputValue: string,
inputFocused: boolean,
focusedItem: ?Item,
};
@ -89,6 +90,7 @@ export class ProjectSearch extends Component<Props, State> {
super(props);
this.state = {
inputValue: this.props.query || "",
inputFocused: false,
focusedItem: null,
};
}
@ -177,7 +179,11 @@ export class ProjectSearch extends Component<Props, State> {
};
onEnterPress = () => {
if (!this.isProjectSearchEnabled() || !this.state.focusedItem) {
if (
!this.isProjectSearchEnabled() ||
!this.state.focusedItem ||
this.state.inputFocused
) {
return;
}
if (this.state.focusedItem.type === "MATCH") {
@ -295,6 +301,8 @@ export class ProjectSearch extends Component<Props, State> {
summaryMsg={this.renderSummary()}
isLoading={status === statusType.fetching}
onChange={this.inputOnChange}
onFocus={() => this.setState({ inputFocused: true })}
onBlur={() => this.setState({ inputFocused: false })}
onKeyDown={this.onKeyDown}
onHistoryScroll={this.onHistoryScroll}
handleClose={

Просмотреть файл

@ -35,13 +35,16 @@ type Props = {
handleNext?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
handlePrev?: (e: SyntheticMouseEvent<HTMLButtonElement>) => void,
hasPrefix?: boolean,
onBlur?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onChange: (e: SyntheticInputEvent<HTMLInputElement>) => void,
onFocus?: (e: SyntheticFocusEvent<HTMLInputElement>) => void,
onKeyDown: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onKeyUp?: (e: SyntheticKeyboardEvent<HTMLInputElement>) => void,
onHistoryScroll?: (historyValue: string) => void,
placeholder: string,
query: string,
selectedItemId?: string,
shouldFocus?: boolean,
showErrorEmoji: boolean,
size: string,
summaryMsg: string,
@ -77,6 +80,12 @@ class SearchInput extends Component<Props, State> {
this.setFocus();
}
componentDidUpdate(prevProps: Props) {
if (this.props.shouldFocus && !prevProps.shouldFocus) {
this.setFocus();
}
}
setFocus() {
if (this.$input) {
const input = this.$input;
@ -115,6 +124,22 @@ class SearchInput extends Component<Props, State> {
];
}
onFocus = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onFocus } = this.props;
if (onFocus) {
onFocus(e);
}
};
onBlur = (e: SyntheticFocusEvent<HTMLInputElement>) => {
const { onBlur } = this.props;
if (onBlur) {
onBlur(e);
}
};
onKeyDown = (e: any) => {
const { onHistoryScroll, onKeyDown } = this.props;
if (!onHistoryScroll) {
@ -209,6 +234,8 @@ class SearchInput extends Component<Props, State> {
onChange,
onKeyDown: e => this.onKeyDown(e),
onKeyUp,
onFocus: e => this.onFocus(e),
onBlur: e => this.onBlur(e),
"aria-autocomplete": "list",
"aria-controls": "result-list",
"aria-activedescendant":

Просмотреть файл

@ -19,7 +19,9 @@ exports[`SearchInput renders 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -56,7 +58,9 @@ exports[`SearchInput shows nav buttons 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -119,7 +123,9 @@ exports[`SearchInput shows svg error emoji 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}
@ -182,7 +188,9 @@ exports[`SearchInput shows svg magnifying glass 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="A placeholder"
spellCheck={false}

Просмотреть файл

@ -16,7 +16,9 @@ exports[`ProjectSearch found no search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -117,7 +119,9 @@ exports[`ProjectSearch found search results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -150,7 +154,9 @@ exports[`ProjectSearch found search results 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
spellCheck={false}
@ -744,7 +750,9 @@ exports[`ProjectSearch should display loading message while search is in progres
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -781,7 +789,9 @@ exports[`ProjectSearch showErrorEmoji false if not done & no results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -818,7 +828,9 @@ exports[`ProjectSearch showErrorEmoji false if not done & results 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={true}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -863,7 +875,9 @@ exports[`ProjectSearch turns off shortcuts on unmount 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"
@ -895,7 +909,9 @@ exports[`ProjectSearch where <Enter> has not been pressed 1`] = `
handleClose={[MockFunction]}
hasPrefix={false}
isLoading={false}
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onHistoryScroll={[Function]}
onKeyDown={[Function]}
placeholder="Find in files…"

Просмотреть файл

@ -98,7 +98,9 @@ exports[`QuickOpenModal Basic render with mount & searchType = functions 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -229,7 +231,9 @@ exports[`QuickOpenModal Basic render with mount & searchType = variables 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -343,7 +347,9 @@ exports[`QuickOpenModal Basic render with mount 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -509,7 +515,9 @@ exports[`QuickOpenModal Simple goto search query = :abc & searchType = goto 1`]
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -628,7 +636,9 @@ exports[`QuickOpenModal showErrorEmoji false when count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -790,7 +800,9 @@ exports[`QuickOpenModal showErrorEmoji false when goto numeric ':2222' 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -909,7 +921,9 @@ exports[`QuickOpenModal showErrorEmoji false when no query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1039,7 +1053,9 @@ exports[`QuickOpenModal showErrorEmoji true when goto not numeric ':22k22' 1`] =
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1158,7 +1174,9 @@ exports[`QuickOpenModal showErrorEmoji true when no count + query 1`] = `
aria-autocomplete="list"
aria-controls="result-list"
className="empty"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}
@ -1335,7 +1353,9 @@ exports[`QuickOpenModal updateResults on enable 2`] = `
aria-autocomplete="list"
aria-controls="result-list"
className=""
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
onKeyDown={[Function]}
placeholder="Go to file…"
spellCheck={false}

Просмотреть файл

@ -64,4 +64,10 @@ add_task(async function() {
// selecting another source keeps search open
await selectSource(dbg, "simple2");
ok(findElement(dbg, "searchField"), "Search field is still visible");
// search is always focused regardless of when or how it was opened
pressKey(dbg, "fileSearch");
await clickElement(dbg, "codeMirror");
pressKey(dbg, "fileSearch");
is(dbg.win.document.activeElement.tagName, "INPUT", "Search field focused");
});