Skip to content

Commit bbdf99a

Browse files
authored
Merge pull request Weaverse#232 from Weaverse/dev
Add clear filters functionlity, update filters styles
2 parents 7e1f9dc + e47364b commit bbdf99a

File tree

5 files changed

+142
-76
lines changed

5 files changed

+142
-76
lines changed

app/components/header/desktop-header.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { useThemeSettings } from "@weaverse/hydrogen";
88
import { cva } from "class-variance-authority";
99
import { Suspense } from "react";
1010
import useWindowScroll from "react-use/esm/useWindowScroll";
11-
import { DialogDemo } from "~/components/drawer";
1211
import { IconUser } from "~/components/icons";
1312
import { Logo } from "~/components/logo";
1413
import { cn } from "~/lib/cn";
@@ -73,7 +72,6 @@ export function DesktopHeader() {
7372
<div className="flex items-center gap-1 z-1">
7473
<PredictiveSearchButton />
7574
<AccountLink className="relative flex items-center justify-center w-8 h-8" />
76-
{/* <DialogDemo openFrom="right" /> */}
7775
<CartCount
7876
isHome={isHome}
7977
openCart={() => {}}

app/components/tooltip.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export let TooltipContent = forwardRef<HTMLDivElement, TooltipContentProps>(
3030
ref={ref}
3131
className={cn(
3232
"animate-slide-down-and-fade",
33-
"z-50 px-4 rounded py-1 shadow-sm text-background bg-body",
33+
"z-50 px-3 py-1 shadow-sm text-background bg-body",
3434
className,
3535
)}
3636
align="center"

app/sections/collection-filters/filters.tsx

Lines changed: 56 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -44,18 +44,22 @@ export function Filters({ className }: { className?: string }) {
4444
appliedFilters: AppliedFilter[];
4545
}
4646
>();
47+
let appliedFiltersKeys = appliedFilters
48+
.map((filter) => filter.label)
49+
.join("-");
4750
let filters = collection.products.filters as Filter[];
4851

4952
return (
5053
<Accordion.Root
5154
type="multiple"
5255
className={cn("filters-list divide-y divide-line-subtle", className)}
53-
key={expandFilters.toString() + showFiltersCount}
56+
key={appliedFiltersKeys + expandFilters.toString() + showFiltersCount}
5457
defaultValue={expandFilters ? filters.map((filter) => filter.id) : []}
5558
>
5659
{filters.map((filter: Filter) => {
5760
let asColorSwatch =
5861
enableColorSwatch && COLORS_FILTERS.includes(filter.label);
62+
let asButton = displayAsButtonFor.includes(filter.label);
5963

6064
return (
6165
<Accordion.Item
@@ -83,10 +87,11 @@ export function Filters({ className }: { className?: string }) {
8387
])}
8488
>
8589
<div
86-
key={filter.id}
8790
className={clsx(
8891
"flex pt-8",
89-
asColorSwatch ? "gap-1.5 flex-wrap" : "flex-col gap-5",
92+
asColorSwatch || asButton
93+
? "gap-1.5 flex-wrap"
94+
: "flex-col gap-5",
9095
)}
9196
>
9297
{filter.values?.map((option) => {
@@ -108,9 +113,15 @@ export function Filters({ className }: { className?: string }) {
108113
}
109114
default:
110115
return (
111-
<ListItemFilter
116+
<FilterItem
112117
key={option.id}
113-
asColorSwatch={asColorSwatch}
118+
displayAs={
119+
asColorSwatch
120+
? "color-swatch"
121+
: asButton
122+
? "button"
123+
: "list-item"
124+
}
114125
appliedFilters={appliedFilters as AppliedFilter[]}
115126
option={option}
116127
showFiltersCount={showFiltersCount}
@@ -127,13 +138,13 @@ export function Filters({ className }: { className?: string }) {
127138
);
128139
}
129140

130-
function ListItemFilter({
131-
asColorSwatch,
141+
function FilterItem({
142+
displayAs,
132143
option,
133144
appliedFilters,
134145
showFiltersCount,
135146
}: {
136-
asColorSwatch?: boolean;
147+
displayAs: "color-swatch" | "button" | "list-item";
137148
option: Filter["values"][0];
138149
appliedFilters: AppliedFilter[];
139150
showFiltersCount: boolean;
@@ -161,7 +172,7 @@ function ListItemFilter({
161172
}
162173
}
163174

164-
if (asColorSwatch) {
175+
if (displayAs === "color-swatch") {
165176
let swatchColor = swatches.colors.find(({ name }) => name === option.label);
166177
let optionConf = options.find(({ name }) => {
167178
return name.toLowerCase() === option.label.toLowerCase();
@@ -179,6 +190,7 @@ function ListItemFilter({
179190
shape,
180191
}),
181192
checked ? "p-1 border-line" : "border-line-subtle",
193+
option.count === 0 && "diagonal",
182194
)}
183195
onClick={() => handleCheckedChange(!checked)}
184196
>
@@ -195,37 +207,56 @@ function ListItemFilter({
195207
</button>
196208
</TooltipTrigger>
197209
<TooltipContent>
198-
{showFiltersCount ? (
199-
<span>
200-
{option.label}{" "}
201-
<span className="text-gray-100">({option.count})</span>
202-
</span>
203-
) : (
204-
option.label
205-
)}
210+
<FilterLabel option={option} showFiltersCount={showFiltersCount} />
206211
</TooltipContent>
207212
</Tooltip>
208213
);
209214
}
210215

216+
if (displayAs === "button") {
217+
return (
218+
<button
219+
type="button"
220+
className={cn(
221+
"px-3 py-1.5 border text-center",
222+
option.count === 0 && "diagonal text-body-subtle",
223+
checked
224+
? "border-line bg-body text-background"
225+
: "border-line-subtle hover:border-line",
226+
)}
227+
onClick={() => handleCheckedChange(!checked)}
228+
>
229+
<FilterLabel option={option} showFiltersCount={showFiltersCount} />
230+
</button>
231+
);
232+
}
233+
211234
return (
212235
<Checkbox
213236
checked={checked}
214237
onCheckedChange={handleCheckedChange}
215238
label={
216-
showFiltersCount ? (
217-
<span>
218-
{option.label}{" "}
219-
<span className="text-gray-700">({option.count})</span>
220-
</span>
221-
) : (
222-
option.label
223-
)
239+
<FilterLabel option={option} showFiltersCount={showFiltersCount} />
224240
}
241+
className={clsx(option.count === 0 && "line-through text-body-subtle")}
225242
/>
226243
);
227244
}
228245

246+
function FilterLabel({
247+
option,
248+
showFiltersCount,
249+
}: { option: Filter["values"][0]; showFiltersCount: boolean }) {
250+
if (showFiltersCount) {
251+
return (
252+
<span>
253+
{option.label} <span>({option.count})</span>
254+
</span>
255+
);
256+
}
257+
return option.label;
258+
}
259+
229260
// const PRICE_RANGE_FILTER_DEBOUNCE = 500;
230261

231262
function PriceRangeFilter({ max, min }: { max?: number; min?: number }) {

app/sections/collection-filters/products-pagination.tsx

Lines changed: 81 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
1-
import { useLoaderData, useNavigate } from "@remix-run/react";
1+
import { X } from "@phosphor-icons/react";
2+
import {
3+
useLoaderData,
4+
useLocation,
5+
useNavigate,
6+
useSearchParams,
7+
} from "@remix-run/react";
28
import { Pagination } from "@shopify/hydrogen";
39
import clsx from "clsx";
410
import { useEffect } from "react";
511
import { useInView } from "react-intersection-observer";
612
import type { CollectionDetailsQuery } from "storefrontapi.generated";
713
import Link from "~/components/link";
814
import { getImageLoadingPriority } from "~/lib/const";
15+
import { getAppliedFilterLink, type AppliedFilter } from "~/lib/filter";
916
import { ProductCard } from "~/modules/product-card";
1017

1118
export function ProductsPagination({
@@ -19,58 +26,87 @@ export function ProductsPagination({
1926
loadPrevText: string;
2027
loadMoreText: string;
2128
}) {
22-
let { collection } = useLoaderData<
29+
let { collection, appliedFilters } = useLoaderData<
2330
CollectionDetailsQuery & {
2431
collections: Array<{ handle: string; title: string }>;
32+
appliedFilters: AppliedFilter[];
2533
}
2634
>();
35+
let [params] = useSearchParams();
36+
let location = useLocation();
37+
let { pathname } = location;
2738
let { ref, inView } = useInView();
2839

2940
return (
30-
<Pagination connection={collection.products}>
31-
{({
32-
nodes,
33-
isLoading,
34-
nextPageUrl,
35-
previousPageUrl,
36-
hasNextPage,
37-
hasPreviousPage,
38-
state,
39-
}) => (
40-
<div
41-
className="flex w-full flex-col gap-8 items-center"
42-
style={
43-
{
44-
"--cols-mobile": `repeat(${gridSizeMobile || 1}, minmax(0, 1fr))`,
45-
"--cols-desktop": `repeat(${gridSizeDesktop || 3}, minmax(0, 1fr))`,
46-
} as React.CSSProperties
47-
}
48-
>
49-
{hasPreviousPage && (
50-
<Link to={previousPageUrl} variant="outline" className="mx-auto">
51-
{isLoading ? "Loading..." : loadPrevText}
52-
</Link>
53-
)}
54-
<ProductsLoadedOnScroll
55-
nodes={nodes}
56-
inView={inView}
57-
nextPageUrl={nextPageUrl}
58-
hasNextPage={hasNextPage}
59-
state={state}
60-
/>
61-
{hasNextPage && (
62-
<Link
63-
ref={ref}
64-
to={nextPageUrl}
65-
variant="outline"
66-
className="mx-auto"
67-
>
68-
{isLoading ? "Loading..." : loadMoreText}
69-
</Link>
70-
)}
41+
<div className="space-y-6">
42+
{appliedFilters.length > 0 ? (
43+
<div className="flex items-center flex-wrap gap-6">
44+
<div className="flex items-center gap-2">
45+
{appliedFilters.map((filter: AppliedFilter) => {
46+
let { label } = filter;
47+
return (
48+
<Link
49+
key={label}
50+
to={getAppliedFilterLink(filter, params, location)}
51+
className="px-2 py-1 border border-line-subtle hover:border-line items-center gap-2"
52+
variant="custom"
53+
>
54+
<span>{label}</span>
55+
<X className="w-4 h-4" />
56+
</Link>
57+
);
58+
})}
59+
</div>
60+
<Link to={pathname} variant="underline">
61+
Clear all filters
62+
</Link>
7163
</div>
72-
)}
73-
</Pagination>
64+
) : null}
65+
<Pagination connection={collection.products}>
66+
{({
67+
nodes,
68+
isLoading,
69+
nextPageUrl,
70+
previousPageUrl,
71+
hasNextPage,
72+
hasPreviousPage,
73+
state,
74+
}) => (
75+
<div
76+
className="flex w-full flex-col gap-8 items-center"
77+
style={
78+
{
79+
"--cols-mobile": `repeat(${gridSizeMobile || 1}, minmax(0, 1fr))`,
80+
"--cols-desktop": `repeat(${gridSizeDesktop || 3}, minmax(0, 1fr))`,
81+
} as React.CSSProperties
82+
}
83+
>
84+
{hasPreviousPage && (
85+
<Link to={previousPageUrl} variant="outline" className="mx-auto">
86+
{isLoading ? "Loading..." : loadPrevText}
87+
</Link>
88+
)}
89+
<ProductsLoadedOnScroll
90+
nodes={nodes}
91+
inView={inView}
92+
nextPageUrl={nextPageUrl}
93+
hasNextPage={hasNextPage}
94+
state={state}
95+
/>
96+
{hasNextPage && (
97+
<Link
98+
ref={ref}
99+
to={nextPageUrl}
100+
variant="outline"
101+
className="mx-auto"
102+
>
103+
{isLoading ? "Loading..." : loadMoreText}
104+
</Link>
105+
)}
106+
</div>
107+
)}
108+
</Pagination>
109+
</div>
74110
);
75111
}
76112

app/sections/collection-filters/sort.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { CaretDown } from "@phosphor-icons/react";
1+
import { CaretDown, CheckCircle } from "@phosphor-icons/react";
22
import * as DropdownMenu from "@radix-ui/react-dropdown-menu";
3-
import { Link, useLocation, useSearchParams } from "@remix-run/react";
3+
import { useLocation, useSearchParams } from "@remix-run/react";
4+
import Link from "~/components/link";
45
import { cn } from "~/lib/cn";
56
import type { SortParam } from "~/lib/filter";
67

@@ -68,7 +69,7 @@ export function Sort() {
6869
to={sortUrl}
6970
className={cn(
7071
"hover:underline underline-offset-[6px] hover:outline-none",
71-
currentSortValue === key && "underline",
72+
currentSortValue === key && "font-bold",
7273
)}
7374
>
7475
{label}

0 commit comments

Comments
 (0)