Skip to content

Commit

Permalink
Merge pull request metabrainz#2948 from metabrainz/search-input-focus
Browse files Browse the repository at this point in the history
Autofocus on search input in MBIDMapping modal
  • Loading branch information
MonkeyDo authored Aug 5, 2024
2 parents dd38e1e + 336e68e commit 2ad5b45
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
5 changes: 5 additions & 0 deletions frontend/js/src/common/listens/MBIDMappingModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ export default NiceModal.create(({ listenToMap }: MBIDMappingModalProps) => {
TrackMetadata
>();

const searchInputRef = React.useRef<HTMLInputElement>(null);

const closeModal = React.useCallback(() => {
modal.hide();
document?.body?.classList?.remove("modal-open");
Expand Down Expand Up @@ -141,6 +143,8 @@ export default NiceModal.create(({ listenToMap }: MBIDMappingModalProps) => {
setDefaultValue(
`${getTrackName(listenToMap)} - ${getArtistName(listenToMap)}`
);
// Autofocus on the search input in order to automatically show list of results
searchInputRef?.current?.focus();
}, [listenToMap]);

const listenFromSelectedRecording = getListenFromSelectedRecording(
Expand Down Expand Up @@ -270,6 +274,7 @@ export default NiceModal.create(({ listenToMap }: MBIDMappingModalProps) => {
) : (
<div className="card listen-card">
<SearchTrackOrMBID
ref={searchInputRef}
expectedPayload="trackmetadata"
key={`${defaultValue}-${copyTextClickCounter}`}
onSelectRecording={(trackMetadata) => {
Expand Down
6 changes: 5 additions & 1 deletion frontend/js/src/user/components/AddSingleListen.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import {
faChevronDown,
faTimesCircle,
Expand Down Expand Up @@ -26,6 +26,8 @@ export default function AddSingleListen({
| undefined;
}>({});

const searchInputRef = useRef<HTMLInputElement>(null);

const removeRecording = (recordingMBID: string) => {
setSelectedRecordings((prevRecordings) =>
prevRecordings.filter((rec) => rec.id !== recordingMBID)
Expand Down Expand Up @@ -72,6 +74,7 @@ export default function AddSingleListen({
return (
<div>
<SearchTrackOrMBID
ref={searchInputRef}
expectedPayload="recording"
onSelectRecording={selectRecording}
/>
Expand Down Expand Up @@ -101,6 +104,7 @@ export default function AddSingleListen({
iconSize="lg"
action={() => {
removeRecording(recording.id);
searchInputRef?.current?.focus();
}}
/>
}
Expand Down
3 changes: 3 additions & 0 deletions frontend/js/src/utils/SearchAlbumOrMBID.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default function SearchAlbumOrMBID({
const { APIService } = useContext(GlobalAppContext);
const { lookupMBReleaseGroup, searchMBRelease } = APIService;
const dropdownRef = DropdownRef();
const searchInputRef = useRef<HTMLInputElement>(null);
const [inputValue, setInputValue] = useState(defaultValue ?? "");
const [searchResults, setSearchResults] = useState<
Array<MusicBrainzRelease & Partial<WithMedia> & WithArtistCredits>
Expand Down Expand Up @@ -122,6 +123,7 @@ export default function SearchAlbumOrMBID({
setInputValue("");
setSearchResults([]);
onSelectAlbum();
searchInputRef?.current?.focus();
};

useEffect(() => {
Expand All @@ -143,6 +145,7 @@ export default function SearchAlbumOrMBID({
<div>
<div className="input-group dropdown-search" ref={dropdownRef}>
<input
ref={searchInputRef}
type="search"
value={inputValue}
className="form-control"
Expand Down
36 changes: 30 additions & 6 deletions frontend/js/src/utils/SearchTrackOrMBID.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { faTimesCircle } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { throttle } from "lodash";
import React, {
forwardRef,
useCallback,
useContext,
useEffect,
useImperativeHandle,
useMemo,
useRef,
useState,
Expand Down Expand Up @@ -37,11 +39,10 @@ type SearchTrackOrMBIDProps = {
expectedPayload: PayloadType;
} & ConditionalReturnValue;

export default function SearchTrackOrMBID({
onSelectRecording,
expectedPayload,
defaultValue,
}: SearchTrackOrMBIDProps) {
const SearchTrackOrMBID = forwardRef(function SearchTrackOrMBID(
{ onSelectRecording, expectedPayload, defaultValue }: SearchTrackOrMBIDProps,
inputRefForParent
) {
const { APIService } = useContext(GlobalAppContext);
const { lookupMBRecording } = APIService;
const dropdownRef = DropdownRef();
Expand All @@ -50,6 +51,25 @@ export default function SearchTrackOrMBID({
[]
);
const [selectedIndex, setSelectedIndex] = useState(-1);
const inputRefLocal = useRef<HTMLInputElement>(null);

// Allow parents to focus on input
useImperativeHandle(
inputRefForParent,
() => {
return {
focus() {
inputRefLocal?.current?.focus();
},
};
},
[]
);

// Autofocus once on load
useEffect(() => {
inputRefLocal?.current?.focus();
}, []);

const handleError = useCallback(
(error: string | Error, title?: string): void => {
Expand Down Expand Up @@ -180,6 +200,7 @@ export default function SearchTrackOrMBID({
setInputValue("");
setSearchResults([]);
setSelectedIndex(-1);
inputRefLocal?.current?.focus();
};

useEffect(() => {
Expand All @@ -199,6 +220,7 @@ export default function SearchTrackOrMBID({
<div>
<div className="input-group dropdown-search" ref={dropdownRef}>
<input
ref={inputRefLocal}
type="search"
value={inputValue}
className="form-control"
Expand Down Expand Up @@ -261,4 +283,6 @@ export default function SearchTrackOrMBID({
</div>
</div>
);
}
});

export default SearchTrackOrMBID;

0 comments on commit 2ad5b45

Please sign in to comment.