diff --git a/src/components/OpenSourceStat.astro b/src/components/OpenSourceStat.astro
index 6b2cf7495..f0da3adff 100644
--- a/src/components/OpenSourceStat.astro
+++ b/src/components/OpenSourceStat.astro
@@ -14,7 +14,7 @@ const isDiscordMembers = text.toLowerCase() === 'discord members';
---
{
isGitHubStars && (
diff --git a/src/components/Roadmaps/CategoryFilterButton.tsx b/src/components/Roadmaps/CategoryFilterButton.tsx
new file mode 100644
index 000000000..c1628ba32
--- /dev/null
+++ b/src/components/Roadmaps/CategoryFilterButton.tsx
@@ -0,0 +1,28 @@
+import { cn } from '../../lib/classname.ts';
+
+type CategoryFilterButtonProps = {
+ category: string;
+ selected: boolean;
+ onClick: () => void;
+};
+
+export function CategoryFilterButton(props: CategoryFilterButtonProps) {
+ const { category, selected, onClick } = props;
+
+ return (
+
+ );
+}
diff --git a/src/components/Roadmaps/RoadmapsPage.tsx b/src/components/Roadmaps/RoadmapsPage.tsx
index 4d21fda08..a26e0981b 100644
--- a/src/components/Roadmaps/RoadmapsPage.tsx
+++ b/src/components/Roadmaps/RoadmapsPage.tsx
@@ -1,5 +1,8 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
import { cn } from '../../lib/classname.ts';
+import { Filter, X } from 'lucide-react';
+import { CategoryFilterButton } from './CategoryFilterButton.tsx';
+import { useOutsideClick } from '../../hooks/use-outside-click.ts';
const groupNames = [
'Absolute Beginners',
@@ -387,6 +390,14 @@ export function RoadmapsPage() {
const [activeGroup, setActiveGroup] = useState
('');
const [visibleGroups, setVisibleGroups] = useState(allGroups);
+ const [isFilterOpen, setIsFilterOpen] = useState(false);
+
+ useEffect(() => {
+ if (!isFilterOpen) {
+ document?.getElementById('filter-button')?.focus();
+ }
+ }, [isFilterOpen]);
+
useEffect(() => {
if (!activeGroup) {
setVisibleGroups(allGroups);
@@ -421,46 +432,65 @@ export function RoadmapsPage() {
return (
-
-
-
+
+
+
+
-
+ {
+ setActiveGroup('');
+ setIsFilterOpen(false);
+ }}
+ category={'All Roadmaps'}
+ selected={activeGroup === ''}
+ />
+
{groups.map((group) => (
-
+ onClick={() => {
+ setActiveGroup(group.group);
+ setIsFilterOpen(false);
+ }}
+ category={group.group}
+ selected={activeGroup === group.group}
+ />
))}
-
+
{visibleGroups.map((group) => (