11'use client' ;
22
33import React from 'react' ;
4- import { Button } from '../ui/button' ;
4+ // import { Button } from '../ui/button';
55import type { Category } from '../../../types/entries' ;
66import { getContrastColor } from '../../../utils/colorUtils' ;
77
@@ -23,101 +23,124 @@ const FilterBar: React.FC<FilterBarProps> = ({
2323 const topCategories = rootCategory . children ?? [ ] ;
2424
2525 return (
26- < div className = 'flex flex-col gap-2' >
27- { /* Breadcrumbs Row */ }
28- < div className = 'flex items-center gap-2 px-4 py-2 border-b bg-gray-50 flex-wrap' >
29- < span
30- onClick = { ( ) => onBreadcrumbClick ( - 1 ) }
31- className = 'cursor-pointer text-blue-600 hover:underline'
32- >
33- All
34- </ span >
35- { path . map ( ( cat , index ) => (
36- < React . Fragment key = { cat . id } >
37- < span className = 'text-gray-500' > /</ span >
38- < span
39- onClick = { ( ) => onBreadcrumbClick ( index ) }
40- className = 'cursor-pointer text-blue-600 hover:underline'
41- >
42- { cat . displayName }
43- </ span >
44- </ React . Fragment >
45- ) ) }
46- </ div >
26+ < div className = 'flex flex-col border rounded-md ' >
27+ { /* Header with integrated filters label and breadcrumbs */ }
28+ < div className = 'px-3 py-1.5 bg-gray-100 border-b flex items-center' >
29+ < div className = 'flex items-center flex-wrap' >
30+ < h3 className = 'text-xs font-medium text-gray-700 mr-1' > Filters:</ h3 >
31+
32+ < span
33+ onClick = { ( ) => onBreadcrumbClick ( - 1 ) }
34+ className = { `cursor-pointer px-2 py-0.5 rounded text-xs font-medium transition-colors
35+ ${
36+ path . length === 0
37+ ? 'bg-brand-pink text-white'
38+ : 'text-gray-600 hover:bg-gray-100'
39+ } `}
40+ >
41+ All
42+ </ span >
43+
44+ { path . map ( ( cat , index ) => (
45+ < React . Fragment key = { cat . id } >
46+ < svg
47+ width = '12'
48+ height = '12'
49+ viewBox = '0 0 24 24'
50+ fill = 'none'
51+ xmlns = 'http://www.w3.org/2000/svg'
52+ className = 'text-gray-400 mx-0.5'
53+ >
54+ < path
55+ d = 'M9 6L15 12L9 18'
56+ stroke = 'currentColor'
57+ strokeWidth = '2'
58+ strokeLinecap = 'round'
59+ strokeLinejoin = 'round'
60+ />
61+ </ svg >
4762
48- { /* Filter Bar Row using grid layout */ }
49- < div
50- className = '
51- grid
52- w-full
53- gap-4
54- px-4
55- py-2
56- border-b
57- bg-gray-100
58- grid-cols-[repeat(auto-fill,minmax(150px,1fr))]
59- '
60- >
61- { /* CASE 1: No filter selected → show top-level categories */ }
62- { ! currentCategory &&
63- topCategories . map ( ( cat ) => (
64- < Button
65- key = { cat . id }
66- onClick = { ( ) => onSelectCategory ( cat ) }
67- variant = 'outline'
68- className = 'flex items-center gap-1 text-sm'
69- style = { {
70- backgroundColor : cat . color ,
71- color : getContrastColor ( cat . color ) ,
72- borderColor : cat . color ,
73- } }
74- >
75- < span > { cat . icon } </ span >
76- < span > { cat . displayName } </ span >
77- </ Button >
63+ < span
64+ onClick = { ( ) => onBreadcrumbClick ( index ) }
65+ className = 'cursor-pointer px-1.5 py-0.5 rounded text-xs font-medium transition-colors flex items-center'
66+ style = { {
67+ backgroundColor :
68+ index === path . length - 1 ? cat . color : undefined ,
69+ color :
70+ index === path . length - 1
71+ ? getContrastColor ( cat . color )
72+ : 'inherit' ,
73+ } }
74+ >
75+ { cat . displayName }
76+ </ span >
77+ </ React . Fragment >
7878 ) ) }
79+ </ div >
80+ </ div >
7981
80- { /* CASE 2: A filter is selected and it has children */ }
81- { currentCategory &&
82- currentCategory . children &&
83- currentCategory . children . length > 0 &&
84- currentCategory . children . map ( ( child ) => {
85- // If there's exactly one child at this level, add col-span-full so it fills the row.
86- const spanClass =
87- currentCategory . children ?. length === 1 ? 'col-span-full' : '' ;
88- return (
89- < Button
90- key = { child . id }
91- onClick = { ( ) => onSelectCategory ( child ) }
92- variant = 'outline'
93- className = { `flex items-center gap-1 text-sm ${ spanClass } ` }
82+ { /* Categories Grid/Flex Layout */ }
83+ < div className = 'bg-gray-50 px-3 py-1 flex-1' >
84+ { /* CASE 1: No filter selected → show top-level categories in a grid */ }
85+ { ! currentCategory && (
86+ < div className = 'grid grid-cols-3 gap-1.5 sm:grid-cols-4 md:grid-cols-5 justify-items-center' >
87+ { topCategories . map ( ( cat ) => (
88+ < button
89+ key = { cat . id }
90+ onClick = { ( ) => onSelectCategory ( cat ) }
91+ className = 'flex flex-col items-center justify-center gap-1 p-1.5 rounded hover:bg-gray-100 transition-colors text-center w-full max-w-[90px]'
9492 style = { {
95- backgroundColor : child . color ,
96- color : getContrastColor ( child . color ) ,
97- borderColor : child . color ,
93+ color : getContrastColor ( cat . color ) ,
9894 } }
9995 >
100- < span > { child . icon } </ span >
101- < span > { child . displayName } </ span >
102- </ Button >
103- ) ;
104- } ) }
96+ < div
97+ className = 'w-6 h-6 flex items-center justify-center rounded-sm'
98+ style = { { backgroundColor : cat . color } }
99+ >
100+ { cat . icon || '•' }
101+ </ div >
102+ < span className = 'text-xs font-medium text-gray-700 line-clamp-1' >
103+ { cat . displayName }
104+ </ span >
105+ </ button >
106+ ) ) }
107+ </ div >
108+ ) }
109+
110+ { /* CASE 2: A filter is selected → show its children in a grid */ }
111+ { currentCategory &&
112+ currentCategory . children &&
113+ currentCategory . children . length > 0 && (
114+ < div className = 'grid grid-cols-3 gap-1.5 sm:grid-cols-4 md:grid-cols-5 justify-items-center' >
115+ { currentCategory . children . map ( ( child ) => (
116+ < button
117+ key = { child . id }
118+ onClick = { ( ) => onSelectCategory ( child ) }
119+ className = 'flex flex-col items-center justify-center gap-1 p-1.5 rounded hover:bg-gray-100 transition-colors text-center w-full max-w-[90px]'
120+ style = { {
121+ color : getContrastColor ( child . color ) ,
122+ } }
123+ >
124+ < div
125+ className = 'w-6 h-6 flex items-center justify-center rounded-sm'
126+ style = { { backgroundColor : child . color } }
127+ >
128+ { child . icon || '•' }
129+ </ div >
130+ < span className = 'text-xs font-medium text-gray-700 line-clamp-1' >
131+ { child . displayName }
132+ </ span >
133+ </ button >
134+ ) ) }
135+ </ div >
136+ ) }
105137
106- { /* CASE 3: A filter is selected and it's a leaf (no children) */ }
107- { /* CASE 3: A filter is selected and it's a leaf (no children) */ }
138+ { /* CASE 3: A filter is selected but has no children */ }
108139 { currentCategory &&
109140 ( ! currentCategory . children ||
110141 currentCategory . children . length === 0 ) && (
111- < div
112- className = 'flex items-center gap-1 text-sm col-span-full cursor-default select-none rounded-lg shadow-md px-4 py-2'
113- style = { {
114- backgroundColor : currentCategory . color ,
115- color : getContrastColor ( currentCategory . color ) ,
116- border : `1px solid ${ currentCategory . color } ` ,
117- } }
118- >
119- < span > { currentCategory . icon } </ span >
120- < span > { currentCategory . displayName } </ span >
142+ < div className = 'flex items-center justify-center py-1 text-xs text-gray-500' >
143+ No subcategories
121144 </ div >
122145 ) }
123146 </ div >
0 commit comments