diff --git a/components/Blog/BlogHeader.tsx b/components/Blog/BlogHeader.tsx new file mode 100644 index 000000000..3bc49a68b --- /dev/null +++ b/components/Blog/BlogHeader.tsx @@ -0,0 +1,38 @@ +import { Rss } from "react-feather"; +import Dropdown from "../Dropdown"; +import { BLOG_CATEGORIES } from "./index"; + +export default function BlogHeader({ description }: { description: string }) { + const categoryLinks = Object.keys(BLOG_CATEGORIES).map((k) => ({ + href: `/blog/category/${k}`, + text: BLOG_CATEGORIES[k], + })); + return ( +
+
+

+ Blog +

+ +
+
+

{description}

+ + + +
+ +
+ ); +} diff --git a/components/Blog/BlogPostList.tsx b/components/Blog/BlogPostList.tsx new file mode 100644 index 000000000..23e830b69 --- /dev/null +++ b/components/Blog/BlogPostList.tsx @@ -0,0 +1,42 @@ +import Image from "next/image"; +import { RiCalendarLine } from "@remixicon/react"; +import Tags from "src/shared/Blog/Tags"; +import { type BlogPost } from "./index"; + +export default function BlogPostList({ posts }: { posts: BlogPost[] }) { + return ( + + ); +} diff --git a/components/Blog/index.ts b/components/Blog/index.ts new file mode 100644 index 000000000..4b2be6fbe --- /dev/null +++ b/components/Blog/index.ts @@ -0,0 +1,19 @@ +import { type MDXFileMetadata } from "src/utils/markdown"; + +export type BlogPost = { + heading: string; + subtitle: string; + author?: string; + image: string; + date: string; + humanDate: string; + tags?: string[]; + hide?: boolean; +} & MDXFileMetadata; + +// Slug -> Formatted title +export const BLOG_CATEGORIES = { + "product-updates": "Product updates", + "company-news": "Company news", + engineering: "Engineering", +}; diff --git a/components/Dropdown.tsx b/components/Dropdown.tsx new file mode 100644 index 000000000..2d2bc57ab --- /dev/null +++ b/components/Dropdown.tsx @@ -0,0 +1,62 @@ +"use client"; +import { useState } from "react"; +import { RiArrowDownSLine } from "@remixicon/react"; + +export default function Dropdown({ + title, + items, + className = "", +}: { + title: React.ReactNode; + items: { + href: string; + text: string; + target?: string; + }[]; + className?: string; +}) { + const [open, setOpen] = useState(false); + /** + * NOTE - This uses md: prefixes to make the button work on hover on desktop and click on mobile + */ + return ( +
+
setOpen(!open)} + > + {title} + +
+
md) + className={`absolute right-0 w-full min-w-min md:hidden md:group-hover:block ${ + open ? "block" : "hidden" + }`} + > +
+ {/* transparent element to persist hover */} +
+ +
+
+ ); +} diff --git a/components/Nav.tsx b/components/Nav.tsx index a56885ffc..8aa773770 100644 --- a/components/Nav.tsx +++ b/components/Nav.tsx @@ -14,6 +14,7 @@ import classNames from "src/utils/classNames"; import Container from "src/shared/layout/Container"; import Menu, { type MenuProps } from "./Nav/Menu"; import { productLinks, resourcesLinks } from "./Nav/links"; +import Dropdown from "./Dropdown"; // Manual count of stars on GitHub for now // Run pnpm run github:stars to get the latest count @@ -200,50 +201,22 @@ const repos = [ ]; function OpenSourceButton({ className = "" }: { className?: string }) { - const [open, setOpen] = useState(false); - /** - * NOTE - This uses md: prefixes to make the button work on hover on desktop and click on mobile - */ + const items = repos.map((repo) => ({ + href: `https://github.com/${repo}`, + text: repo, + target: "_blank", + })); return ( -
-
setOpen(!open)} - > - Open Source - - {(GITHUB_STARS / 1000).toFixed(1)}K - -
-
md) - className={`absolute right-0 w-full min-w-min md:hidden md:group-hover:block ${ - open ? "block" : "hidden" - }`} - > -
- {/* transparent element to persist hover */} -
- -
-
+ + Open Source + + {(GITHUB_STARS / 1000).toFixed(1)}K + + } + items={items} + className={className} + /> ); } diff --git a/pages/blog.tsx b/pages/blog.tsx index 79ad25d62..5683496fd 100644 --- a/pages/blog.tsx +++ b/pages/blog.tsx @@ -14,9 +14,12 @@ import { loadMarkdownFilesMetadata, type MDXFileMetadata, } from "../utils/markdown"; +import BlogHeader from "src/components/Blog/BlogHeader"; +import BlogPostList from "src/components/Blog/BlogPostList"; +import { type BlogPost } from "src/components/Blog"; // import { LaunchWeekBanner } from "./index"; -export default function BlogLayout(props) { +export default function BlogIndex(props) { const router = useRouter(); const { showHidden } = router.query; @@ -37,7 +40,7 @@ export default function BlogLayout(props) { return ( <> - Inngest → Product & Engineering blog + Inngest - Product & Engineering blog */} -
-

- Blog -

-

{description}

- - - -
+ +
{focus && ( )} - +