Filters 1
Filters2 ColumnsText Align LeftFilter LeftButtonsFilters

Code
relume-filters1.tsx
"use client";
import { useState, useEffect } from "react";
import { useMediaQuery } from "@/hooks/use-media-query";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import {
Sheet,
SheetClose,
SheetContent,
SheetFooter,
SheetHeader,
SheetOverlay,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet";
import { Slider } from "@/components/ui/slider";
import { Switch } from "@/components/ui/switch";
import { Cancel, FilterList, KeyboardArrowDown, Search } from "relume-icons";
import { Badge } from "@/components/ui/badge";
export const Filters1 = () => {
const isTablet = useMediaQuery("(max-width: 991px)");
const [key, setKey] = useState(0);
const handleClearAll = () => {
setKey((prev) => prev + 1);
};
return (
<section className="px-[5%] py-16 md:py-24 lg:py-28">
<div className="container">
<div className="mb-12 w-full max-w-lg md:mb-18 lg:mb-20">
<h1 className="mb-5 text-h2 font-bold md:mb-6">Collection</h1>
<p className="text-medium">Lorem ipsum dolor sit amet.</p>
</div>
<div className="grid grid-cols-1 gap-10 md:gap-x-16 md:gap-y-12 lg:grid-cols-[max-content_1fr]">
{isTablet ? (
<div className="lg:hidden">
<Sheet>
<SheetTrigger asChild>
<Button className="w-full gap-2" variant="secondary">
<FilterList className="size-6 text-scheme-text" />
<span className="underline">Filters</span>
</Button>
</SheetTrigger>
<SheetOverlay />
<SheetContent side="bottom" className="h-screen w-full px-[5%] pt-12">
<SheetClose className="absolute top-6 right-6" />
<SheetHeader className="mb-6 space-y-0 text-left">
<SheetTitle className="mb-6 text-h2 font-bold">Filters</SheetTitle>
<p className="text-regular">Showing 0 of 100</p>
</SheetHeader>
<div className="mb-6">
{["All", "Category One", "Category Two", "Category Three"].map(
(category, index) => (
<a key={index} href="#" className="block py-2 underline">
{category}
</a>
),
)}
</div>
<div className="mt-6">
<FilterSections key={key} onClearAll={handleClearAll} />
</div>
<SheetFooter className="sticky bottom-0 z-50 mt-12">
<div className="-mx-[5%] flex h-auto w-screen items-center justify-between border-t border-scheme-border bg-white px-[5%] py-2 md:py-3">
<Button variant="link" size="link" onClick={handleClearAll}>
Clear all
</Button>
<Button>Apply</Button>
</div>
</SheetFooter>
</SheetContent>
</Sheet>
</div>
) : (
<div className="hidden w-[18rem] lg:block">
<div className="mb-6">
<div className="mb-6 flex items-center justify-between">
<h2 className="text-h5 font-bold">Filters</h2>
<Button variant="link" size="link" onClick={handleClearAll}>
Clear all
</Button>
</div>
<p className="text-small">Showing 0 of 100</p>
</div>
<div className="mb-6">
{["All", "Category One", "Category Two", "Category Three"].map(
(category, index) => (
<a key={index} href="#" className="block py-2 underline">
{category}
</a>
),
)}
</div>
<FilterSections key={key} onClearAll={handleClearAll} />
</div>
)}
<div>
<div className="mb-6 flex items-center justify-between gap-8">
<div className="flex flex-wrap gap-2">
<Badge className="flex items-center py-2 pr-3 pl-4 text-regular font-normal">
<span>Tag</span>
<Cancel className="ml-2 size-5.5 flex-none cursor-pointer" />
</Badge>
</div>
<DropdownMenu>
<DropdownMenuTrigger className="-mr-2 flex items-center gap-2">
Sort by
<KeyboardArrowDown className="text-scheme-text" />
</DropdownMenuTrigger>
<DropdownMenuContent>
{[
"Most Popular",
"Most Recent",
"Name: A to Z",
"Name: Z to A",
"Price: Low to High",
"Price: High to Low",
].map((item, index) => (
<DropdownMenuItem key={index}>{item}</DropdownMenuItem>
))}
</DropdownMenuContent>
</DropdownMenu>
</div>
<div className="min-h-[200vh] w-full border-2 border-dashed border-neutral-darkest/15" />
<div className="border border-scheme-border p-[2.9rem] text-center">
<h6 className="mb-2 text-h6 font-bold">No results found.</h6>
<p>There are no results with this criteria. Try changing your search.</p>
</div>
</div>
</div>
</div>
</section>
);
};
const FilterSections = ({ onClearAll }: { onClearAll: () => void }) => {
const [expandedSections, setExpandedSections] = useState<string[]>([]);
const [selectedCheckboxes, setSelectedCheckboxes] = useState<Set<string>>(new Set());
const [selectedRadio, setSelectedRadio] = useState("all");
const [selectedButtonCheckboxes, setSelectedButtonCheckboxes] = useState<Set<string>>(
new Set(["Option One"]),
);
const [selectedButtonRadio, setSelectedButtonRadio] = useState("Option One");
const [searchKeyword, setSearchKeyword] = useState("");
const [selectValue, setSelectValue] = useState("");
const [sliderValue, setSliderValue] = useState(0);
const [rangeValue, setRangeValue] = useState([0]);
const [switchEnabled, setSwitchEnabled] = useState(false);
useEffect(() => {
setSelectedCheckboxes(new Set());
setSelectedRadio("all");
setSelectedButtonCheckboxes(new Set(["Option One"]));
setSelectedButtonRadio("Option One");
setSearchKeyword("");
setSelectValue("");
setSliderValue(0);
setRangeValue([0]);
setSwitchEnabled(false);
}, [onClearAll]);
const handleCheckboxChange = (option: string) => {
setSelectedCheckboxes((prev) => {
const newSet = new Set(prev);
if (newSet.has(option)) {
newSet.delete(option);
} else {
newSet.add(option);
}
return newSet;
});
};
const handleOptionThreeClick = (option: string) => {
setSelectedButtonCheckboxes((prev) => {
const newSet = new Set(prev);
if (newSet.has(option)) {
newSet.delete(option);
} else {
newSet.add(option);
}
return newSet;
});
};
return (
<Accordion
type="multiple"
className="w-full"
value={expandedSections}
onValueChange={setExpandedSections}
>
<AccordionItem value="filter-one">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter One
</AccordionTrigger>
<AccordionContent>
<div className="grid grid-cols-1">
{["Option One", "Option Two", "Option Three", "Option Four", "Option Five"].map(
(option, index) => (
<label key={index} className="flex items-center gap-3 py-2">
<Checkbox
checked={selectedCheckboxes.has(option)}
onCheckedChange={() => handleCheckboxChange(option)}
/>
<span>{option}</span>
</label>
),
)}
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-two">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Two
</AccordionTrigger>
<AccordionContent>
<RadioGroup
className="grid grid-cols-1 gap-0"
value={selectedRadio}
onValueChange={setSelectedRadio}
>
{["All", "Option One", "Option Two", "Option Three", "Option Four", "Option Five"].map(
(option, index) => (
<div key={index} className="flex items-center gap-3 py-2">
<RadioGroupItem value={option.toLowerCase().replace(" ", "-")} id={`r${index}`} />
<Label htmlFor={`r${index}`}>{option}</Label>
</div>
),
)}
</RadioGroup>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-three">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Three
</AccordionTrigger>
<AccordionContent>
<div className="flex flex-wrap gap-2">
{["Option One", "Option Two", "Option Three", "Option Four", "Option Five"].map(
(option, index) => (
<Button
key={index}
variant={selectedButtonCheckboxes.has(option) ? "default" : "secondary"}
size="sm"
className="px-4"
onClick={() => handleOptionThreeClick(option)}
>
{option}
</Button>
),
)}
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-four">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Four
</AccordionTrigger>
<AccordionContent>
<RadioGroup
className="flex flex-wrap gap-2"
value={selectedButtonRadio}
onValueChange={setSelectedButtonRadio}
>
{["Option One", "Option Two", "Option Three", "Option Four", "Option Five"].map(
(option) => (
<div key={option} className="flex items-center">
<RadioGroupItem value={option} id={`filter-four-${option}`} className="hidden" />
<label
htmlFor={`filter-four-${option}`}
className={`inline-flex cursor-pointer items-center justify-center border border-scheme-border px-4 py-2 text-base transition-colors ${
selectedButtonRadio === option
? "bg-neutral-darkest text-white"
: "bg-transparent"
}`}
>
{option}
</label>
</div>
),
)}
</RadioGroup>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-five">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Five
</AccordionTrigger>
<AccordionContent>
<Input
placeholder="Keyword"
icon={<Search className="size-6 shrink-0 text-scheme-text" />}
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
/>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-six">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Six
</AccordionTrigger>
<AccordionContent>
<Select value={selectValue} onValueChange={setSelectValue}>
<SelectTrigger>
<SelectValue placeholder="Select" />
</SelectTrigger>
<SelectContent>
<SelectItem value="select">Select</SelectItem>
<SelectItem value="option-one">Option One</SelectItem>
<SelectItem value="option-two">Option Two</SelectItem>
<SelectItem value="option-three">Option Three</SelectItem>
</SelectContent>
</Select>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-seven">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Seven
</AccordionTrigger>
<AccordionContent>
<div className="px-3 py-4">
<Slider
value={[sliderValue]}
onValueChange={(value) => setSliderValue(value[0])}
min={0}
step={1}
/>
<div className="mt-3 flex justify-between text-small">
<span className="text-medium">{sliderValue}</span>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-eight">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Eight
</AccordionTrigger>
<AccordionContent>
<div className="px-3 pt-4">
<Slider value={rangeValue} onValueChange={setRangeValue} min={0} max={100} step={1} />
<div className="mt-3 flex justify-between text-small">
<span className="text-medium">{rangeValue}</span>
<span className="text-medium">100</span>
</div>
</div>
</AccordionContent>
</AccordionItem>
<AccordionItem value="filter-nine">
<AccordionTrigger
className="py-4 text-medium font-semibold md:py-5"
icon={
<KeyboardArrowDown className="size-6 shrink-0 text-scheme-text transition-transform duration-300" />
}
>
Filter Nine
</AccordionTrigger>
<AccordionContent>
<Switch id="feature-a" checked={switchEnabled} onCheckedChange={setSwitchEnabled} />
</AccordionContent>
</AccordionItem>
</Accordion>
);
};npm i @radix-ui/react-accordion @radix-ui/react-checkbox @radix-ui/react-dialog @radix-ui/react-dropdown-menu @radix-ui/react-label @radix-ui/react-radio-group @radix-ui/react-select @radix-ui/react-slider @radix-ui/react-slot @radix-ui/react-switch @radix-ui/react-tabs class-variance-authority@0.7.1 clsx@^2.1.1 luxon@^3.5.0 motion@^12.15.0 relume-icons@1.3.0 tailwind-merge@^2.2.2


