50698f9a7d
Search now exposes a small icon-only clear button whenever a query is present. Clicking it clears the term in one step and returns focus to the input so users can immediately type a replacement. The button uses the existing topbar styling language and a compact circled-x icon alongside the keyboard hint. Test Plan: - git diff --check Refs: user redesign nitpick about one-click search clearing
69 lines
2.1 KiB
TypeScript
69 lines
2.1 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
|
|
import { Icon } from '../Icon';
|
|
|
|
interface Props {
|
|
value: string;
|
|
onChange: (value: string) => void;
|
|
}
|
|
|
|
/**
|
|
* Search input with a `/` keyboard shortcut for focus. Ignores the shortcut
|
|
* when the user is already typing into another input or textarea.
|
|
*/
|
|
export const SearchField = ({ value, onChange }: Props) => {
|
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
|
|
useEffect(() => {
|
|
const onKey = (e: KeyboardEvent) => {
|
|
if (e.key !== '/') return;
|
|
const target = e.target as HTMLElement | null;
|
|
if (target && (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA')) return;
|
|
e.preventDefault();
|
|
inputRef.current?.focus();
|
|
};
|
|
window.addEventListener('keydown', onKey);
|
|
return () => window.removeEventListener('keydown', onKey);
|
|
}, []);
|
|
|
|
const blurInput = () => inputRef.current?.blur();
|
|
|
|
return (
|
|
<div className="search">
|
|
<Icon.search />
|
|
<input
|
|
ref={inputRef}
|
|
type="text"
|
|
placeholder="Search games"
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
blurInput();
|
|
} else if (e.key === 'Escape') {
|
|
e.preventDefault();
|
|
onChange('');
|
|
blurInput();
|
|
}
|
|
}}
|
|
spellCheck={false}
|
|
/>
|
|
{value && (
|
|
<button
|
|
className="search-clear"
|
|
type="button"
|
|
aria-label="Clear search"
|
|
onClick={() => {
|
|
onChange('');
|
|
inputRef.current?.focus();
|
|
}}
|
|
>
|
|
<Icon.clearCircle />
|
|
</button>
|
|
)}
|
|
<span className="search-kbd">/</span>
|
|
</div>
|
|
);
|
|
};
|