feat(mobile): add FilterChips primitive (horizontal chip row with Add-filter trigger)
This commit is contained in:
67
src/components/shared/filter-chips.tsx
Normal file
67
src/components/shared/filter-chips.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
'use client';
|
||||
|
||||
import { X, Filter } from 'lucide-react';
|
||||
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
export type ActiveFilter = {
|
||||
id: string;
|
||||
label: string;
|
||||
/** Compact value rendered on the chip after the label (e.g. ": Active"). */
|
||||
value?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Horizontal chip row for active filters, with an "Add filter" trigger that
|
||||
* the caller wires to a `<Drawer>`. Active chips are dismissable via the X
|
||||
* button. Scrolls horizontally on mobile when there are many filters.
|
||||
*/
|
||||
export function FilterChips({
|
||||
active,
|
||||
onRemove,
|
||||
onAddClick,
|
||||
className,
|
||||
}: {
|
||||
active: ActiveFilter[];
|
||||
onRemove: (id: string) => void;
|
||||
onAddClick: () => void;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex items-center gap-2 overflow-x-auto -mx-3 px-3 sm:mx-0 sm:px-0 sm:flex-wrap sm:overflow-visible',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onAddClick}
|
||||
className="shrink-0 inline-flex items-center gap-1.5 rounded-full border border-input bg-background px-3 h-9 text-sm font-medium text-foreground hover:bg-accent"
|
||||
>
|
||||
<Filter className="size-4" aria-hidden />
|
||||
Add filter
|
||||
</button>
|
||||
|
||||
{active.map((filter) => (
|
||||
<span
|
||||
key={filter.id}
|
||||
className="shrink-0 inline-flex items-center gap-1 rounded-full bg-secondary text-secondary-foreground px-3 h-9 text-sm font-medium"
|
||||
>
|
||||
<span>
|
||||
{filter.label}
|
||||
{filter.value ? `: ${filter.value}` : ''}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onRemove(filter.id)}
|
||||
aria-label={`Remove ${filter.label} filter`}
|
||||
className="-mr-1 inline-flex size-6 items-center justify-center rounded-full hover:bg-secondary-foreground/10"
|
||||
>
|
||||
<X className="size-3.5" aria-hidden />
|
||||
</button>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user