Skip to content

docs: Examples, footer, and remaining pages #1784

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 23, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added examples card grid and fixed demo styling
  • Loading branch information
matthewlipski committed Jun 20, 2025
commit cba5b056eb8f68a6836f04ee2159e38ad40ba3fc
2 changes: 1 addition & 1 deletion fumadocs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ next-env.d.ts

# Sentry Config File
.env.sentry-build-plugin
/content/examples/*/
/content/examples/**/*.mdx
/components/example/generated/
/.source/
24 changes: 24 additions & 0 deletions fumadocs/components/ThemedExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"use client";

import { BlockNoteContext } from "@blocknote/react";
import dynamic from "next/dynamic";
import { useTheme } from "next-themes";

export default function ThemedExample(props: { name: string }) {
const Component = dynamic(
() => import("./example/generated/components/" + props.name + "/index"),
{ ssr: false },
);

const { resolvedTheme } = useTheme();

return (
<BlockNoteContext.Provider
value={{
colorSchemePreference: resolvedTheme === "dark" ? "dark" : "light",
}}
>
<Component />
</BlockNoteContext.Provider>
);
}
73 changes: 38 additions & 35 deletions fumadocs/components/example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,67 +29,69 @@ const baseGitHubURL = "https://github.com/TypeCellOS/BlockNote/tree/main/";
const baseStackBlitzURL =
"https://www.stackblitz.com/github/TypeCellOS/BlockNote/tree/main/";

// const ThemedExample = dynamic(() => import("./ThemedExample"), {
// ssr: false,
// });
const ThemedExample = dynamic(() => import("./ThemedExample"));

export async function Example(props: {
name: string;
path: string;
children: any;
pro?: boolean;
}) {
const Component = dynamic(
() => import("./example/generated/components/" + props.name + "/index"),
);
// const showCode =
// !props.isProExample ||
// props.isProExample.userStatus === "starter" ||
// props.isProExample.userStatus === "business";
const showCode = true;

return (
<div className="demo nx-bg-primary-700/5 dark:nx-bg-primary-300/10 mt-6 rounded-lg p-4">
{showCode && (
<div className={"z-10 flex flex-row gap-6 pb-4"}>
<a
className={
"nx-select-none nx-text-gray-600 hover:nx-text-black dark:nx-text-gray-200 dark:hover:nx-text-white flex flex-row items-center gap-1"
}
href={`${baseGitHubURL}${props.path}/`}
target="_blank"
rel="noreferrer">
<AiFillGithub />
<div className={"text-sm"}>GitHub</div>
</a>
<a
className={
"nx-select-none nx-text-gray-600 hover:nx-text-black dark:nx-text-gray-200 dark:hover:nx-text-white flex flex-row items-center gap-1"
}
href={`${baseStackBlitzURL}${props.path}/`}
target="_blank"
rel="noreferrer">
<SiStackblitz />
<div className={"text-sm"}>StackBlitz</div>
</a>
<div className="demo">
<div className="not-prose bg-fd-secondary border-fd-border flex h-[600px] flex-col rounded-xl border">
{showCode && (
<div className={"flex items-center gap-4 px-4"}>
<a
className={
"hover:text-fd-accent-foreground flex items-center gap-1 py-2 text-sm font-medium"
}
href={`${baseGitHubURL}${props.path}/`}
target="_blank"
rel="noreferrer"
>
<AiFillGithub size={16} />
<div>GitHub</div>
</a>
<a
className={
"hover:text-fd-accent-foreground flex items-center gap-1 py-2 text-sm font-medium"
}
href={`${baseStackBlitzURL}${props.path}/`}
target="_blank"
rel="noreferrer"
>
<SiStackblitz size={16} />
<div className={"text-sm"}>StackBlitz</div>
</a>
</div>
)}
<div
className={"demo-contents bg-fd-background h-0 flex-1 rounded-xl p-4"}
>
<ThemedExample name={props.name} />
</div>
)}
<div className={"demo-contents h-96 overflow-auto rounded-lg"}>
<Component />
</div>
{showCode ? (
props.children
) : (
<div
className={
"relative flex h-96 flex-col items-center justify-center gap-2"
}>
}
>
<div className={"absolute h-1/2 w-1/2"}>
<div className={"cta-glow h-full w-full"}></div>
</div>
<div className={"z-10 flex w-2/3 flex-col items-center"}>
<SectionHeader>Pro Example</SectionHeader>
<p className={"text-center text-[#00000080] dark:text-[#FFFFFFB2]"}>
<p className={"text-center"}>
Get access to the full source code for pro examples by subscribing
to BlockNote Pro
</p>
Expand All @@ -98,7 +100,8 @@ export async function Example(props: {
href={"/pricing"}
color={"pro"}
size={"large"}
hoverGlow={true}>
hoverGlow={true}
>
Get BlockNote Pro
</CTAButton>
</div>
Expand Down
98 changes: 98 additions & 0 deletions fumadocs/content/examples/ExampleCards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { source } from "@/lib/source/examples";
import { Card, Cards } from "fumadocs-ui/components/card";
import { Heading } from "fumadocs-ui/components/heading";
import { examplesMeta } from "@/.source";
import { useMemo } from "react";

type CardData = {
title: string;
author: string;
href: string;
};

type CardGroupData = {
groupName: string;
cards: CardData[];
};

export function ExampleCards() {
// Creates card groups in the order the example & example categories appear
// in the sidebar (i.e. from `meta.json` files in the `content/examples`
// directory).
const cardGroups = useMemo<CardGroupData[]>(() => {
// Indexes all example pages by their URL.
const pagesByUrl = Object.fromEntries(
source.getPages().map((page) => [page.url, page]),
);

// Gets metadata for root examples directory.
const rootMeta =
examplesMeta[
examplesMeta.findIndex((meta) => {
return meta.root;
})
];

return (
rootMeta.pages
// Filters out the page showing all examples.
.filter((exampleCategoryName) => exampleCategoryName !== "index")
// Maps each example category to a `CardGroupData` object.
.map((exampleCategoryName) => {
// Gets metadata for the example category directory ("basic",
// "collaboration", "theming", etc).
const exampleMeta = examplesMeta.find(
(exampleMeta) =>
exampleMeta._file.path.replace("/meta.json", "") ===
exampleCategoryName,
)!;

return {
groupName: exampleMeta.title,
// Maps each example in the category to a `CardData` object.
cards: (exampleMeta.pages || []).map((exampleName) => {
// Gets the page for the example by its URL, which contains the
// example URL and frontmatter data (title & author).
const page =
pagesByUrl[`/examples/${exampleCategoryName}/${exampleName}`];

return {
title: page.data.title,
author: page.data.author!,
href: page.url,
};
}),
};
})
);
}, []);

return (
<>
{cardGroups.map((group) => (
<>
<Heading key={group.groupName}>{group.groupName}</Heading>
<Cards key={group.groupName} className="mb-8">
{group.cards.map((card) => (
<Card
key={card.href}
icon={
card.author ? (
<img
src={`https://github.com/${card.author}.png`}
alt={card.author}
width={32}
/>
) : undefined
}
title={card.title}
description={card.author ? `by ${card.author}` : undefined}
href={card.href}
/>
))}
</Cards>
</>
))}
</>
);
}
4 changes: 4 additions & 0 deletions fumadocs/content/examples/ai/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"title": "AI",
"pages": ["minimal", "playground", "custom-ai-menu-items"]
}
9 changes: 9 additions & 0 deletions fumadocs/content/examples/backend/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"title": "Backend",
"pages": [
"file-uploading",
"saving-loading",
"s3",
"rendering-static-documents"
]
}
18 changes: 18 additions & 0 deletions fumadocs/content/examples/basic/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"title": "Basic",
"pages": [
"minimal",
"block-objects",
"multi-column",
"default-blocks",
"removing-default-blocks",
"block-manipulation",
"selection-blocks",
"ariakit",
"shadcn",
"localization",
"custom-placeholder",
"multi-editor",
"custom-paste-handler"
]
}
10 changes: 10 additions & 0 deletions fumadocs/content/examples/collaboration/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"title": "Collaboration",
"pages": [
"partykit",
"liveblocks",
"y-sweet",
"comments",
"comments-with-sidebar"
]
}
10 changes: 10 additions & 0 deletions fumadocs/content/examples/custom-schema/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"title": "Custom Schema",
"pages": [
"alert-block",
"suggestion-menus-mentions",
"font-style",
"pdf-file-block",
"alert-block-full-ux"
]
}
1 change: 1 addition & 0 deletions fumadocs/content/examples/extensions/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "title": "Extensions", "pages": ["tiptap-arrow-conversion"] }
4 changes: 3 additions & 1 deletion fumadocs/content/examples/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ description: Explore BlockNote examples
imageTitle: Examples
---

import { ExampleCards } from "@/content/examples/ExampleCards";

Browse through the examples below to see how to use and customize BlockNote.

Want to contribute? Copy the [basic example on StackBlitz](https://stackblitz.com/github/TypeCellOS/BlockNote/tree/main/examples/01-basic/01-minimal/) and submit a PR.

<MadeByTable />
<ExampleCards />
12 changes: 12 additions & 0 deletions fumadocs/content/examples/interoperability/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"title": "Interoperability",
"pages": [
"converting-blocks-to-html",
"converting-blocks-from-html",
"converting-blocks-to-md",
"converting-blocks-from-md",
"converting-blocks-to-pdf",
"converting-blocks-to-docx",
"converting-blocks-to-odt"
]
}
6 changes: 3 additions & 3 deletions fumadocs/content/examples/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
"pages": [
"index",
"basic",
"theming",
"backend",
"ui-components",
"theming",
"custom-schema",
"collaboration",
"custom-schemas",
"backend",
"ai"
]
}
12 changes: 12 additions & 0 deletions fumadocs/content/examples/theming/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"title": "Theming",
"pages": [
"theming-dom-attributes",
"changing-font",
"theming-css",
"theming-css-variables",
"theming-css-variables-code",
"code-block",
"custom-code-block"
]
}
20 changes: 20 additions & 0 deletions fumadocs/content/examples/ui-components/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"title": "UI Components",
"pages": [
"ui-elements-remove",
"formatting-toolbar-buttons",
"formatting-toolbar-block-type-items",
"side-menu-buttons",
"side-menu-drag-handle-items",
"suggestion-menus-slash-menu-items",
"suggestion-menus-slash-menu-component",
"suggestion-menus-emoji-picker-columns",
"suggestion-menus-emoji-picker-component",
"suggestion-menus-grid-mentions",
"uppy-file-panel",
"static-formatting-toolbar",
"custom-ui",
"experimental-mobile-formatting-toolbar",
"advanced-tables"
]
}
Loading
Loading