fix: offer clear search when a calendar search finds nothing

This commit is contained in:
Linus Rath
2026-10-28 10:21:14 +01:00
parent 82aeddfdaa
commit 4d736740a5
3 changed files with 22 additions and 1 deletions
@@ -352,6 +352,18 @@ describe('CalendarApp event search (CAL-16)', () => {
expect(await screen.findByText('search.no_results', {}, { timeout: 3000 })).toBeInTheDocument();
});
it('offers Clear search when nothing matches, back to the calendar with the cursor in the box', async () => {
renderApp();
const box = screen.getByRole('searchbox', { name: 'search.title' });
fireEvent.change(box, { target: { value: 'zzz' } });
await screen.findByText('search.no_results', {}, { timeout: 3000 });
const results = screen.getByTestId('calendar-search-results');
fireEvent.click(within(results).getByRole('button', { name: 'search.clear' }));
expect(box).toHaveValue('');
expect(document.activeElement).toBe(box);
await waitFor(() => expect(screen.queryByTestId('calendar-search-results')).toBeNull());
});
it('is in the command palette', () => {
render(<><CalendarApp /><PaletteGroups /></>);
const items = screen.getByTestId('palette').textContent ?? '';
+1
View File
@@ -1795,6 +1795,7 @@ export function CalendarApp({ linkSegments: routeSegments }: CalendarAppProps =
currentUserEmails={currentUserEmails}
onSelectEvent={handleSelectEvent}
onContextMenuEvent={handleContextMenuEvent}
onClearSearch={() => { setSearchQuery(""); searchInputRef.current?.focus(); }}
/>
);
}
+9 -1
View File
@@ -6,6 +6,7 @@ import { format } from "date-fns";
import { Search, X, MapPin, Repeat } from "@/components/icons";
import { Input } from "@/components/ui/input";
import { IconButton } from "@/components/ui/icon-button";
import { Button } from "@/components/ui/button";
import { EmptyState } from "@/components/ui/empty-state";
import { Spinner } from "@/components/ui/spinner";
import { cn } from "@/lib/utils";
@@ -88,11 +89,13 @@ interface CalendarSearchResultsProps {
currentUserEmails?: string[];
onSelectEvent: (event: CalendarEvent, anchorRect: DOMRect) => void;
onContextMenuEvent?: (e: React.MouseEvent, event: CalendarEvent) => void;
/** Empties the search box, back to the calendar (R9). */
onClearSearch?: () => void;
}
/** The events a calendar search found, upcoming first, then past ones. */
export function CalendarSearchResults({
query, results, calendars, timeFormat = "24h", currentUserEmails, onSelectEvent, onContextMenuEvent,
query, results, calendars, timeFormat = "24h", currentUserEmails, onSelectEvent, onContextMenuEvent, onClearSearch,
}: CalendarSearchResultsProps) {
const t = useTranslations("calendar");
const intlFormatter = useDisplayDateFormatter();
@@ -199,6 +202,11 @@ export function CalendarSearchResults({
icon={Search}
title={t("search.no_results", { query: query.trim() })}
description={t("search.no_results_hint")}
actions={onClearSearch && (
<Button size="sm" variant="outline" onClick={onClearSearch}>
{t("search.clear")}
</Button>
)}
/>
)}
{section("calendar-search-upcoming", t("search.upcoming"), upcoming)}