Bromeo777 commited on
Commit
502f8d0
·
unverified ·
1 Parent(s): 9036dac

Create index.tsx

Browse files
src/components/molecules/FilterChips/index.tsx ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+ import { X } from "lucide-react";
5
+ import { Badge } from "@/components/atoms/Badge";
6
+ import { Icon } from "@/components/atoms/Icon";
7
+ import { cn } from "@/lib/utils";
8
+
9
+ export interface FilterOption {
10
+ label: string;
11
+ value: string;
12
+ count?: number;
13
+ }
14
+
15
+ interface FilterChipsProps {
16
+ options: FilterOption[];
17
+ selectedValues: string[];
18
+ onToggle: (value: string) => void;
19
+ onClearAll?: () => void;
20
+ className?: string;
21
+ }
22
+
23
+ /**
24
+ * FilterChips Molecule
25
+ * Displays a horizontal list of interactive badges for search filtering.
26
+ * Uses the Badge atom for consistent academic styling.
27
+ */
28
+ export function FilterChips({
29
+ options,
30
+ selectedValues,
31
+ onToggle,
32
+ onClearAll,
33
+ className,
34
+ }: FilterChipsProps) {
35
+ return (
36
+ <div className={cn("flex flex-wrap items-center gap-2", className)}>
37
+ {options.map((option) => {
38
+ const isSelected = selectedValues.includes(option.value);
39
+
40
+ return (
41
+ <button
42
+ key={option.value}
43
+ onClick={() => onToggle(option.value)}
44
+ className="focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 rounded-full"
45
+ aria-pressed={isSelected}
46
+ >
47
+ <Badge
48
+ variant={isSelected ? "default" : "secondary"}
49
+ className={cn(
50
+ "cursor-pointer px-3 py-1 text-[11px] transition-all",
51
+ isSelected
52
+ ? "bg-primary text-primary-foreground shadow-sm"
53
+ : "hover:bg-muted-foreground/10"
54
+ )}
55
+ >
56
+ {option.label}
57
+ {option.count !== undefined && (
58
+ <span className={cn(
59
+ "ml-1.5 opacity-60 font-normal",
60
+ isSelected ? "text-primary-foreground" : "text-muted-foreground"
61
+ )}>
62
+ ({option.count})
63
+ </span>
64
+ )}
65
+ {isSelected && (
66
+ <Icon icon={X} size={10} className="ml-1.5 opacity-80" />
67
+ )}
68
+ </Badge>
69
+ </button>
70
+ );
71
+ })}
72
+
73
+ {selectedValues.length > 0 && onClearAll && (
74
+ <button
75
+ onClick={onClearAll}
76
+ className="ml-2 text-[11px] font-medium text-muted-foreground hover:text-primary transition-colors underline-offset-4 hover:underline"
77
+ >
78
+ Clear all
79
+ </button>
80
+ )}
81
+ </div>
82
+ );
83
+ }