15
15
< div class ="container mx-auto px-6 py-4 ">
16
16
< nav class ="flex justify-between items-center ">
17
17
< div class ="text-xl font-bold "> AFS</ div >
18
-
18
+
19
19
<!-- Mobile Menu Button (Hamburger) -->
20
- < button class ="md:hidden flex items-center px-3 py-2 border rounded hover:bg-gray-100 "
21
- id ="mobile-menu-button "
22
- aria-label ="Toggle menu ">
20
+ < button class ="md:hidden flex items-center px-3 py-2 border rounded hover:bg-gray-100 "
21
+ id ="mobile-menu-button " aria-label ="Toggle menu ">
23
22
< svg class ="w-5 h-5 " fill ="none " stroke ="currentColor " viewBox ="0 0 24 24 ">
24
- < path strokeLinecap ="round "
25
- strokeLinejoin ="round "
26
- strokeWidth ="2 "
27
- d ="M4 6h16M4 12h16M4 18h16 "/>
23
+ < path strokeLinecap ="round " strokeLinejoin ="round " strokeWidth ="2 "
24
+ d ="M4 6h16M4 12h16M4 18h16 " />
28
25
</ svg >
29
26
</ button >
30
-
27
+
31
28
<!-- Desktop Navigation -->
32
29
< div class ="flex-none max-sm:hidden md:flex items-center gap-6 ">
33
30
< a href ="#features " class ="hover:text-gray-600 "> Features</ a >
34
31
< a href ="#installation " class ="hover:text-gray-600 "> Installation</ a >
35
32
< a href ="#usage " class ="hover:text-gray-600 "> Usage</ a >
36
- < a href ="https://github.com/misits/advanced-filter-system " class ="text-white flex items-center px-2 py-1.5 bg-black rounded-lg hover:bg-gray-800 transition-colors "> < svg class ="mr-2 flex items-center " xmlns ="http://www.w3.org/2000/svg " width ="20 " height ="20 " viewBox ="0 0 24 24 "> < path fill ="none " stroke ="currentColor " stroke-linecap ="round " stroke-linejoin ="round " stroke-width ="1.5 " d ="M6.517 17.113c.395.578 1.592 1.81 3.225 2.12M9.864 22C8.836 21.83 2 19.606 2 12.093C2 5.063 8.002 2 12 2c4 0 10 3.063 10 10.093c0 7.513-6.836 9.738-7.864 9.907c0 0-.21-3.417-.087-4.003c.122-.586-.294-1.528-.294-1.528c.971-.364 2.45-.884 2.945-2.282c.385-1.084.627-2.658-.45-4.138c0 0 .282-2.39-.25-2.484c-.533-.092-2.1.947-2.1.947c-.457-.13-1.476-.377-1.898-.333c-.423-.044-1.445.203-1.902.333c0 0-1.568-1.04-2.1-.947s-.25 2.484-.25 2.484c-1.077 1.48-.835 3.054-.45 4.138c.496 1.398 1.974 1.918 2.945 2.282c0 0-.416.942-.294 1.528S9.864 22 9.864 22 " color ="currentColor "/> </ svg > GitHub</ a >
33
+ < a href ="https://github.com/misits/advanced-filter-system "
34
+ class ="text-white flex items-center px-2 py-1.5 bg-black rounded-lg hover:bg-gray-800 transition-colors "> < svg
35
+ class ="mr-2 flex items-center " xmlns ="http://www.w3.org/2000/svg " width ="20 " height ="20 "
36
+ viewBox ="0 0 24 24 ">
37
+ < path fill ="none " stroke ="currentColor " stroke-linecap ="round " stroke-linejoin ="round "
38
+ stroke-width ="1.5 "
39
+ d ="M6.517 17.113c.395.578 1.592 1.81 3.225 2.12M9.864 22C8.836 21.83 2 19.606 2 12.093C2 5.063 8.002 2 12 2c4 0 10 3.063 10 10.093c0 7.513-6.836 9.738-7.864 9.907c0 0-.21-3.417-.087-4.003c.122-.586-.294-1.528-.294-1.528c.971-.364 2.45-.884 2.945-2.282c.385-1.084.627-2.658-.45-4.138c0 0 .282-2.39-.25-2.484c-.533-.092-2.1.947-2.1.947c-.457-.13-1.476-.377-1.898-.333c-.423-.044-1.445.203-1.902.333c0 0-1.568-1.04-2.1-.947s-.25 2.484-.25 2.484c-1.077 1.48-.835 3.054-.45 4.138c.496 1.398 1.974 1.918 2.945 2.282c0 0-.416.942-.294 1.528S9.864 22 9.864 22 "
40
+ color ="currentColor " />
41
+ </ svg > GitHub</ a >
37
42
</ div >
38
-
43
+
39
44
<!-- Mobile Navigation -->
40
- < div class ="hidden absolute top-full left-0 right-0 bg-white border-b border-gray-200 md:hidden "
41
- id ="mobile-menu ">
45
+ < div class ="hidden absolute top-full left-0 right-0 bg-white border-b border-gray-200 md:hidden "
46
+ id ="mobile-menu ">
42
47
< div class ="container mx-auto px-6 py-4 flex flex-col gap-4 ">
43
48
< a href ="#features " class ="hover:text-gray-600 py-2 "> Features</ a >
44
49
< a href ="#installation " class ="hover:text-gray-600 py-2 "> Installation</ a >
45
50
< a href ="#usage " class ="hover:text-gray-600 py-2 "> Usage</ a >
46
- < a href ="https://github.com/misits/advanced-filter-system " class ="hover:text-gray-600 py-2 "> GitHub</ a >
51
+ < a href ="https://github.com/misits/advanced-filter-system "
52
+ class ="hover:text-gray-600 py-2 "> GitHub</ a >
47
53
</ div >
48
54
</ div >
49
55
</ nav >
@@ -90,6 +96,18 @@ <h2 class="text-3xl font-bold mb-8">Live Demo</h2>
90
96
</ div >
91
97
</ button >
92
98
99
+ <!-- Add this toggle button -->
100
+ < button
101
+ class ="filter-type-toggle px-4 py-2 border border-gray-300 bg-white rounded-md hover:bg-gray-100 transition-colors flex items-center gap-2 ">
102
+ < span class ="type-text "> BUTTON</ span >
103
+ < div class ="type-indicator w-8 h-4 bg-gray-300 rounded-full relative ">
104
+ < div
105
+ class ="type-dot absolute w-3 h-3 bg-white rounded-full top-0.5 left-0.5 transition-transform ">
106
+ </ div >
107
+ </ div >
108
+ </ button >
109
+
110
+ < div class ="btn-filters ">
93
111
< button
94
112
class ="btn-filter px-4 py-2 border border-gray-300 bg-white rounded-md hover:bg-gray-100 transition-colors "
95
113
data-filter ="* "> All</ button >
@@ -102,10 +120,43 @@ <h2 class="text-3xl font-bold mb-8">Live Demo</h2>
102
120
< button
103
121
class ="btn-filter px-4 py-2 border border-gray-300 bg-white rounded-md hover:bg-gray-100 transition-colors "
104
122
data-filter ="category:food "> Food</ button >
123
+ </ div >
124
+ <!-- Dropdown Multi-select -->
125
+ < div class ="relative inline-block text-left select-filters ">
126
+ < button type ="button "
127
+ class ="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white hover:bg-gray-50 "
128
+ id ="dropdownMultiSelectButton ">
129
+ Categories < span class ="selected-filter-counter "> </ span >
130
+ < svg class ="-mr-1 ml-2 h-5 w-5 " xmlns ="http://www.w3.org/2000/svg " fill ="none "
131
+ viewBox ="0 0 24 24 " stroke ="currentColor " aria-hidden ="true ">
132
+ < path stroke-linecap ="round " stroke-linejoin ="round " stroke-width ="2 "
133
+ d ="M19 9l-7 7-7-7 " />
134
+ </ svg >
135
+ </ button >
136
+
137
+ < div id ="dropdownMultiSelect "
138
+ class ="hidden absolute left-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none z-[100] ">
139
+ < div class ="py-1 " role ="none ">
140
+ < label class ="flex items-center px-4 py-2 text-sm text-gray-700 ">
141
+ < input type ="checkbox " class ="btn-filter mr-2 " value ="category:tech " data-filter ="category:tech ">
142
+ Technology
143
+ </ label >
144
+ < label class ="flex items-center px-4 py-2 text-sm text-gray-700 ">
145
+ < input type ="checkbox " class ="btn-filter mr-2 " value ="category:fashion " data-filter ="category:fashion ">
146
+ Fashion
147
+ </ label >
148
+ < label class ="flex items-center px-4 py-2 text-sm text-gray-700 ">
149
+ < input type ="checkbox " class ="btn-filter mr-2 " value ="category:food " data-filter ="category:food ">
150
+ Food
151
+ </ label >
152
+ </ div >
153
+ </ div >
154
+ </ div >
105
155
106
156
< div class ="filter-counter text-gray-500 text-sm "> </ div >
107
157
</ div >
108
158
159
+
109
160
<!-- Grid of Items -->
110
161
< div id ="item-grid "> </ div >
111
162
</ div >
@@ -174,7 +225,7 @@ <h4 class="text-xl font-semibold mb-3">HTML Structure</h4>
174
225
</div>
175
226
</div></ code > </ pre >
176
227
</ div >
177
-
228
+
178
229
< div >
179
230
< h4 class ="text-xl font-semibold mb-3 "> Basic JavaScript Initialization</ h4 >
180
231
< pre class ="bg-gray-100 p-4 rounded-lg overflow-x-auto "> < code class ="language-javascript "> import { AFS } from 'advanced-filter-system';
@@ -198,7 +249,7 @@ <h4 class="text-xl font-semibold mb-3">Basic JavaScript Initialization</h4>
198
249
</ div >
199
250
</ div >
200
251
</ div >
201
-
252
+
202
253
<!-- Advanced Features -->
203
254
< div >
204
255
< h3 class ="text-2xl font-bold mb-4 "> Advanced Features</ h3 >
@@ -213,7 +264,7 @@ <h4 class="text-xl font-semibold mb-3">Filter Groups & Logic</h4>
213
264
filter.setGroupMode('AND'); // Must match all groups
214
265
filter.setLogic(true); // Alternative way (true = AND, false = OR)</ code > </ pre >
215
266
</ div >
216
-
267
+
217
268
< div >
218
269
< h4 class ="text-xl font-semibold mb-3 "> Sorting & Range Filtering</ h4 >
219
270
< pre class ="bg-gray-100 p-4 rounded-lg overflow-x-auto "> < code class ="language-javascript "> // Multi-criteria sorting
@@ -225,7 +276,7 @@ <h4 class="text-xl font-semibold mb-3">Sorting & Range Filtering</h4>
225
276
// Range filtering
226
277
filter.addRangeFilter('price', 0, 1000);</ code > </ pre >
227
278
</ div >
228
-
279
+
229
280
< div >
230
281
< h4 class ="text-xl font-semibold mb-3 "> State Management & Presets</ h4 >
231
282
< pre class ="bg-gray-100 p-4 rounded-lg overflow-x-auto "> < code class ="language-javascript "> // Save current state
@@ -238,7 +289,7 @@ <h4 class="text-xl font-semibold mb-3">State Management & Presets</h4>
238
289
filter.savePreset('myFilters');
239
290
filter.loadPreset('myFilters');</ code > </ pre >
240
291
</ div >
241
-
292
+
242
293
< div >
243
294
< h4 class ="text-xl font-semibold mb-3 "> Responsive Behavior</ h4 >
244
295
< pre class ="bg-gray-100 p-4 rounded-lg overflow-x-auto "> < code class ="language-javascript "> filter.setResponsiveOptions({
@@ -252,7 +303,7 @@ <h4 class="text-xl font-semibold mb-3">Responsive Behavior</h4>
252
303
}
253
304
});</ code > </ pre >
254
305
</ div >
255
-
306
+
256
307
< div >
257
308
< h4 class ="text-xl font-semibold mb-3 "> Events & Analytics</ h4 >
258
309
< pre class ="bg-gray-100 p-4 rounded-lg overflow-x-auto "> < code class ="language-javascript "> // Listen for filter changes
@@ -284,7 +335,7 @@ <h4 class="text-xl font-semibold mb-3">Events & Analytics</h4>
284
335
import { AFS } from './dist/AFS.esm.js' ;
285
336
import { createFeatureSection } from './js/features.js' ;
286
337
import { createItemGrid } from './js/item-grid.js' ;
287
-
338
+
288
339
// Use default features
289
340
createFeatureSection ( ) ;
290
341
// Use default items
@@ -302,11 +353,12 @@ <h4 class="text-xl font-semibold mb-3">Events & Analytics</h4>
302
353
filterMode : 'OR' // Set default to OR
303
354
} ) ;
304
355
305
- // Toggle button handler
356
+ // Toggle button handler for OR/AND logic
306
357
const toggleButton = document . querySelector ( '.filter-logic-toggle' ) ;
307
358
const toggleDot = toggleButton . querySelector ( '.toggle-dot' ) ;
308
359
const logicText = toggleButton . querySelector ( '.logic-text' ) ;
309
360
361
+
310
362
// Initialize with OR (isAnd = false)
311
363
let isAnd = false ;
312
364
updateToggleState ( isAnd ) ;
@@ -337,6 +389,63 @@ <h4 class="text-xl font-semibold mb-3">Events & Analytics</h4>
337
389
updateToggleState ( isAnd ) ;
338
390
} ) ;
339
391
392
+ // Toggle button handler for Button/Checkbox type
393
+ const typeButton = document . querySelector ( '.filter-type-toggle' ) ;
394
+ const typeDot = typeButton . querySelector ( '.type-dot' ) ;
395
+ const typeText = typeButton . querySelector ( '.type-text' ) ;
396
+ const btnFilters = document . querySelector ( '.btn-filters' ) ;
397
+ const selectFilters = document . querySelector ( '.select-filters' ) ;
398
+
399
+ // Initialize with Button (isCheckbox = false)
400
+ let isCheckbox = false ;
401
+ updateTypeState ( isCheckbox ) ;
402
+ toggleType ( ) ;
403
+
404
+ // Add click event listener
405
+ typeButton . addEventListener ( 'click' , ( ) => {
406
+ // Reset filter state to show all items & url
407
+ filter . clearAllFilters ( ) ;
408
+ isCheckbox = ! isCheckbox ;
409
+ updateTypeState ( isCheckbox ) ;
410
+ toggleType ( ) ;
411
+ } ) ;
412
+
413
+ function toggleType ( ) {
414
+ if ( isCheckbox ) {
415
+ btnFilters . classList . add ( 'hidden' ) ;
416
+ selectFilters . classList . remove ( 'hidden' ) ;
417
+ } else {
418
+ btnFilters . classList . remove ( 'hidden' ) ;
419
+ selectFilters . classList . add ( 'hidden' ) ;
420
+ }
421
+ }
422
+
423
+ // Function to update type visual state
424
+ function updateTypeState ( isCheckboxType ) {
425
+ if ( isCheckboxType ) {
426
+ typeDot . style . transform = 'translateX(16px)' ;
427
+ typeText . textContent = 'DROPDOWN' ;
428
+ typeButton . setAttribute ( 'aria-label' , 'Switch to BUTTON type' ) ;
429
+ } else {
430
+ typeDot . style . transform = 'translateX(0)' ;
431
+ typeText . textContent = 'BUTTON' ;
432
+ typeButton . setAttribute ( 'aria-label' , 'Switch to DROPDOWN type' ) ;
433
+ }
434
+ }
435
+
436
+ // Listen for type changes
437
+ filter . container . addEventListener ( 'filterTypeChange' , ( event ) => {
438
+ isCheckbox = event . detail . type === 'DROPDOWN' ;
439
+ updateTypeState ( isCheckbox ) ;
440
+ } ) ;
441
+
442
+ // Dropdown Multi-Select logic
443
+ document . getElementById ( 'dropdownMultiSelectButton' ) . addEventListener ( 'click' , function ( ) {
444
+ const dropdown = document . getElementById ( 'dropdownMultiSelect' ) ;
445
+ dropdown . classList . toggle ( 'hidden' ) ;
446
+ } ) ;
447
+
448
+
340
449
// Mobile menu functionality
341
450
const mobileMenuButton = document . getElementById ( 'mobile-menu-button' ) ;
342
451
const mobileMenu = document . getElementById ( 'mobile-menu' ) ;
0 commit comments