Compare commits

...

4 Commits

Author SHA1 Message Date
blacksmith-sh[bot]
494d902e79 Migrate workflows to Blacksmith 2025-02-11 11:25:06 +00:00
Guido D'Orsi
44f38f3438 Merge pull request #1346 from garden-co/jazz-697-fix-copy-button-alignment
Fix copy button alignment
2025-02-11 11:45:06 +01:00
Trisha Lim
33293f3b64 Fix copy button alignment 2025-02-11 16:20:55 +07:00
Trisha Lim
e35018a5fa Redesign mobile nav (#1177) 2025-02-10 20:53:33 +07:00
51 changed files with 281 additions and 254 deletions

View File

@@ -6,7 +6,7 @@ on:
jobs:
build-examples:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
strategy:
matrix:
example: [
@@ -36,7 +36,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v3
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -46,7 +46,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -6,7 +6,7 @@ on:
jobs:
build-starters:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
strategy:
matrix:
starter: [
@@ -27,7 +27,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v3
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -37,7 +37,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -6,7 +6,7 @@ on:
jobs:
quality:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -8,7 +8,7 @@ on:
jobs:
test:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
timeout-minutes: 5
steps:
@@ -25,7 +25,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v3
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -35,7 +35,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -9,7 +9,7 @@ on:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
continue-on-error: true
strategy:
matrix:
@@ -29,7 +29,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v3
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -39,7 +39,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -17,7 +17,7 @@ concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- name: Checkout Repo
uses: actions/checkout@v3
@@ -31,7 +31,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v3
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -41,7 +41,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v3
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -9,7 +9,7 @@ on:
jobs:
unit-tests:
runs-on: ubuntu-latest
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- name: Checkout
@@ -24,7 +24,7 @@ jobs:
pnpm --version
- name: Install Node.js
uses: actions/setup-node@v4
uses: useblacksmith/setup-node@v5
with:
node-version-file: '.node-version'
cache: 'pnpm'
@@ -34,7 +34,7 @@ jobs:
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
- uses: useblacksmith/cache@v5
name: Setup pnpm cache
with:
path: ${{ env.STORE_PATH }}

View File

@@ -26,6 +26,7 @@ import {
MousePointerSquareDashedIcon,
PencilLineIcon,
ScanFace,
ScrollIcon,
SunIcon,
TrashIcon,
UploadCloudIcon,
@@ -67,6 +68,7 @@ const icons = {
permissions: FileLock2Icon,
social: UsersIcon,
spatialPresence: MousePointerSquareDashedIcon,
tableOfContents: ScrollIcon,
touchId: FingerprintIcon,
upload: UploadCloudIcon,
write: PencilLineIcon,

View File

@@ -6,7 +6,7 @@ import { Icon } from "../atoms/Icon";
// TODO: add tabs feature, and remove CodeExampleTabs
function CopyButton({ code, size }: { code: string; size?: "sm" | "md" }) {
function CopyButton({ code, size }: { code: string; size: "md" | "lg" }) {
let [copyCount, setCopyCount] = useState(0);
let copied = copyCount > 0;
@@ -27,8 +27,8 @@ function CopyButton({ code, size }: { code: string; size?: "sm" | "md" }) {
copied
? "bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20"
: "bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5",
size == "sm"
? "right-1.5 top-1.5 py-[2px] pl-1 pr-2"
size == "md"
? "right-[8px] top-[8px] py-[2px] pl-1 pr-2"
: "right-2 top-2 py-1 pl-2 pr-3 ",
)}
onClick={() => {
@@ -48,7 +48,7 @@ function CopyButton({ code, size }: { code: string; size?: "sm" | "md" }) {
name="copy"
size="xs"
className={clsx(
size === "sm" ? "size-2" : "size-3",
size === "md" ? "size-3" : "size-4",
"stroke-stone-500 transition-colors group-hover/button:stroke-stone-600 dark:group-hover/button:stroke-stone-400",
)}
/>
@@ -69,11 +69,11 @@ function CopyButton({ code, size }: { code: string; size?: "sm" | "md" }) {
export function CodeGroup({
children,
size,
size = "md",
className,
}: {
children: React.ReactNode;
size?: "sm" | "md";
size?: "md" | "lg";
className?: string;
}) {
const textRef = useRef<HTMLPreElement | null>(null);
@@ -86,13 +86,14 @@ export function CodeGroup({
}, [children]);
return (
<div className={clsx(className, "group relative")}>
<div className={clsx(className, "not-prose group relative")}>
<pre
className={clsx(
"h-full border p-0 bg-stone-50 dark:bg-stone-925",
"h-full overflow-x-auto",
"border rounded-md p-0 bg-stone-50 dark:bg-stone-925",
"text-black dark:text-white",
{
"text-sm": size === "sm",
"text-sm": size === "md",
},
)}
ref={textRef}

View File

@@ -31,7 +31,7 @@ export function Footer({
themeToggle: ThemeToggle,
}: FooterProps) {
return (
<footer className="w-full py-8 mt-12 md:mt-20">
<footer className="w-full pt-8 pb-20 mt-12 md:mt-20 md:pb-8">
<div className="container grid gap-8 md:gap-12">
<div className="grid grid-cols-12 gap-y-3 sm:items-center pb-8 border-b">
<div className="col-span-full sm:col-span-6 md:col-span-8">

View File

@@ -10,14 +10,7 @@ import {
import clsx from "clsx";
import Link from "next/link";
import { usePathname } from "next/navigation";
import {
ComponentType,
ReactNode,
useEffect,
useLayoutEffect,
useRef,
useState,
} from "react";
import { ComponentType, ReactNode, useEffect, useState } from "react";
import { Icon } from "../atoms/Icon";
import { BreadCrumb } from "../molecules/Breadcrumb";
import { SocialLinks, SocialLinksProps } from "./SocialLinks";
@@ -35,10 +28,16 @@ type NavItemProps = {
type NavProps = {
mainLogo: ReactNode;
items: NavItemProps[];
docNav?: ReactNode;
cta?: ReactNode;
socials?: SocialLinksProps;
themeToggle: ComponentType<{ className?: string }>;
sections?: NavSection[];
};
export type NavSection = {
name: string;
content: ReactNode;
icon: string;
};
function NavItem({
@@ -68,7 +67,7 @@ function NavItem({
className,
"text-sm px-2 lg:px-4 py-3 ",
firstOnRight && "ml-auto",
path === href ? "text-black dark:text-white" : "",
path === href ? "text-stone-900 dark:text-white" : "",
)}
{...item}
>
@@ -81,8 +80,8 @@ function NavItem({
<Popover className={clsx("relative", className, firstOnRight && "ml-auto")}>
<PopoverButton
className={clsx(
"flex items-center gap-1.5 text-sm px-2 lg:px-4 py-3 max-sm:w-full text-stone-600 dark:text-stone-400 hover:text-black dark:hover:text-white transition-colors hover:transition-none focus-visible:outline-none",
path === href ? "text-black dark:text-white" : "",
"flex items-center gap-1.5 text-sm px-2 lg:px-4 py-3 max-sm:w-full hover:text-stone-900 dark:hover:text-white transition-colors hover:transition-none focus-visible:outline-none",
path === href ? "text-stone-900 dark:text-white" : "",
)}
>
<span>{title}</span>
@@ -128,25 +127,57 @@ function NavItem({
export function MobileNav({
mainLogo,
items,
docNav,
cta,
socials,
sections,
themeToggle: ThemeToggle,
}: NavProps) {
const [menuOpen, setMenuOpen] = useState(false);
const [searchOpen, setSearchOpen] = useState(false);
const searchRef = useRef<HTMLInputElement>(null);
const primarySection = {
name: "Menu",
icon: "menu",
content: (
<>
<div className="flex items-center justify-between border-b p-3">
<Link href="/" className="flex items-center">
{mainLogo}
</Link>
useLayoutEffect(() => {
searchOpen && searchRef.current?.focus();
}, [searchOpen]);
<SocialLinks {...socials} className="ml-auto" />
<ThemeToggle className="ml-4 mr-1" />
</div>
<div className="flex flex-col gap-2 p-3">
{items
.filter((item) => !("icon" in item))
.map((item, i) => (
<NavLink
className="p-1"
key={i}
href={item.href}
onClick={() => setActive(null)}
newTab={item.newTab}
>
{item.title}
</NavLink>
))}
</div>
</>
),
};
const [active, setActive] = useState<string | null>();
const pathname = usePathname();
useEffect(() => {
setMenuOpen(false);
setActive(null);
}, [pathname]);
const toggle = (type: string) => {
setActive(active == type ? null : type);
};
const navSections = [primarySection, ...(sections || [])];
return (
<>
<div className="md:hidden px-4 flex items-center self-stretch dark:text-white">
@@ -155,9 +186,8 @@ export function MobileNav({
</NavLinkLogo>
<button
className="flex gap-2 p-3 rounded-xl items-center"
onMouseDown={() => {
setMenuOpen((o) => !o);
setSearchOpen(false);
onClick={() => {
setActive("Menu");
}}
aria-label="Open menu"
>
@@ -165,80 +195,70 @@ export function MobileNav({
<BreadCrumb items={items} />
</button>
</div>
<div
onClick={() => {
setMenuOpen(false);
setSearchOpen(false);
setActive(null);
}}
className={clsx(
menuOpen || searchOpen ? "block" : "hidden",
"fixed top-0 bottom-0 left-0 right-0 bg-stone-200/80 dark:bg-black/80 w-full h-full z-20",
!!active ? "block" : "hidden",
"md:hidden fixed backdrop-blur-sm top-0 bottom-0 left-0 right-0 bg-stone-200/80 dark:bg-black/80 w-full h-full z-20",
)}
></div>
<nav
<div
className={clsx(
"md:hidden fixed flex flex-col bottom-4 right-4 z-50",
"bg-stone-50 dark:bg-stone-925 border rounded-lg shadow-lg",
menuOpen || searchOpen ? "left-4" : "",
"md:hidden bg-white border fixed z-50",
"dark:bg-stone-925",
{
"rounded-lg right-6 left-6 bottom-6 sm:max-w-lg sm:w-full shadow-md sm:left-1/2 sm:-translate-x-1/2 ":
!!active,
"rounded-full shadow-sm left-1/2 -translate-x-1/2 bottom-7":
!active,
},
)}
>
<div className={clsx(menuOpen ? "block" : "hidden", " px-2 pb-2")}>
<div className="flex items-center w-full border-b">
<NavLinkLogo
prominent
href="/"
className="mr-auto"
onClick={() => setMenuOpen(false)}
>
{mainLogo}
</NavLinkLogo>
<SocialLinks className="px-2 gap-2" {...socials} />
</div>
{pathname.startsWith("/docs") && docNav && (
<div className="max-h-[calc(100dvh-15rem)] p-4 border-b overflow-x-auto">
{docNav}
</div>
)}
<div className="flex flex-wrap justify-end py-2 gap-x-3 gap-y-1 border-b">
{[{ title: "Home", href: "/" }, ...items]
.filter((item) => !("icon" in item))
.map((item, i) => (
<NavLink
className="p-1 text-sm"
key={i}
href={item.href}
onClick={() => setMenuOpen(false)}
newTab={item.newTab}
>
{item.title}
</NavLink>
))}
</div>
</div>
<div className="flex items-center self-stretch justify-between">
{(menuOpen || searchOpen) && <ThemeToggle className="p-3" />}
<button
className="flex gap-2 p-3 rounded-xl items-center"
onMouseDown={() => {
setMenuOpen((o) => !o);
setSearchOpen(false);
}}
aria-label="Close menu"
>
{menuOpen || searchOpen ? (
<Icon name="close" />
) : (
<>
<Icon name="menu" />
<BreadCrumb items={items} />
</>
{active && (
<div
className={clsx(
"max-h-[calc(100vh-16rem)] overflow-y-auto",
active === "Menu" ? "" : "p-3 pb-10",
)}
</button>
>
{navSections.map((section) =>
section.name == active ? section.content : null,
)}
</div>
)}
<div
className={clsx("flex justify-center py-1 px-1.5", {
"border-t py-2": !!active,
})}
>
{navSections.map(
(section) =>
section.content && (
<button
type="button"
className={clsx(
"flex items-center gap-1 px-2 py-1 text-sm rounded-md whitespace-nowrap",
"text-stone-900 dark:text-white",
{
"bg-stone-100 dark:bg-stone-900": active === section.name,
},
)}
onClick={() => toggle(section.name)}
key={section.name}
>
<Icon name={section.icon} size="xs" />
{section.name}
</button>
),
)}
</div>
</nav>
</div>
</>
);
}
@@ -262,7 +282,7 @@ function NavLink({
<Link
href={href}
className={clsx(
"text-stone-600 dark:text-stone-400 hover:text-black dark:hover:text-white transition-colors hover:transition-none",
"hover:text-stone-900 dark:hover:text-white transition-colors hover:transition-none",
className,
)}
onClick={onClick}
@@ -310,7 +330,7 @@ function NavLinkLogo({
}
export function Nav(props: NavProps) {
const { mainLogo, items, docNav, cta } = props;
const { mainLogo, items, cta } = props;
return (
<>
<div className="w-full border-b py-2 sticky top-0 z-50 bg-white dark:bg-stone-950 hidden md:block">

View File

@@ -42,7 +42,12 @@ const socials = [
export function SocialLinks(props: SocialLinksProps & { className?: string }) {
return (
<div className={clsx(props.className, "inline-flex gap-6 items-center")}>
<div
className={clsx(
props.className,
"inline-flex gap-3 items-center sm:gap-6",
)}
>
{socials.map(
(social) =>
props[social.key as keyof SocialLinksProps] && (

View File

@@ -0,0 +1,15 @@
import { ApiNav } from "@/components/docs/ApiNav";
import DocsLayout from "@/components/docs/DocsLayout";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<DocsLayout nav={<ApiNav />} navIcon="package" navName="API Ref">
<Prose className="overflow-x-hidden lg:flex-1 py-8">{children}</Prose>
</DocsLayout>
);
}

View File

@@ -1,13 +1,6 @@
import DocsLayout from "@/components/docs/DocsLayout";
import { DocNav } from "@/components/docs/nav";
export const metadata = {
title: {
default: "Documentation",
template: "%s | Jazz",
},
description: "Jazz guide and documentation.",
};
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export default function Layout({
children,
@@ -16,7 +9,7 @@ export default function Layout({
}) {
return (
<DocsLayout nav={<DocNav />}>
<div className="flex justify-center lg:gap-5">{children}</div>
<Prose className="max-w-3xl mx-auto lg:flex-1 py-8">{children}</Prose>
</DocsLayout>
);
}

View File

@@ -1,7 +1,8 @@
import MdxSource from "@/components/docs/docs-intro.mdx";
import { frameworks } from "@/lib/framework";
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
import { HeroHeader } from "gcmp-design-system/src/app/components/molecules/HeroHeader";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import MdxSource from "../../../../../components/docs/docs-intro.mdx";
import { frameworks } from "../../../../../lib/framework";
export default function Page() {
return (

View File

@@ -349,7 +349,7 @@ This works because CoValues
1. Directly on an instance:
<CodeGroup size="sm">
<CodeGroup>
```ts
const unsub = issue.subscribe([], (updatedIssue) => console.log(updatedIssue));
```
@@ -357,7 +357,7 @@ This works because CoValues
2. If you only have an ID (this will load the issue if needed):
<CodeGroup size="sm">
<CodeGroup>
```ts
const unsub = Issue.subscribe(issueID, me, [], (updatedIssue) => {
console.log(updatedIssue);
@@ -373,7 +373,7 @@ This works because CoValues
By the way, `useCoState` is basically just an optimized version of
<CodeGroup size="sm">
<CodeGroup>
```ts
function useCoState<V extends CoValue>(Schema: CoValueClass<V>, id?: ID<V>): V | undefined {
const [value, setValue] = useState<V>();

View File

@@ -1,46 +1,11 @@
import DocsLayout from "@/app/docs/[framework]/(others)/layout";
import DocsLayout from "@/components/docs/DocsLayout";
import { TableOfContents } from "@/components/docs/TableOfContents";
import ComingSoonPage from "@/components/docs/coming-soon.mdx";
import { DocNav } from "@/components/docs/nav";
import { docNavigationItems } from "@/lib/docNavigationItems.js";
import { Framework, frameworks } from "@/lib/framework";
import type { Toc } from "@stefanprobst/rehype-extract-toc";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
import { Metadata } from "next";
async function getMdxSource(slugPath: string, framework: string) {
try {
return await import(`./${slugPath}.mdx`);
} catch (error) {
return await import(`./${slugPath}/${framework}.mdx`);
}
}
export async function generateMetadata({
params: { slug, framework },
}: {
params: { slug: string[]; framework: string };
}): Promise<Metadata> {
const slugPath = slug.join("/");
const title = "Coming soon";
try {
const mdxSource = await getMdxSource(slugPath, framework);
const title = mdxSource.metadata.title;
return {
title,
openGraph: {
title,
},
};
} catch (error) {
return {
title,
openGraph: {
title,
},
};
}
}
export default async function Page({
params: { slug, framework },
@@ -48,24 +13,31 @@ export default async function Page({
const slugPath = slug.join("/");
try {
const mdxSource = await getMdxSource(slugPath, framework);
let mdxSource;
try {
mdxSource = await import(`./${slugPath}.mdx`);
} catch (error) {
mdxSource = await import(`./${slugPath}/${framework}.mdx`);
}
const { default: Content, tableOfContents } = mdxSource;
// Exclude h1 from table of contents
const tocItems = (tableOfContents as Toc)?.[0]?.children;
return (
<>
<DocsLayout toc={tocItems} nav={<DocNav />}>
<Prose className="overflow-x-hidden lg:flex-1 py-8">
<Content />
</Prose>
{tocItems && <TableOfContents items={tocItems} />}
</>
</DocsLayout>
);
} catch (error) {
return (
<DocsLayout>
<ComingSoonPage />
<DocsLayout nav={<DocNav />}>
<Prose className="overflow-x-hidden lg:flex-1 py-8">
<ComingSoonPage className="max-w-3xl mx-auto" />
</Prose>
</DocsLayout>
);
}

View File

@@ -17,12 +17,12 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
<CodeGroup>
{/* prettier-ignore */}
```ts
import { useState } from "react";
import { Issue } from "./schema";
import { IssueComponent } from "./components/Issue.tsx";
import { useState } from "react";
import { Issue } from "./schema";
import { IssueComponent } from "./components/Issue.tsx";
function App() {
const [issue, setIssue] = useState<Issue>();
const [issue, setIssue] = useState<Issue>();
const createIssue = () => {
setIssue(Issue.create(
{
@@ -33,13 +33,13 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
}, // The owner defaults now to a group managed by the current user!
));
};
if (issue) {
return <IssueComponent issue={issue} />;
} else {
return <IssueComponent issue={issue} />;
} else {
return <button onClick={createIssue}>Create Issue</button>;
}
}
}
}
```
</CodeGroup>
@@ -71,4 +71,4 @@ export const metadata = { title: "Upgrade to Jazz 0.9.0" };
Everything is backward compatible, so no upgrade steps are required.
With this Jazz API becomes way more lean and more is coming!
</div>
</div>

View File

@@ -0,0 +1,14 @@
import { JazzNav } from "@/components/nav";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex-1 w-full">
<JazzNav />
<main>{children}</main>
</div>
);
}

View File

@@ -1,21 +0,0 @@
import { ApiNav } from "@/components/docs/ApiNav";
import DocsLayout from "@/components/docs/DocsLayout";
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export const metadata = {
title: "API reference",
description:
"API references for packages like jazz-tools, jazz-react, and more.",
};
export default function Layout({
children,
}: {
children: React.ReactNode;
}) {
return (
<DocsLayout nav={<ApiNav />}>
<Prose className="py-8 [&_*]:scroll-mt-[8rem]">{children}</Prose>
</DocsLayout>
);
}

View File

@@ -1,13 +0,0 @@
import { Prose } from "gcmp-design-system/src/app/components/molecules/Prose";
export default function DocsLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<Prose className="max-w-3xl mx-auto overflow-x-hidden lg:flex-1 py-8">
{children}
</Prose>
);
}

View File

@@ -6,7 +6,6 @@ import localFont from "next/font/local";
import { ThemeProvider } from "@/components/ThemeProvider";
import { JazzFooter } from "@/components/footer";
import { JazzNav } from "@/components/nav";
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/next";
@@ -98,10 +97,7 @@ export default function RootLayout({
enableSystem
disableTransitionOnChange
>
<div className="flex-1 w-full">
<JazzNav />
<main>{children}</main>
</div>
{children}
<JazzFooter />
</ThemeProvider>
</body>

View File

@@ -1,25 +1,68 @@
import { TableOfContents } from "@/components/docs/TableOfContents";
import { JazzNav } from "@/components/nav";
import { Toc } from "@stefanprobst/rehype-extract-toc";
import { clsx } from "clsx";
export default function DocsLayout({
children,
nav,
navName,
navIcon,
toc,
}: {
children: React.ReactNode;
nav?: React.ReactNode;
navName?: string;
navIcon?: string;
toc?: Toc;
}) {
const navSections = [
{
name: navName || "Docs",
content: nav,
icon: navIcon || "docs",
},
{
name: "Outline",
content: toc && (
<TableOfContents className="text-sm" items={toc as Toc} />
),
icon: "tableOfContents",
},
];
return (
<div className="container relative grid grid-cols-12 gap-5">
<div
className={clsx(
"py-8",
"pr-3 md:col-span-4 lg:col-span-3",
"sticky align-start top-[65px] h-[calc(100vh-65px)] overflow-y-auto overflow-x-hidden",
"hidden md:block",
)}
>
{nav}
</div>
<div className="col-span-12 md:col-span-8 lg:col-span-9">{children}</div>
<div className="flex-1 w-full">
<JazzNav sections={navSections} />
<main>
<div className="container relative grid grid-cols-12 gap-5">
<div
className={clsx(
"py-8",
"pr-3 md:col-span-4 lg:col-span-3",
"sticky align-start top-[65px] h-[calc(100vh-65px)] overflow-y-auto overflow-x-hidden",
"hidden md:block",
)}
>
{nav}
</div>
<div
className={clsx(
"col-span-12 md:col-span-8 lg:col-span-9 flex gap-3",
)}
>
{children}
{toc && (
<>
<TableOfContents
className="pl-3 py-6 shrink-0 text-sm sticky align-start top-[65px] w-[16rem] h-[calc(100vh-65px)] overflow-y-auto overflow-x-hidden hidden lg:block"
items={toc as Toc}
/>
</>
)}
</div>
</div>
</main>
</div>
);
}

View File

@@ -2,13 +2,13 @@ import type { Toc, TocEntry } from "@stefanprobst/rehype-extract-toc";
import { clsx } from "clsx";
import Link from "next/link";
const TocList = ({ items }: { items: TocEntry[] }) => {
const TocList = ({ items, level }: { items: TocEntry[]; level: number }) => {
return (
<ul className="list-disc pl-4 space-y-2">
<ul className="space-y-3" style={{ paddingLeft: `${level * 1}rem` }}>
{items.map((item) => (
<li key={item.id} className="space-y-2">
<li key={item.id} className="space-y-3">
<Link href={`#${item.id}`}>{item.value}</Link>
{item.children && <TocList items={item.children} />}
{item.children && <TocList items={item.children} level={level + 1} />}
</li>
))}
</ul>
@@ -25,14 +25,11 @@ export function TableOfContents({
if (!items.length) return null;
return (
<div
className={clsx(
"pl-3 py-6 text-sm sticky align-start top-[65px] w-[16rem] h-[calc(100vh-65px)] overflow-y-auto overflow-x-hidden hidden lg:block",
className,
)}
>
<p className="mb-3">On this page:</p>
<TocList items={items} />
<div className={className}>
<p className="font-medium text-stone-900 dark:text-white mb-3">
On this page
</p>
<TocList items={items} level={0} />
</div>
);
}

View File

@@ -2,13 +2,16 @@ import { ThemeToggle } from "@/components/ThemeToggle";
import { socials } from "@/lib/socials";
import { useFramework } from "@/lib/use-framework";
import { JazzLogo } from "gcmp-design-system/src/app/components/atoms/logos/JazzLogo";
import { Nav } from "gcmp-design-system/src/app/components/organisms/Nav";
import { DocNav } from "./docs/nav";
import {
Nav,
type NavSection,
} from "gcmp-design-system/src/app/components/organisms/Nav";
export function JazzNav() {
export function JazzNav({ sections }: { sections?: NavSection[] }) {
return (
<Nav
mainLogo={<JazzLogo className="w-24" />}
sections={sections}
mainLogo={<JazzLogo className="w-20 md:w-24" />}
themeToggle={ThemeToggle}
items={[
{ title: "Jazz Cloud", href: "/cloud" },
@@ -46,7 +49,6 @@ export function JazzNav() {
},
]}
socials={socials}
docNav={<DocNav className="block h-auto" />}
/>
);
}