зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
9904baeded
Коммит
52443a5de3
|
@ -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");
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче