Skip to content

Commit 4320bf6

Browse files
committed
Moving on with search bar improvements
1 parent 6a504ee commit 4320bf6

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

src/SearchBar/SearchButton.tsx

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { useEffect, useState } from "react";
3+
import React, { useEffect, useState, useReducer } from "react";
44
import { useTranslation } from "./SearchBar";
55
import { fr } from "../fr";
66
import { assert } from "tsafe/assert";
@@ -17,7 +17,9 @@ export function SearchButton(props: SearchButtonProps) {
1717

1818
const { t } = useTranslation();
1919

20-
const [inputValue, setInputValue] = useState("");
20+
const [, forceUpdate] = useReducer(x => x + 1, 0);
21+
22+
const [getInputValue, setGetInputValue] = useState(() => () => "");
2123

2224
const [resetInputValue, setResetInputValue] = useState<() => void>(() => () => {
2325
/* do nothing */
@@ -29,6 +31,8 @@ export function SearchButton(props: SearchButtonProps) {
2931
const [isInputFocused, setIsInputFocused] = useState(false);
3032

3133
const onClick = useConstCallback(() => {
34+
const inputValue = getInputValue();
35+
3236
if (inputValue === "") {
3337
focusInputElement();
3438
return;
@@ -38,6 +42,8 @@ export function SearchButton(props: SearchButtonProps) {
3842
resetInputValue();
3943
});
4044

45+
const isControlledByUser = onClick_props === undefined;
46+
4147
useEffect(() => {
4248
const inputElement = document.getElementById(searchInputId);
4349

@@ -49,21 +55,40 @@ export function SearchButton(props: SearchButtonProps) {
4955

5056
assert(is<HTMLInputElement>(inputElement));
5157

52-
setInputValue(inputElement.value);
58+
setGetInputValue(() => () => inputElement.value);
5359

5460
const cleanups: (() => void)[] = [];
5561

5662
inputElement.addEventListener(
5763
"input",
5864
(() => {
59-
const callback = () => setInputValue(inputElement.value);
65+
const callback = () => {
66+
forceUpdate();
67+
};
6068

6169
cleanups.push(() => inputElement.removeEventListener("input", callback));
6270

6371
return callback;
6472
})()
6573
);
6674

75+
inputElement.addEventListener(
76+
"keydown",
77+
(() => {
78+
const callback = (event: KeyboardEvent) => {
79+
if (event.key !== "Escape") {
80+
return;
81+
}
82+
83+
forceUpdate();
84+
};
85+
86+
cleanups.push(() => inputElement.removeEventListener("keydown", callback));
87+
88+
return callback;
89+
})()
90+
);
91+
6792
const resetInputValue = () => {
6893
inputElement.value = "";
6994
inputElement.dispatchEvent(new Event("input"));
@@ -73,7 +98,7 @@ export function SearchButton(props: SearchButtonProps) {
7398

7499
setFocusInputElement(() => () => inputElement.focus());
75100

76-
if (onClick_props === undefined) {
101+
if (isControlledByUser) {
77102
inputElement.addEventListener(
78103
"focus",
79104
(() => {
@@ -95,7 +120,9 @@ export function SearchButton(props: SearchButtonProps) {
95120
return callback;
96121
})()
97122
);
98-
} else {
123+
}
124+
125+
if (!isControlledByUser) {
99126
inputElement.addEventListener(
100127
"keydown",
101128
(() => {
@@ -136,9 +163,9 @@ export function SearchButton(props: SearchButtonProps) {
136163
return () => {
137164
cleanups.forEach(cleanup => cleanup());
138165
};
139-
}, [searchInputId, onClick_props]);
166+
}, [searchInputId, isControlledByUser]);
140167

141-
if (onClick_props === undefined && (isInputFocused || inputValue !== "")) {
168+
if (onClick_props === undefined && (isInputFocused || getInputValue() !== "")) {
142169
return null;
143170
}
144171

stories/Header.stories.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,12 @@ function MySearchInput(props: MySearchInputProps) {
200200
const { className, id, placeholder, type } = props;
201201

202202
const [search, onSearchChange] = useState("");
203+
const [inputElement, setInputElement] = useState<HTMLInputElement | null>(null);
203204

204205
return (
205206
<>
206207
<input
208+
ref={setInputElement}
207209
className={className}
208210
id={id}
209211
placeholder={placeholder}
@@ -213,6 +215,7 @@ function MySearchInput(props: MySearchInputProps) {
213215
onKeyDown={event => {
214216
if (event.key === "Escape") {
215217
onSearchChange("");
218+
inputElement?.blur();
216219
}
217220
}}
218221
/>
@@ -267,9 +270,15 @@ function MySearchInput(props: MySearchInputProps) {
267270
268271
const { className, id, placeholder, type, search, onSearchChange } = props;
269272
273+
const [
274+
inputElement,
275+
setInputElement
276+
] = useState<HTMLInputElement | null>(null);
277+
270278
return (
271279
<>
272280
<input
281+
ref={setInputElement}
273282
className={className}
274283
id={id}
275284
placeholder={placeholder}
@@ -279,6 +288,7 @@ function MySearchInput(props: MySearchInputProps) {
279288
onKeyDown={event => {
280289
if (event.key === "Escape") {
281290
onSearchChange("");
291+
inputElement?.blur();
282292
}
283293
}}
284294
/>

stories/SearchBar.stories.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,12 @@ function MySearchInput(props: MySearchInputProps) {
6363

6464
const [search, onSearchChange] = useState("");
6565

66+
const [inputElement, setInputElement] = useState<HTMLInputElement | null>(null);
67+
6668
return (
6769
<>
6870
<input
71+
ref={setInputElement}
6972
className={className}
7073
id={id}
7174
placeholder={placeholder}
@@ -75,6 +78,7 @@ function MySearchInput(props: MySearchInputProps) {
7578
onKeyDown={event => {
7679
if (event.key === "Escape") {
7780
onSearchChange("");
81+
inputElement?.blur();
7882
}
7983
}}
8084
/>
@@ -115,7 +119,12 @@ type MySearchInputProps = {
115119
function MySearchInput(props: MySearchInputProps) {
116120
117121
const { className, id, placeholder, type, search, onSearchChange } = props;
118-
122+
123+
const [
124+
inputElement,
125+
setInputElement
126+
] = useState<HTMLInputElement | null>(null);
127+
119128
return (
120129
<>
121130
<input
@@ -128,6 +137,7 @@ function MySearchInput(props: MySearchInputProps) {
128137
onKeyDown={event => {
129138
if (event.key === "Escape") {
130139
onSearchChange("");
140+
setInputElement?.blur();
131141
}
132142
}}
133143
/>

0 commit comments

Comments
 (0)