Skip to content

Commit 788c5b8

Browse files
matthewlipskiYousefEDnperez0111
authored
feat: toggle blocks (#1707)
Co-authored-by: yousefed <[email protected]> Co-authored-by: Nick the Sick <[email protected]>
1 parent 8fe92ba commit 788c5b8

File tree

342 files changed

+3046
-1077
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

342 files changed

+3046
-1077
lines changed

examples/01-basic/04-default-blocks/App.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ export default function App() {
3232
type: "heading",
3333
content: "Heading",
3434
},
35+
{
36+
id: "toggle-heading",
37+
type: "heading",
38+
props: { isToggleable: true },
39+
content: "Toggle Heading",
40+
},
3541
{
3642
type: "quote",
3743
content: "Quote",
@@ -48,6 +54,11 @@ export default function App() {
4854
type: "checkListItem",
4955
content: "Check List Item",
5056
},
57+
{
58+
id: "toggle-list-item",
59+
type: "toggleListItem",
60+
content: "Toggle List Item",
61+
},
5162
{
5263
type: "codeBlock",
5364
props: { language: "javascript" },
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"playground": true,
3+
"docs": true,
4+
"author": "matthewlipski",
5+
"tags": ["Basic"]
6+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { BlockNoteSchema, defaultBlockSpecs } from "@blocknote/core";
2+
import "@blocknote/core/fonts/inter.css";
3+
import { BlockNoteView } from "@blocknote/mantine";
4+
import "@blocknote/mantine/style.css";
5+
import { useCreateBlockNote } from "@blocknote/react";
6+
7+
import { ToggleBlock } from "./Toggle.js";
8+
9+
// Our schema with block specs, which contain the configs and implementations for
10+
// blocks that we want our editor to use.
11+
const schema = BlockNoteSchema.create({
12+
blockSpecs: {
13+
// Adds all default blocks.
14+
...defaultBlockSpecs,
15+
// Adds the Toggle block.
16+
toggle: ToggleBlock,
17+
},
18+
});
19+
20+
export default function App() {
21+
// Creates a new editor instance.
22+
const editor = useCreateBlockNote({
23+
schema,
24+
initialContent: [
25+
{
26+
type: "paragraph",
27+
content: "Welcome to this demo!",
28+
},
29+
{
30+
// We set a persistent ID so that the toggled state is preserved
31+
// on reload.
32+
id: "toggle",
33+
type: "toggle",
34+
content: "This is an example toggle",
35+
children: [
36+
{
37+
type: "paragraph",
38+
content: "This is the first child of the toggle block.",
39+
},
40+
{
41+
type: "paragraph",
42+
content: "This is the second child of the toggle block.",
43+
},
44+
],
45+
},
46+
{
47+
type: "paragraph",
48+
content: "Click the '>' icon to show/hide its children",
49+
},
50+
{
51+
type: "paragraph",
52+
},
53+
],
54+
});
55+
56+
// Renders the editor instance.
57+
return <BlockNoteView editor={editor} />;
58+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Toggleable Custom Blocks
2+
3+
This example shows how to create custom blocks with a toggle button to show/hide their children, like with the default toggle heading and list item blocks. This is done using the use the `ToggleWrapper` component from `@blocknote/react`.
4+
5+
**Relevant Docs:**
6+
7+
- [Custom Blocks](/docs/custom-schemas/custom-blocks)
8+
- [Editor Setup](/docs/editor-basics/setup)
9+
- [Default Schema](/docs/editor-basics/default-schema)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { defaultProps } from "@blocknote/core";
2+
import { createReactBlockSpec, ToggleWrapper } from "@blocknote/react";
3+
4+
// The Toggle block that we want to add to our editor.
5+
export const ToggleBlock = createReactBlockSpec(
6+
{
7+
type: "toggle",
8+
propSchema: {
9+
...defaultProps,
10+
},
11+
content: "inline",
12+
},
13+
{
14+
render: (props) => (
15+
// The `ToggleWrapper` component renders a button on the left which
16+
// toggles the visibility of the block's children. It also adds a button
17+
// to add child blocks if there are none. By default, it uses local
18+
// storage to remember the toggled state based on the block ID, but you can pass a custom
19+
// `toggledState` prop to use a different storage mechanism.
20+
<ToggleWrapper block={props.block} editor={props.editor}>
21+
<p ref={props.contentRef} />
22+
</ToggleWrapper>
23+
),
24+
},
25+
);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<html lang="en">
2+
<head>
3+
<script>
4+
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
5+
</script>
6+
<meta charset="UTF-8" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+
<title>Toggleable Blocks</title>
9+
</head>
10+
<body>
11+
<div id="root"></div>
12+
<script type="module" src="./main.tsx"></script>
13+
</body>
14+
</html>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
2+
import React from "react";
3+
import { createRoot } from "react-dom/client";
4+
import App from "./App.jsx";
5+
6+
const root = createRoot(document.getElementById("root")!);
7+
root.render(
8+
<React.StrictMode>
9+
<App />
10+
</React.StrictMode>
11+
);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@blocknote/example-toggleable-blocks",
3+
"description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
4+
"private": true,
5+
"version": "0.12.4",
6+
"scripts": {
7+
"start": "vite",
8+
"dev": "vite",
9+
"build:prod": "tsc && vite build",
10+
"preview": "vite preview"
11+
},
12+
"dependencies": {
13+
"@blocknote/core": "latest",
14+
"@blocknote/react": "latest",
15+
"@blocknote/ariakit": "latest",
16+
"@blocknote/mantine": "latest",
17+
"@blocknote/shadcn": "latest",
18+
"react": "^18.3.1",
19+
"react-dom": "^18.3.1"
20+
},
21+
"devDependencies": {
22+
"@types/react": "^18.0.25",
23+
"@types/react-dom": "^18.0.9",
24+
"@vitejs/plugin-react": "^4.3.1",
25+
"vite": "^5.3.4"
26+
}
27+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"__comment": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
3+
"compilerOptions": {
4+
"target": "ESNext",
5+
"useDefineForClassFields": true,
6+
"lib": [
7+
"DOM",
8+
"DOM.Iterable",
9+
"ESNext"
10+
],
11+
"allowJs": false,
12+
"skipLibCheck": true,
13+
"esModuleInterop": false,
14+
"allowSyntheticDefaultImports": true,
15+
"strict": true,
16+
"forceConsistentCasingInFileNames": true,
17+
"module": "ESNext",
18+
"moduleResolution": "bundler",
19+
"resolveJsonModule": true,
20+
"isolatedModules": true,
21+
"noEmit": true,
22+
"jsx": "react-jsx",
23+
"composite": true
24+
},
25+
"include": [
26+
"."
27+
],
28+
"__ADD_FOR_LOCAL_DEV_references": [
29+
{
30+
"path": "../../../packages/core/"
31+
},
32+
{
33+
"path": "../../../packages/react/"
34+
}
35+
]
36+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
2+
import react from "@vitejs/plugin-react";
3+
import * as fs from "fs";
4+
import * as path from "path";
5+
import { defineConfig } from "vite";
6+
// import eslintPlugin from "vite-plugin-eslint";
7+
// https://vitejs.dev/config/
8+
export default defineConfig((conf) => ({
9+
plugins: [react()],
10+
optimizeDeps: {},
11+
build: {
12+
sourcemap: true,
13+
},
14+
resolve: {
15+
alias:
16+
conf.command === "build" ||
17+
!fs.existsSync(path.resolve(__dirname, "../../packages/core/src"))
18+
? {}
19+
: ({
20+
// Comment out the lines below to load a built version of blocknote
21+
// or, keep as is to load live from sources with live reload working
22+
"@blocknote/core": path.resolve(
23+
__dirname,
24+
"../../packages/core/src/"
25+
),
26+
"@blocknote/react": path.resolve(
27+
__dirname,
28+
"../../packages/react/src/"
29+
),
30+
} as any),
31+
},
32+
}));

0 commit comments

Comments
 (0)