feat: selective history removal

This commit is contained in:
Moyasee
2025-11-15 21:10:33 +02:00
parent 9979e92d8f
commit 093a9f251e
4 changed files with 63 additions and 3 deletions

View File

@@ -97,6 +97,7 @@
"recent_searches": "Recent Searches",
"suggestions": "Suggestions",
"clear_history": "Clear history",
"remove_from_history": "Remove from history",
"loading": "Loading...",
"no_results": "No results",
"home": "Home",

View File

@@ -62,7 +62,8 @@ export function Header() {
const { t } = useTranslation("header");
const { addToHistory, clearHistory, getRecentHistory } = useSearchHistory();
const { addToHistory, removeFromHistory, clearHistory, getRecentHistory } =
useSearchHistory();
const { suggestions, isLoading: isLoadingSuggestions } = useSearchSuggestions(
searchValue,
@@ -176,6 +177,10 @@ export function Header() {
setActiveIndex(-1);
};
const handleRemoveHistoryItem = (query: string) => {
removeFromHistory(query);
};
const handleClearHistory = () => {
clearHistory();
};
@@ -326,6 +331,7 @@ export function Header() {
isLoadingSuggestions={isLoadingSuggestions}
onSelectHistory={handleSelectHistory}
onSelectSuggestion={handleSelectSuggestion}
onRemoveHistoryItem={handleRemoveHistoryItem}
onClearHistory={handleClearHistory}
onClose={handleCloseDropdown}
activeIndex={activeIndex}

View File

@@ -57,6 +57,37 @@
margin: 0;
}
&__item-container {
position: relative;
display: flex;
align-items: center;
&:hover .search-dropdown__item-remove {
opacity: 1;
}
}
&__item-remove {
position: absolute;
right: 8px;
top: 50%;
transform: translateY(-50%);
color: globals.$muted-color;
padding: 4px;
border-radius: 4px;
opacity: 0;
transition: all ease 0.15s;
display: flex;
align-items: center;
justify-content: center;
background-color: transparent;
&:hover {
color: #ff5555;
background-color: rgba(255, 85, 85, 0.1);
}
}
&__item {
width: 100%;
display: flex;

View File

@@ -1,6 +1,11 @@
import { useEffect, useRef, useCallback, useState } from "react";
import { createPortal } from "react-dom";
import { ClockIcon, SearchIcon, TrashIcon } from "@primer/octicons-react";
import {
ClockIcon,
SearchIcon,
TrashIcon,
XIcon,
} from "@primer/octicons-react";
import cn from "classnames";
import { useTranslation } from "react-i18next";
import type { SearchHistoryEntry } from "@renderer/hooks/use-search-history";
@@ -16,6 +21,7 @@ export interface SearchDropdownProps {
isLoadingSuggestions: boolean;
onSelectHistory: (query: string) => void;
onSelectSuggestion: (suggestion: SearchSuggestion) => void;
onRemoveHistoryItem: (query: string) => void;
onClearHistory: () => void;
onClose: () => void;
activeIndex: number;
@@ -31,6 +37,7 @@ export function SearchDropdown({
isLoadingSuggestions,
onSelectHistory,
onSelectSuggestion,
onRemoveHistoryItem,
onClearHistory,
onClose,
activeIndex,
@@ -146,7 +153,10 @@ export function SearchDropdown({
</div>
<ul className="search-dropdown__list">
{historyItems.map((item, index) => (
<li key={`history-${item.query}-${item.timestamp}`}>
<li
key={`history-${item.query}-${item.timestamp}`}
className="search-dropdown__item-container"
>
<button
type="button"
className={cn("search-dropdown__item", {
@@ -161,6 +171,18 @@ export function SearchDropdown({
{item.query}
</span>
</button>
<button
type="button"
className="search-dropdown__item-remove"
onMouseDown={(e) => e.preventDefault()}
onClick={(e) => {
e.stopPropagation();
onRemoveHistoryItem(item.query);
}}
title={t("remove_from_history")}
>
<XIcon size={12} />
</button>
</li>
))}
</ul>