Skip to content

Commit 29f1cef

Browse files
committed
feat: search auto focus
1 parent a5b2e90 commit 29f1cef

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

src/features/search/index.jsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ const STATIC_PROPS =
6868
},
6969
PopperComponent,
7070
onChange: handleChange,
71-
renderInput,
7271
renderOption,
7372
autoComplete: false,
7473
clearOnBlur: false,
@@ -83,18 +82,41 @@ export function Search() {
8382

8483
const { t } = useTranslation()
8584

85+
/** @type {React.MutableRefObject<HTMLInputElement | null>} */
86+
const inputRef = React.useRef(null)
87+
8688
const search = useStorage((s) => s.search)
8789
const isMobile = useMemory((s) => s.isMobile)
8890
const open = useLayoutStore((s) => s.search)
8991

9092
const { loading, options, handleInputChange } = useSendSearch(search, open)
9193

94+
const handleDialogEntered = React.useCallback(() => {
95+
if (inputRef.current) {
96+
inputRef.current.focus()
97+
}
98+
}, [])
99+
100+
React.useEffect(() => {
101+
if (!open) {
102+
return undefined
103+
}
104+
const frame = requestAnimationFrame(() => {
105+
if (inputRef.current) {
106+
inputRef.current.focus()
107+
}
108+
})
109+
return () => cancelAnimationFrame(frame)
110+
}, [open])
111+
92112
return (
93113
<Dialog
94114
fullScreen={isMobile}
95115
open={open}
96116
onClose={handleClose}
117+
disableAutoFocus
97118
sx={DIALOG_SX}
119+
TransitionProps={{ onEntered: handleDialogEntered }}
98120
>
99121
<Box width={BOX_WIDTH}>
100122
<Header titles="search" action={handleClose} />
@@ -106,6 +128,7 @@ export function Search() {
106128
loading={loading}
107129
loadingText={t('searching')}
108130
noOptionsText={t('no_options')}
131+
renderInput={(params) => renderInput(params, inputRef)}
109132
{...STATIC_PROPS}
110133
/>
111134
</Box>

src/features/search/renderInput.jsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,11 @@ const EndAdornment = React.memo(
7070
},
7171
)
7272

73-
/** @param {import('@mui/material').AutocompleteRenderInputParams} props */
74-
export function renderInput({ InputProps, ...props }) {
73+
/**
74+
* @param {import('@mui/material').AutocompleteRenderInputParams} props
75+
* @param {React.MutableRefObject<HTMLInputElement | null>} [inputRef]
76+
*/
77+
export function renderInput({ InputProps, ...props }, inputRef) {
7578
const { t } = useTranslation()
7679

7780
const searchTab = useStorage((s) => s.searchTab)
@@ -98,11 +101,24 @@ export function renderInput({ InputProps, ...props }) {
98101
}
99102
}, [searchTab, data])
100103

104+
const handleInputRef = (node) => {
105+
const { ref } = props.inputProps
106+
if (typeof ref === 'function') {
107+
ref(node)
108+
} else if (ref && typeof ref === 'object') {
109+
ref.current = node
110+
}
111+
if (inputRef) {
112+
inputRef.current = node
113+
}
114+
}
115+
101116
return (
102117
<>
103118
<TextField
104119
placeholder={t(`global_search_${searchTab}`)}
105120
variant="standard"
121+
inputRef={handleInputRef}
106122
{...props}
107123
InputProps={{
108124
...InputProps,

0 commit comments

Comments
 (0)