Add roadmaps page

pull/5424/head
Kamran Ahmed 8 months ago
parent f8f29d2a17
commit dd728b526e
  1. 2
      src/components/OpenSourceBanner.astro
  2. 2
      src/components/OpenSourceStat.astro
  3. 28
      src/components/Roadmaps/CategoryFilterButton.tsx
  4. 86
      src/components/Roadmaps/RoadmapsPage.tsx
  5. 16
      src/components/Roadmaps/RoadmapsPageHeader.tsx

@ -21,7 +21,7 @@ const discordInfo = await getDiscordInfo();
</p>
<div
class='mt-5 grid grid-cols-1 justify-between gap-2 divide-x-0 sm:my-11 sm:grid-cols-3 sm:gap-0 sm:divide-x'
class='mt-5 grid grid-cols-1 justify-between gap-2 divide-x-0 sm:my-11 sm:grid-cols-3 sm:gap-0 sm:divide-x mb-4 sm:mb-0'
>
<OpenSourceStat text='GitHub Stars' value={starCount} />
<OpenSourceStat text='Registered Users' value={'850k'} />

@ -14,7 +14,7 @@ const isDiscordMembers = text.toLowerCase() === 'discord members';
---
<div
class='flex items-start sm:items-center justify-start flex-col sm:justify-center sm:gap-0 gap-2 sm:bg-transparent bg-gray-200 sm:rounded-none rounded-xl p-4'
class='flex items-start sm:items-center justify-start flex-col sm:justify-center sm:gap-0 gap-2 sm:bg-transparent sm:rounded-none rounded-xl p-0 sm:p-4 mb-3 sm:mb-0'
>
{
isGitHubStars && (

@ -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 (
<button
className={cn(
'border-b bg-gradient-to-l py-1.5 pr-3 text-center text-sm text-gray-500 hover:from-white hover:text-gray-900 sm:text-right',
{
'from-white font-semibold text-gray-900':
selected && category !== 'All Roadmaps',
'font-semibold text-gray-900': selected && category === 'All Roadmaps',
},
)}
type="button"
onClick={onClick}
>
{category}
</button>
);
}

@ -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<AllowGroupNames>('');
const [visibleGroups, setVisibleGroups] = useState<GroupType[]>(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 (
<div className="border-t bg-gray-100">
<div className="container flex flex-row gap-4">
<div className="w-[180px] border-r bg-gradient-to-l from-gray-100 pt-6">
<div className="sticky top-10 pb-20">
<button
onClick={() => {
setIsFilterOpen(!isFilterOpen);
}}
id="filter-button"
className={cn(
'-mt-1 flex w-full items-center justify-center bg-gray-300 py-2 text-sm text-black focus:shadow-none focus:outline-0 sm:hidden',
{
'mb-3': !isFilterOpen,
},
)}
>
{!isFilterOpen && <Filter size={13} className="mr-1" />}
{isFilterOpen && <X size={13} className="mr-1" />}
Categories
</button>
<div className="container relative flex flex-col gap-4 sm:flex-row">
<div
className={cn(
'hidden w-full flex-col from-gray-100 sm:w-[180px] sm:border-r sm:bg-gradient-to-l sm:pt-6',
{
'hidden sm:flex': !isFilterOpen,
'z-50 flex': isFilterOpen,
},
)}
>
<div className="absolute top-0 -mx-4 w-full bg-white pb-0 shadow-xl sm:sticky sm:top-10 sm:mx-0 sm:bg-transparent sm:pb-20 sm:shadow-none">
<div className="grid grid-cols-1">
<button
onClick={() => setActiveGroup('')}
className={cn('border-b py-1.5 pr-3 text-right text-sm', {
'font-bold text-gray-900': activeGroup === '',
})}
>
{' '}
All Roadmaps
</button>
<CategoryFilterButton
onClick={() => {
setActiveGroup('');
setIsFilterOpen(false);
}}
category={'All Roadmaps'}
selected={activeGroup === ''}
/>
{groups.map((group) => (
<button
<CategoryFilterButton
key={group.group}
className={cn(
'border-b bg-gradient-to-l py-1.5 pr-3 text-right text-sm text-gray-500 hover:from-white hover:text-gray-900',
{
'from-white font-semibold text-gray-900':
activeGroup === group.group,
},
)}
type="button"
onClick={() => setActiveGroup(group.group)}
>
{group.group}
</button>
onClick={() => {
setActiveGroup(group.group);
setIsFilterOpen(false);
}}
category={group.group}
selected={activeGroup === group.group}
/>
))}
</div>
</div>
</div>
<div className="flex flex-grow flex-col gap-6 pb-20 pt-8">
<div className="flex flex-grow flex-col gap-6 pb-20 pt-2 sm:pt-8">
{visibleGroups.map((group) => (
<div key={`${group.group}-${group.roadmaps.length}`}>
<h2 className="mb-2 text-xs uppercase tracking-wide text-gray-400">
{group.group}
</h2>
<div className="grid grid-cols-3 gap-1.5">
<div className="grid grid-cols-1 gap-1.5 sm:grid-cols-2 md:grid-cols-3">
{group.roadmaps.map((roadmap) => (
<a
key={roadmap.link}

@ -1,21 +1,21 @@
export function RoadmapsPageHeader() {
return (
<div className="bg-white py-12">
<div className="bg-white py-3 sm:py-12">
<div className="container">
<div className="flex flex-col items-center bg-white">
<h1 className="text-5xl font-bold">Developer Roadmaps</h1>
<p className="my-3 text-lg">
Browse ever-growing list of up-to-date, community driven roadmaps
<div className="flex flex-col items-start sm:items-center bg-white">
<h1 className="text-2xl sm:text-5xl font-bold">Developer Roadmaps</h1>
<p className="mb-3 mt-1 sm:my-3 text-sm sm:text-lg">
Browse the ever-growing list of up-to-date, community driven roadmaps
</p>
<p className="flex flex-row gap-3">
<p className="flex flex-col sm:flex-row gap-1.5 sm:gap-3 w-full sm:w-auto mb-3 sm:mb-0">
<a
className="inline-block rounded-md bg-black px-3.5 py-1.5 text-base text-white"
className="inline-block rounded-md bg-black px-3.5 py-2 sm:py-1.5 text-sm sm:text-base text-white"
href="#"
>
Draw your own roadmap
</a>
<a
className="inline-block rounded-md bg-gray-300 px-3.5 py-1.5 text-base text-black"
className="inline-block rounded-md bg-gray-300 px-3.5 py-2 sm:py-1.5 text-sm sm:text-base text-black"
href="#"
>
Generate Roadmap with AI

Loading…
Cancel
Save