2026-07-01 20:43:49 +02:00
|
|
|
/**
|
|
|
|
|
* Mail search bar — input for full-text mail search.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import React, { useState, useCallback } from 'react';
|
|
|
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
|
import { Input } from '@/components/ui/Input';
|
|
|
|
|
|
|
|
|
|
export interface MailSearchBarProps {
|
|
|
|
|
onSearch: (query: string) => void;
|
2026-07-19 17:41:39 +02:00
|
|
|
value?: string;
|
2026-07-01 20:43:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function MailSearchBar({ onSearch }: MailSearchBarProps) {
|
|
|
|
|
const { t } = useTranslation();
|
|
|
|
|
const [query, setQuery] = useState('');
|
|
|
|
|
|
|
|
|
|
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
|
|
|
|
|
setQuery(e.target.value);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleSubmit = useCallback((e: React.FormEvent) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
onSearch(query.trim());
|
|
|
|
|
}, [query, onSearch]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<form onSubmit={handleSubmit} className="relative" data-testid="mail-search-bar">
|
|
|
|
|
<Input
|
|
|
|
|
type="search"
|
|
|
|
|
value={query}
|
|
|
|
|
onChange={handleChange}
|
|
|
|
|
placeholder={t('mail.searchPlaceholder')}
|
|
|
|
|
aria-label={t('common.search')}
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
type="submit"
|
|
|
|
|
className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 rounded-md hover:bg-secondary-100 min-h-touch min-w-touch"
|
|
|
|
|
aria-label={t('common.search')}
|
|
|
|
|
>
|
|
|
|
|
<svg className="w-4 h-4 text-secondary-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
|
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</form>
|
|
|
|
|
);
|
|
|
|
|
}
|