feat: add clear X button to all search inputs

This commit is contained in:
Christian Vidal Wolf
2026-04-10 12:39:31 +02:00
parent dbcd6d622f
commit be584600fc
8 changed files with 84 additions and 19 deletions
+11 -3
View File
@@ -1,6 +1,6 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { ExcelRow, COLUMNS } from '../types'; import { ExcelRow, COLUMNS } from '../types';
import { Search, Filter, Edit2, ChevronDown, ChevronUp, Info, Package, X as XIcon } from 'lucide-react'; import { Search, Filter, Edit2, ChevronDown, ChevronUp, Info, Package, X } from 'lucide-react';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
import { ColumnFilterPopover } from './ColumnFilterPopover'; import { ColumnFilterPopover } from './ColumnFilterPopover';
@@ -185,8 +185,16 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp
placeholder="Search SKU or Name..." placeholder="Search SKU or Name..."
value={search} value={search}
onChange={e => { setSearch(e.target.value); setPage(1); }} onChange={e => { setSearch(e.target.value); setPage(1); }}
className="w-full pl-9 pr-4 py-2 bg-slate-900/50 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500" className="w-full pl-9 pr-10 py-2 bg-slate-900/50 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500"
/> />
{search && (
<button
onClick={() => { setSearch(''); setPage(1); }}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
{(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && ( {(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && (
<button <button
@@ -196,7 +204,7 @@ export function ArticleDetails({ data, onEdit, rowStatuses }: ArticleDetailsProp
}} }}
className="flex items-center gap-2 px-4 py-2 bg-red-600/10 text-red-400 hover:bg-red-600 hover:text-white rounded-md text-sm font-medium transition-colors border border-red-600/20" className="flex items-center gap-2 px-4 py-2 bg-red-600/10 text-red-400 hover:bg-red-600 hover:text-white rounded-md text-sm font-medium transition-colors border border-red-600/20"
> >
<XIcon className="w-4 h-4" /> <X className="w-4 h-4" />
Clear All Column Filters Clear All Column Filters
</button> </button>
)} )}
+10 -2
View File
@@ -1,5 +1,5 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { Search, Check } from 'lucide-react'; import { Search, Check, X } from 'lucide-react';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
interface ColumnFilterPopoverProps { interface ColumnFilterPopoverProps {
@@ -50,9 +50,17 @@ export function ColumnFilterPopover({
placeholder="Filter values..." placeholder="Filter values..."
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className="w-full bg-slate-900 border border-slate-700 rounded p-1.5 pl-8 text-xs text-white focus:outline-none focus:border-blue-500" className="w-full bg-slate-900 border border-slate-700 rounded p-1.5 pl-8 pr-7 text-xs text-white focus:outline-none focus:border-blue-500"
autoFocus autoFocus
/> />
{search && (
<button
onClick={() => setSearch('')}
className="absolute right-2 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-3 h-3" />
</button>
)}
</div> </div>
<div className="max-h-48 overflow-y-auto space-y-0.5 pr-1 custom-scrollbar"> <div className="max-h-48 overflow-y-auto space-y-0.5 pr-1 custom-scrollbar">
+11 -3
View File
@@ -1,6 +1,6 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { ExcelRow, COLUMNS } from '../types'; import { ExcelRow, COLUMNS } from '../types';
import { AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, Edit2, Package, Boxes, Scale, Loader2, RefreshCw, Layers, Link2, Search, Filter, X as XIcon, Undo2 } from 'lucide-react'; import { AlertTriangle, CheckCircle2, ChevronDown, ChevronRight, Edit2, Package, Boxes, Scale, Loader2, RefreshCw, Layers, Link2, Search, Filter, X, Undo2 } from 'lucide-react';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
import { ConfirmModal } from './ConfirmModal'; import { ConfirmModal } from './ConfirmModal';
import { ColumnFilterPopover } from './ColumnFilterPopover'; import { ColumnFilterPopover } from './ColumnFilterPopover';
@@ -307,8 +307,16 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat
placeholder="Search SKU or Name in groups..." placeholder="Search SKU or Name in groups..."
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className="w-full pl-9 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500" className="w-full pl-9 pr-10 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500"
/> />
{search && (
<button
onClick={() => setSearch('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -368,7 +376,7 @@ export function DimensionsView({ data, headers, onEdit, onSaveRow, onCaptureStat
className="p-2 text-red-400 hover:text-red-300 transition-colors" className="p-2 text-red-400 hover:text-red-300 transition-colors"
title="Clear all filters" title="Clear all filters"
> >
<XIcon className="w-5 h-5" /> <X className="w-5 h-5" />
</button> </button>
)} )}
</div> </div>
+10 -2
View File
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { History, RotateCcw, ChevronDown, ChevronRight, User, Calendar, Tag } from 'lucide-react'; import { History, RotateCcw, ChevronDown, ChevronRight, User, Calendar, Tag, Search, X } from 'lucide-react';
import { getHistory, deleteHistoryEntry, HistoryEntry } from '../lib/supabase'; import { getHistory, deleteHistoryEntry, HistoryEntry } from '../lib/supabase';
import { ExcelRow, COLUMNS } from '../types'; import { ExcelRow, COLUMNS } from '../types';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
@@ -102,8 +102,16 @@ export function HistoryView({ headers, data, onRevert, sessionToken }: HistoryVi
placeholder="Search history..." placeholder="Search history..."
value={search} value={search}
onChange={(e) => setSearch(e.target.value)} onChange={(e) => setSearch(e.target.value)}
className="pl-10 pr-4 py-2 bg-slate-800 border border-slate-700 rounded-md text-sm text-slate-200 focus:outline-none focus:border-blue-500 transition-colors w-64" className="pl-10 pr-10 py-2 bg-slate-800 border border-slate-700 rounded-md text-sm text-slate-200 focus:outline-none focus:border-blue-500 transition-colors w-64"
/> />
{search && (
<button
onClick={() => setSearch('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
<button <button
onClick={loadHistory} onClick={loadHistory}
+11 -3
View File
@@ -1,6 +1,6 @@
import React, { useState, useMemo } from 'react'; import React, { useState, useMemo } from 'react';
import { ExcelRow } from '../types'; import { ExcelRow } from '../types';
import { Search, Filter, ChevronDown, ChevronUp, X as XIcon } from 'lucide-react'; import { Search, Filter, ChevronDown, ChevronUp, X } from 'lucide-react';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
import { ColumnFilterPopover } from './ColumnFilterPopover'; import { ColumnFilterPopover } from './ColumnFilterPopover';
@@ -170,8 +170,16 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
placeholder="Search all columns..." placeholder="Search all columns..."
value={search} value={search}
onChange={e => { setSearch(e.target.value); setPage(1); }} onChange={e => { setSearch(e.target.value); setPage(1); }}
className="w-full pl-9 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all font-medium" className="w-full pl-9 pr-10 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all font-medium"
/> />
{search && (
<button
onClick={() => { setSearch(''); setPage(1); }}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
{(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && ( {(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && (
<button <button
@@ -181,7 +189,7 @@ export function MatrixView({ data, headers, rowStatuses }: MatrixViewProps) {
}} }}
className="flex items-center gap-2 px-4 py-2 bg-red-600/10 text-red-400 hover:bg-red-600 hover:text-white rounded-md text-sm font-medium transition-colors border border-red-600/20" className="flex items-center gap-2 px-4 py-2 bg-red-600/10 text-red-400 hover:bg-red-600 hover:text-white rounded-md text-sm font-medium transition-colors border border-red-600/20"
> >
<XIcon className="w-4 h-4" /> <X className="w-4 h-4" />
Clear All Column Filters Clear All Column Filters
</button> </button>
)} )}
+10 -2
View File
@@ -1,6 +1,6 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ExcelRow, COLUMNS } from '../types'; import { ExcelRow, COLUMNS } from '../types';
import { Clock, Undo2, Package, Box, DollarSign, FileText, Search, Filter } from 'lucide-react'; import { Clock, Undo2, Package, Box, DollarSign, FileText, Search, Filter, X } from 'lucide-react';
import { cn } from '../lib/utils'; import { cn } from '../lib/utils';
interface PendingValidationViewProps { interface PendingValidationViewProps {
@@ -81,8 +81,16 @@ export function PendingValidationView({ data, pendingRows, rowStatuses, onRevert
placeholder="Search by article no or name..." placeholder="Search by article no or name..."
value={search} value={search}
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className="bg-slate-800 border border-slate-700 rounded-md pl-9 pr-3 py-2 text-sm text-white placeholder:text-slate-500 focus:outline-none focus:border-blue-500 w-64" className="bg-slate-800 border border-slate-700 rounded-md pl-9 pr-10 py-2 text-sm text-white placeholder:text-slate-500 focus:outline-none focus:border-blue-500 w-64"
/> />
{search && (
<button
onClick={() => setSearch('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
</div> </div>
</div> </div>
+12 -3
View File
@@ -282,9 +282,18 @@ export function PricingView({ data, headers, onSaveRow, onCaptureState, onEdit,
onChange={e => setSearch(e.target.value)} onChange={e => setSearch(e.target.value)}
className="w-full pl-4 pr-10 py-2 bg-slate-800 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all" className="w-full pl-4 pr-10 py-2 bg-slate-800 border border-slate-700 rounded-lg text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500 transition-all"
/> />
<div className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-500"> {search ? (
<Package className="w-4 h-4" /> <button
</div> onClick={() => setSearch('')}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
) : (
<div className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-500">
<Package className="w-4 h-4" />
</div>
)}
</div> </div>
{/* ── Filter tabs ── */} {/* ── Filter tabs ── */}
+9 -1
View File
@@ -246,8 +246,16 @@ export function ProductDescriptions({ data, headers, asinColumnIndex, onEdit, ro
placeholder="Search Article Name or No..." placeholder="Search Article Name or No..."
value={search} value={search}
onChange={e => { setSearch(e.target.value); setPage(1); }} onChange={e => { setSearch(e.target.value); setPage(1); }}
className="w-full pl-9 pr-4 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500" className="w-full pl-9 pr-10 py-2 bg-slate-900 border border-slate-700 rounded-md text-sm text-white focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500"
/> />
{search && (
<button
onClick={() => { setSearch(''); setPage(1); }}
className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-white"
>
<X className="w-4 h-4" />
</button>
)}
</div> </div>
{(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && ( {(Object.values(columnFilters) as string[][]).some(v => v.length > 0) && (
<button <button