Search shortcuts (#2963)

This commit is contained in:
hfcRed 2026-04-12 16:03:32 +02:00 committed by GitHub
parent 984a93bd12
commit 0f581d7582
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 67 additions and 11 deletions

View File

@ -98,15 +98,38 @@
outline: none;
}
.inputContainer {
display: flex;
align-items: center;
border-bottom: 1px solid var(--color-border);
&:focus-within {
border-color: var(--color-text-accent);
}
}
.inputPrefix {
font-size: var(--font-xs);
color: var(--color-text-high);
margin-left: var(--s-4);
background-color: var(--color-bg-high);
border-radius: var(--radius-selector);
height: var(--selector-size);
padding-inline: var(--s-1);
text-align: center;
width: var(--s-8);
line-height: 1.75;
}
.input.input {
padding: var(--s-4);
border: none;
border-bottom: 1px solid var(--color-border);
border-radius: 0;
background: transparent;
font-size: var(--font-md);
color: var(--color-text);
height: auto;
padding-left: 0;
& input::placeholder {
color: var(--color-text-high);
@ -114,7 +137,6 @@
&:focus-within {
outline: none;
border-color: var(--color-text-accent);
}
}

View File

@ -48,6 +48,14 @@ const SEARCH_TYPES = [
] as const;
type SearchType = (typeof SEARCH_TYPES)[number];
const SEARCH_TYPE_TO_PREFIX: Record<SearchType, string> = {
weapons: "w",
users: "u",
teams: "t",
organizations: "o",
tournaments: "to",
};
const STORAGE_KEY = "global-search-search-type";
function searchTypeIconPath(type: SearchType): string {
@ -188,6 +196,7 @@ function GlobalSearchContent({
React.useState<SelectedWeapon | null>(
resolveInitialWeapon(initialWeaponId, t),
);
const inputRef = React.useRef<HTMLInputElement>(null);
const listBoxRef = React.useRef<HTMLDivElement>(null);
const modifierKeyRef = React.useRef(false);
@ -266,6 +275,26 @@ function GlobalSearchContent({
setSelectedWeapon(null);
};
const handleQueryChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const value = e.target.value;
const separatorMatch = value.match(/^([a-zA-Z]+)\.(?=[a-zA-Z ]) ?/);
if (separatorMatch) {
const typedPrefix = separatorMatch[1];
const matchedType = SEARCH_TYPES.find(
(type) => SEARCH_TYPE_TO_PREFIX[type] === typedPrefix,
);
if (matchedType) {
setSearchType(matchedType);
setSelectedWeapon(null);
setQuery(value.slice(separatorMatch[0].length));
return;
}
}
setQuery(value);
};
const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
const currentResults = searchType === "weapons" ? weaponResults : results;
if (e.key === "ArrowDown" && currentResults.length > 0) {
@ -302,15 +331,20 @@ function GlobalSearchContent({
return (
<div onClickCapture={handleClickCapture}>
<Input
ref={inputRef}
className={styles.input}
placeholder={t("common:search.placeholder")}
value={query}
onChange={(e) => setQuery(e.target.value)}
onKeyDown={handleInputKeyDown}
icon={<Search className={styles.inputIcon} />}
/>
<div className={styles.inputContainer}>
<p className={styles.inputPrefix}>
{`${SEARCH_TYPE_TO_PREFIX[searchType]}.`}
</p>
<Input
ref={inputRef}
className={styles.input}
placeholder={t("common:search.placeholder")}
value={query}
onChange={handleQueryChange}
onKeyDown={handleInputKeyDown}
icon={<Search className={styles.inputIcon} />}
/>
</div>
<div className={styles.searchTypeContainer}>
<RadioGroup
value={searchType}