Skip to content

Commit

Permalink
Update docs website + add support for light/dark mode.
Browse files Browse the repository at this point in the history
  • Loading branch information
pheralb committed Nov 8, 2023
1 parent 6f622dd commit 10a317a
Show file tree
Hide file tree
Showing 15 changed files with 405 additions and 37 deletions.
73 changes: 73 additions & 0 deletions website/contentlayer.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import type { ComputedFields, FieldDefs } from "contentlayer/source-files";
import { defineDocumentType, makeSource } from "contentlayer/source-files";

// Remark/Rehype extensions:
import rehypeSlug from "rehype-slug";
import rehypeAutolinkHeadings from "rehype-autolink-headings";

// Custom styles:
import { headingStyles } from "./src/styles/headings";

// Define a document type:
const computedFields: ComputedFields = {
slug: {
type: "string",
resolve: (doc) => `/${doc._raw.flattenedPath}`,
},
slugAsParams: {
type: "string",
resolve: (doc) => doc._raw.flattenedPath.split("/").slice(1).join("/"),
},
};

// Shared fields:
const sharedFields: FieldDefs = {
order: {
type: "number",
required: true,
},
title: {
type: "string",
required: true,
},
description: {
type: "string",
},
};

// Pages:
export const Page = defineDocumentType(() => ({
name: "Page",
filePathPattern: `pages/**/*.mdx`,
contentType: "mdx",
fields: sharedFields,
computedFields,
}));

export const EditorPages = defineDocumentType(() => ({
name: "EditorPages",
filePathPattern: `editor/**/*.mdx`,
contentType: "mdx",
fields: sharedFields,
computedFields,
}));

// Create the source:
export default makeSource({
contentDirPath: "./docs",
documentTypes: [Page, EditorPages],
mdx: {
rehypePlugins: [
[rehypeSlug],
[
rehypeAutolinkHeadings,
{
behavior: "wrap",
properties: {
className: [headingStyles],
},
},
],
],
},
});
5 changes: 4 additions & 1 deletion website/next.config.mjs → website/next.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
const { withContentlayer } = require("next-contentlayer");

// Next.js config:
/** @type {import('next').NextConfig} */
const nextConfig = {
swcMinify: true,
reactStrictMode: true,
transpilePackages: ["@typethings/ui"],
};

export default nextConfig;
module.exports = withContentlayer(nextConfig);
71 changes: 71 additions & 0 deletions website/src/app/docs/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { notFound } from "next/navigation";
import { Metadata } from "next";
import { allPages } from "contentlayer/generated";
import { Mdx } from "@/components/mdx";
import { ProseClasses, cn } from "@typethings/ui";

interface PageProps {
params: {
slug: string[];
};
}

async function getPageFromParams(params: PageProps["params"]) {
const slug = params?.slug?.join("/");
const page = allPages.find((page) => page.slugAsParams === slug);

if (!page) {
null;
}

return page;
}

export async function generateMetadata({
params,
}: PageProps): Promise<Metadata> {
const page = await getPageFromParams(params);

if (!page) {
return {};
}

return {
title: page.title,
description: page.description,
};
}

export async function generateStaticParams(): Promise<PageProps["params"][]> {
return allPages.map((page) => ({
slug: page.slugAsParams.split("/"),
}));
}

export default async function PagePage({ params }: PageProps) {
const page = await getPageFromParams(params);

if (!page) {
notFound();
}

return (
<main>
<div className="mb-10 border-b pb-5">
<h1 className="mb-3 inline-block text-2xl font-bold tracking-tight text-gray-900 dark:text-gray-200 sm:text-4xl">
{page.title}
</h1>
{page.description && (
<p className="text-neutral-400">{page.description}</p>
)}
</div>
<article
className={cn(
"prose prose-quoteless prose-neutral dark:prose-invert prose-p:my-4 prose-a:no-underline prose-a:underline-offset-[5px] prose-a:duration-100 hover:prose-a:underline prose-a:decoration-neutral-600 prose-a:decoration-solid",
)}
>
<Mdx code={page.body.code} />
</article>
</main>
);
}
119 changes: 119 additions & 0 deletions website/src/app/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
"use client";

import React from "react";
import Container from "@/components/container";
import {
Button,
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
Input,
ProseClasses,
cn,
} from "@typethings/ui";
import {
ArrowDown,
Book,
ChevronDown,
ChevronUp,
Package,
Rocket,
Search,
} from "lucide-react";
import { allEditorPages, allPages } from "contentlayer/generated";
import Link from "next/link";
import { usePathname } from "next/navigation";

interface iLayoutProps {
children: React.ReactNode;
}

const Layout = (props: iLayoutProps) => {
const path = usePathname();

const groups = [
{
icon: <Rocket size={16} className="text-indigo-600 dark:text-indigo-300" />,
groupName: "App",
pages: allPages,
},
{
icon: <Package size={16} className="text-rose-600 dark:text-rose-300" />,
groupName: "typethings/editor",
pages: allEditorPages,
},
];

return (
<>
<div className="sticky top-0 z-50 flex w-full flex-col border-b border-neutral-200 dark:border-neutral-800 dark:bg-neutral-900">
<Container>
<div className="mx-auto mt-2 flex w-full flex-wrap items-center justify-between py-3">
<div className="flex items-center space-x-2">
<span className="self-center whitespace-nowrap font-normal tracking-tight dark:text-neutral-300">
Documentation
</span>
</div>
<div className="relative w-64">
<Input placeholder="Search..." className="pl-9" />
<Search
size={16}
className="absolute left-3 top-1/2 -translate-y-1/2 transform"
/>
</div>
</div>
</Container>
</div>
<Container className="w-full">
{/* Create a grid, the left zone fixed with 300px and second full screen. */}
<aside className="fixed h-full w-60 overflow-y-auto overflow-x-hidden pb-10">
<div className="flex flex-col pt-8">
{groups.map((group) => (
<Collapsible key={group.groupName} defaultOpen={true}>
<CollapsibleTrigger asChild className="mb-1">
<Button
variant="outline"
className="text-md flex h-10 w-full justify-between text-start shadow-none rounded-md border-dashed"
>
<div className="flex items-center space-x-3">
{group.icon}
<span>{group.groupName}</span>
</div>
<ChevronDown size={16} />
</Button>
</CollapsibleTrigger>
<CollapsibleContent className="pl-5">
<div className="mb-1 flex flex-col space-y-3 py-5">
{group.pages
.sort((a, b) => a.order - b.order)
.map((page) => (
<div key={page.slugAsParams}>
<Link
href={`/docs/${page.slugAsParams}`}
className={cn(
"block text-neutral-500 dark:text-neutral-400 transition-colors duration-100 hover:text-neutral-900 dark:hover:text-white",
path === `/docs/${page.slugAsParams}` &&
"text-neutral-900 dark:text-white font-medium",
)}
>
{page.title}
</Link>
</div>
))}
</div>
</CollapsibleContent>
</Collapsible>
))}
</div>
</aside>
<main className="ml-60 w-full">
<article className={cn("container max-w-5xl flex flex-col px-4 py-8")}>
{props.children}
</article>
</main>
</Container>
</>
);
};

export default Layout;
18 changes: 14 additions & 4 deletions website/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import { cn } from "@typethings/ui";
// Layout:
import Navbar from "@/components/navbar";

// Providers:
import { ThemeProvider } from "@/providers/theme-provider";

// Metadata:
export const metadata: Metadata = {
title: {
Expand Down Expand Up @@ -56,14 +59,21 @@ export default function RootLayout({
children: React.ReactNode;
}) {
return (
<html lang="en">
<html lang="en" suppressHydrationWarning>
<body
className={cn(
"dark min-h-screen bg-neutral-900 text-white antialiased",
"min-h-screen bg-neutral-100 text-neutral-900 dark:text-white antialiased dark:bg-neutral-900",
)}
>
<Navbar />
{children}
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
<Navbar />
{children}
</ThemeProvider>
</body>
</html>
);
Expand Down
12 changes: 8 additions & 4 deletions website/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Windows from "@/components/icons/windows";
import { Global } from "@/global/data";
import { buttonVariants, cn } from "@typethings/ui";
import { Book } from "lucide-react";
import Image from "next/image";
import Link from "next/link";

export default function Home() {
Expand All @@ -18,7 +19,7 @@ export default function Home() {

return (
<>
<section className="pb-12 pt-6">
<section className="py-12">
<Container>
<div className="mx-auto items-center gap-8 md:grid md:grid-cols-2 xl:gap-16">
<div className="animate-in slide-in-from-bottom-8 fade-in-10 mt-4 duration-700 md:mt-0">
Expand Down Expand Up @@ -63,11 +64,14 @@ export default function Home() {
</Link>
</div>
</div>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
<Image
sizes="100vw"
width={800}
height={600}
style={{ width: "100%", height: "auto" }}
className="w-full rounded-md delay-300"
src="/images/screenshot_en.png"
alt="dashboard image"
alt="Typethings screenshot"
/>
</div>
</Container>
Expand Down
2 changes: 1 addition & 1 deletion website/src/components/cardSpotlight.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const CardSpotlight = (props: iCardSpotlight) => {
onBlur={handleBlur}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
className="relative flex overflow-hidden rounded-md border border-neutral-800 p-6"
className="relative flex overflow-hidden rounded-md border dark:border-neutral-800 p-6"
>
<div
className="pointer-events-none absolute -inset-px opacity-0 transition duration-300"
Expand Down
Loading

0 comments on commit 10a317a

Please sign in to comment.