From 36f8a6c445d9d523cb812b54469b0cc3ae387492 Mon Sep 17 00:00:00 2001 From: Ayomide-codex Date: Tue, 30 Jun 2026 09:44:36 +0100 Subject: [PATCH 1/4] Add avatar property to APIItem provider --- src/data/mockApis.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data/mockApis.ts b/src/data/mockApis.ts index 959fc30..49a5330 100644 --- a/src/data/mockApis.ts +++ b/src/data/mockApis.ts @@ -7,6 +7,8 @@ export type Review = { verified: boolean; }; + + export type APIItem = { id: string; name: string; From 1b290ab316d55197912e0e8fb2032beaa74238c7 Mon Sep 17 00:00:00 2001 From: Ayomide-codex Date: Tue, 30 Jun 2026 09:50:34 +0100 Subject: [PATCH 2/4] Enhance Tabs.md with overview section Added overview section to Tabs documentation. --- docs/Tabs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/Tabs.md b/docs/Tabs.md index 0d6cbfb..376dc86 100644 --- a/docs/Tabs.md +++ b/docs/Tabs.md @@ -2,6 +2,8 @@ ## Overview + + The `Tabs` component replaces the inline tab navigation in `ApiDetailPage` with a reusable, fully accessible tab strip featuring a **smooth sliding ink-bar indicator** that animates between tabs using CSS `transition` driven by DOM geometry measurements. No animation libraries required. --- From 8e9a82b89ab67f1c39615b87700b8b4c19c71a9b Mon Sep 17 00:00:00 2001 From: Ayomide-codex Date: Tue, 30 Jun 2026 09:58:13 +0100 Subject: [PATCH 3/4] Add prerequisites section to CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ac19f9b..f5b687e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,6 +2,8 @@ Thanks for contributing! Follow these guidelines to keep the codebase consistent. + + ## Prerequisites - Node.js 18+ From 7a11082861bb980516987cbcee800a93bf07d171 Mon Sep 17 00:00:00 2001 From: ayomide-codex Date: Thu, 2 Jul 2026 17:14:54 +0100 Subject: [PATCH 4/4] feat: active filter chips above MarketplacePage results --- src/components/ActiveFilterChips.tsx | 131 +++++++++++++++++++++++++++ src/pages/MarketplacePage.tsx | 15 +++ 2 files changed, 146 insertions(+) create mode 100644 src/components/ActiveFilterChips.tsx diff --git a/src/components/ActiveFilterChips.tsx b/src/components/ActiveFilterChips.tsx new file mode 100644 index 0000000..955ebfd --- /dev/null +++ b/src/components/ActiveFilterChips.tsx @@ -0,0 +1,131 @@ +import React from 'react'; + +interface ActiveFilterChipsProps { + categories: Set; + minPrice: number | null; + maxPrice: number | null; + popularity: string; + favoritesOnly: boolean; + onRemoveCategory: (c: string) => void; + onRemoveMinPrice: () => void; + onRemoveMaxPrice: () => void; + onRemovePopularity: () => void; + onRemoveFavoritesOnly: () => void; + onClearAll: () => void; +} + +export default function ActiveFilterChips({ + categories, + minPrice, + maxPrice, + popularity, + favoritesOnly, + onRemoveCategory, + onRemoveMinPrice, + onRemoveMaxPrice, + onRemovePopularity, + onRemoveFavoritesOnly, + onClearAll, +}: ActiveFilterChipsProps) { + const chips: { key: string; label: string; onRemove: () => void }[] = []; + + categories.forEach((c) => { + chips.push({ + key: `cat-${c}`, + label: `Category: ${c}`, + onRemove: () => onRemoveCategory(c), + }); + }); + + if (minPrice !== null) { + chips.push({ + key: 'minPrice', + label: `Min price: $${minPrice}`, + onRemove: onRemoveMinPrice, + }); + } + + if (maxPrice !== null) { + chips.push({ + key: 'maxPrice', + label: `Max price: $${maxPrice}`, + onRemove: onRemoveMaxPrice, + }); + } + + if (popularity !== 'any') { + chips.push({ + key: 'popularity', + label: `Popularity: ${popularity}`, + onRemove: onRemovePopularity, + }); + } + + if (favoritesOnly) { + chips.push({ + key: 'favorites', + label: 'Favorites only', + onRemove: onRemoveFavoritesOnly, + }); + } + + if (chips.length === 0) { + return null; + } + + return ( +
+ {chips.map((chip) => ( +
+ {chip.label} + +
+ ))} + {chips.length >= 2 && ( + + )} +
+ ); +} diff --git a/src/pages/MarketplacePage.tsx b/src/pages/MarketplacePage.tsx index d5e7602..396ce15 100644 --- a/src/pages/MarketplacePage.tsx +++ b/src/pages/MarketplacePage.tsx @@ -7,6 +7,7 @@ import SearchBar from "../components/SearchBar"; import SortDropdown, { type SortValue } from "../components/SortDropdown"; import FiltersSidebar from "../components/FiltersSidebar"; +import ActiveFilterChips from "../components/ActiveFilterChips"; import EmptyState from "../components/EmptyState"; import { Pagination } from "../components/Pagination"; import MOCK_APIS, { type APIItem } from "../data/mockApis"; @@ -458,6 +459,20 @@ export default function MarketplacePage(): JSX.Element { + toggleCategory(c)} + onRemoveMinPrice={() => setMinPrice(null)} + onRemoveMaxPrice={() => setMaxPrice(null)} + onRemovePopularity={() => setPopularity("any")} + onRemoveFavoritesOnly={() => setFavoritesOnly(false)} + onClearAll={clearFilters} + /> + {fetchError ? ( ) : filtered.length === 0 ? (