Shop filters
Filter widgets for the sidebar, allowing users to refine product listings based on various attributes like price, brand, size, etc.
Checkboxes
Brands
'use client'
import { useState } from 'react'
import Accordion from 'react-bootstrap/Accordion'
import Stack from 'react-bootstrap/Stack'
import FormCheck from 'react-bootstrap/FormCheck'
import SearchFilter from '@/components/search-filter'
import SimpleBar from 'simplebar-react'
import 'simplebar-react/dist/simplebar.min.css'
export default function ShopFiltersCheckboxesDemo() {
// Brands (checkboxes) array
const brands = [
{ name: 'Adidas', quantity: 425, selected: true },
{ name: 'Ann Taylor', quantity: 15 },
{ name: 'Armani', quantity: 18 },
{ name: 'Banana Republic', quantity: 103 },
{ name: 'Bilabong', quantity: 27, selected: true },
{ name: 'Birkenstock', quantity: 10 },
{ name: 'Calvin Klein', quantity: 365 },
{ name: 'Columbia', quantity: 508 },
{ name: 'Converse', quantity: 176 },
{ name: 'Dockers', quantity: 54 },
{ name: 'Fruit of the Loom', quantity: 739 },
{ name: 'Hanes', quantity: 92 },
{ name: 'Jimmy Choo', quantity: 17 },
{ name: "Levi's", quantity: 361 },
{ name: "Men's Wearhouse", quantity: 75 },
{ name: 'New Balance', quantity: 218 },
{ name: 'Nike', quantity: 810 },
]
const [filteredBrands, setFilteredBrands] = useState(brands)
// Function to filter brands based on the query
const filterBrands = (brand: (typeof brands)[number], query: string): boolean => {
return brand.name.toLowerCase().includes(query)
}
return (
<Accordion defaultActiveKey="0" style={{ maxWidth: 280 }}>
<Accordion.Item className="border-0" eventKey="0">
<Accordion.Button as="h3" className="h6 cursor-pointer p-0" id="headingBrands">
Brands
</Accordion.Button>
<Accordion.Body aria-labelledby="headingBrands">
<SearchFilter
items={brands}
filterFn={filterBrands}
onFilteredItems={setFilteredBrands}
placeholder="Search"
className="mb-3"
/>
<SimpleBar data-simplebar-auto-hide="false" style={{ height: 210 }}>
<Stack gap={2}>
{filteredBrands.length > 0 ? (
<>
{filteredBrands.map(({ name, quantity, selected }, index) => (
<FormCheck key={index} id={`brand-${index}`}>
<FormCheck.Input defaultChecked={selected} />
<FormCheck.Label className="text-body-emphasis">
{name}
<span className="fs-xs text-body-secondary ms-1">({quantity})</span>
</FormCheck.Label>
</FormCheck>
))}
</>
) : (
<p className="fs-sm text-body-secondary mb-0">Nothing found</p>
)}
</Stack>
</SimpleBar>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
Links
Categories
'use client'
import Link from 'next/link'
import Accordion from 'react-bootstrap/Accordion'
import Nav from 'react-bootstrap/Nav'
import SimpleBar from 'simplebar-react'
import 'simplebar-react/dist/simplebar.min.css'
export default function ShopFiltersLinksDemo() {
// Categories (links) array
const categories = [
{ title: 'Smartphones', quantity: 218, href: '#' },
{ title: 'Accessories', quantity: 372, href: '#' },
{ title: 'Tablets', quantity: 110, href: '#' },
{ title: 'Wearable Electronics', quantity: 142, href: '#' },
{ title: 'Computers & Laptops', quantity: 205, href: '#' },
{ title: 'Cameras, Photo & Video', quantity: 78, href: '#' },
{ title: 'TV, Video & Audio', quantity: 97, href: '#' },
{ title: 'Headphones', quantity: 121, href: '#' },
{ title: 'Video Games', quantity: 89, href: '#' },
{ title: 'Printers & Ink', quantity: 116, href: '#' },
{ title: 'Home music', quantity: 154, href: '#' },
]
return (
<Accordion defaultActiveKey="0" style={{ maxWidth: 280 }}>
<Accordion.Item className="border-0" eventKey="0">
<Accordion.Button as="h3" className="h6 cursor-pointer p-0" id="headingCategories">
Categories
</Accordion.Button>
<Accordion.Body aria-labelledby="headingCategories">
<SimpleBar data-simplebar-auto-hide="false" style={{ height: 190 }}>
<ul className="list-unstyled d-block m-0 mt-n2">
{categories.map(({ title, quantity, href }, index) => (
<Nav key={index} as="li" className="d-block pt-2 mt-1">
<Nav.Link as={Link} href={href} active={false} className="animate-underline fw-normal p-0 pe-4">
<span className="animate-target text-truncate me-3">{title}</span>
<span className="text-body-secondary fs-xs ms-auto">{quantity}</span>
</Nav.Link>
</Nav>
))}
</ul>
</SimpleBar>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
Range slider
Price
'use client'
import { useState } from 'react'
import Accordion from 'react-bootstrap/Accordion'
import Stack from 'react-bootstrap/Stack'
import FormControl from 'react-bootstrap/FormControl'
import RangeSlider from '@/components/forms/range-slider'
export default function ShopFiltersRangeSliderDemo() {
const [values, setValues] = useState([50, 150])
const handleInputChange = (index: number, value: string) => {
const numericValue = Math.max(0, Math.min(1000, Number(value)))
const updatedValues = [...values]
updatedValues[index] = numericValue
setValues(updatedValues)
}
return (
<Accordion defaultActiveKey="0" style={{ maxWidth: 280 }}>
<Accordion.Item className="border-0" eventKey="0">
<Accordion.Button as="h3" className="h6 cursor-pointer p-0" id="headingPrice">
Price
</Accordion.Button>
<Accordion.Body className="pt-4" aria-labelledby="headingPrice">
<RangeSlider
min={0}
max={200}
step={1}
value={values}
onValueChange={setValues}
minStepsBetweenThumbs={1}
tooltipPrefix="$"
className="pt-1 mt-0"
/>
<Stack direction="horizontal" gap={2}>
<div className="position-relative w-50">
<i className="ci-dollar-sign position-absolute top-50 start-0 translate-middle-y ms-3"/>
<FormControl
type="number"
min={0}
max={values[1] - 1}
value={values[0]}
onChange={(e) => handleInputChange(0, e.target.value)}
className="form-icon-start"
/>
</div>
<i className="ci-minus text-body-emphasis mx-2"/>
<div className="position-relative w-50">
<i className="ci-dollar-sign position-absolute top-50 start-0 translate-middle-y ms-3"/>
<FormControl
type="number"
min={values[0] + 1}
max={1000}
value={values[1]}
onChange={(e) => handleInputChange(1, e.target.value)}
className="form-icon-start"
/>
</div>
</Stack>
</Accordion.Body>
</Accordion.Item>
</Accordion>
)
}
Selected filters
Filter
import Stack from 'react-bootstrap/Stack'
import Button from 'react-bootstrap/Button'
export default function ShopFiltersSelectedDemo() {
return (
<div style={{ maxWidth: 280 }}>
<div className="d-flex align-items-center justify-content-between mb-3">
<h4 className="h6 mb-0">Filter</h4>
<Button
variant="secondary"
size="sm"
className="bg-transparent border-0 text-decoration-underline p-0 ms-2"
>
Clear all
</Button>
</div>
<Stack direction="horizontal" gap={2} className="flex-wrap">
{['Sale', 'Adidas', 'Bilabong', 'Size: XXS', '$40 - $150'].map((filter, index) => (
<Button key={index} variant="secondary" size="sm">
<i className="ci-close fs-sm ms-n1 me-1"/>
{filter}
</Button>
))}
</Stack>
</div>
)
}