diff --git a/examples/04-theming/08-color-combinations/.bnexample.json b/examples/04-theming/08-color-combinations/.bnexample.json
new file mode 100644
index 0000000000..0bd35957f7
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/.bnexample.json
@@ -0,0 +1,8 @@
+{
+ "playground": true,
+ "docs": false,
+ "author": "",
+ "tags": ["Appearance & Styling"],
+ "dependencies": {},
+ "pro": false
+}
diff --git a/examples/04-theming/08-color-combinations/README.md b/examples/04-theming/08-color-combinations/README.md
new file mode 100644
index 0000000000..44381f8dc4
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/README.md
@@ -0,0 +1,9 @@
+# Color combinations
+
+Inspect every combination of the default text and background colors, including the default color, applied to whole blocks and inline content. Switch between light and dark themes to compare their appearance.
+
+**Try me out!** Use the theme toggle above the editors.
+
+## Relevant docs
+
+- [Themes](https://www.blocknotejs.org/docs/react/styling-theming/themes)
diff --git a/examples/04-theming/08-color-combinations/index.html b/examples/04-theming/08-color-combinations/index.html
new file mode 100644
index 0000000000..c1dbc2ed42
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/index.html
@@ -0,0 +1,17 @@
+
+
+
+
+ Color combinations
+
+
+
+
+
+
+
diff --git a/examples/04-theming/08-color-combinations/main.tsx b/examples/04-theming/08-color-combinations/main.tsx
new file mode 100644
index 0000000000..1260513388
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/main.tsx
@@ -0,0 +1,11 @@
+// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
+import React from "react";
+import { createRoot } from "react-dom/client";
+import App from "./src/App.jsx";
+
+const root = createRoot(document.getElementById("root")!);
+root.render(
+
+
+ ,
+);
diff --git a/examples/04-theming/08-color-combinations/package.json b/examples/04-theming/08-color-combinations/package.json
new file mode 100644
index 0000000000..1324705a58
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "@blocknote/example-theming-color-combinations",
+ "description": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
+ "type": "module",
+ "private": true,
+ "version": "0.12.4",
+ "scripts": {
+ "start": "vite",
+ "dev": "vite",
+ "build:prod": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@blocknote/ariakit": "latest",
+ "@blocknote/core": "latest",
+ "@blocknote/mantine": "latest",
+ "@blocknote/react": "latest",
+ "@blocknote/shadcn": "latest",
+ "@mantine/core": "^9.0.2",
+ "@mantine/hooks": "^9.0.2",
+ "react": "^19.2.3",
+ "react-dom": "^19.2.3"
+ },
+ "devDependencies": {
+ "@types/react": "^19.2.3",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^6.0.1",
+ "vite": "^8.0.0"
+ }
+}
diff --git a/examples/04-theming/08-color-combinations/src/App.tsx b/examples/04-theming/08-color-combinations/src/App.tsx
new file mode 100644
index 0000000000..0d3de8fa41
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/src/App.tsx
@@ -0,0 +1,77 @@
+import { COLORS_DEFAULT, type PartialBlock } from "@blocknote/core";
+import "@blocknote/core/fonts/inter.css";
+import { BlockNoteView } from "@blocknote/mantine";
+import "@blocknote/mantine/style.css";
+import { useCreateBlockNote } from "@blocknote/react";
+import { useState } from "react";
+
+const colors = ["default", ...Object.keys(COLORS_DEFAULT)];
+const blockColors: PartialBlock[] = colors.flatMap((backgroundColor) => [
+ {
+ id: `block-heading-${backgroundColor}`,
+ type: "heading",
+ props: { level: 3 },
+ content: `${backgroundColor} background`,
+ },
+ ...colors.map((textColor) => ({
+ id: `block-${backgroundColor}-${textColor}`,
+ type: "paragraph" as const,
+ props: { textColor, backgroundColor },
+ content: `${textColor} text on ${backgroundColor} background`,
+ })),
+]);
+const inlineColors: PartialBlock[] = colors.flatMap((backgroundColor) => [
+ {
+ id: `inline-heading-${backgroundColor}`,
+ type: "heading",
+ props: { level: 3 },
+ content: `${backgroundColor} background`,
+ },
+ ...colors.map((textColor) => ({
+ id: `inline-${backgroundColor}-${textColor}`,
+ type: "paragraph" as const,
+ content: [
+ { type: "text" as const, text: "Inline: ", styles: {} },
+ {
+ type: "text" as const,
+ text: `${textColor} text on ${backgroundColor} background`,
+ styles: { textColor, backgroundColor },
+ },
+ ],
+ })),
+]);
+
+export default function App() {
+ const [theme, setTheme] = useState<"light" | "dark">("light");
+ const blocks = useCreateBlockNote({ initialContent: blockColors });
+ const inline = useCreateBlockNote({ initialContent: inlineColors });
+
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/examples/04-theming/08-color-combinations/tsconfig.json b/examples/04-theming/08-color-combinations/tsconfig.json
new file mode 100644
index 0000000000..2aa62c56e6
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/tsconfig.json
@@ -0,0 +1,32 @@
+{
+ "__comment": "AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY",
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": ["DOM", "DOM.Iterable", "ESNext"],
+ "allowJs": false,
+ "skipLibCheck": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "composite": true,
+ "paths": {
+ "@shared/*": ["../../../shared/*"]
+ }
+ },
+ "include": ["."],
+ "__ADD_FOR_LOCAL_DEV_references": [
+ {
+ "path": "../../../packages/core/"
+ },
+ {
+ "path": "../../../packages/react/"
+ }
+ ]
+}
diff --git a/examples/04-theming/08-color-combinations/vite-env.d.ts b/examples/04-theming/08-color-combinations/vite-env.d.ts
new file mode 100644
index 0000000000..11f02fe2a0
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/04-theming/08-color-combinations/vite.config.ts b/examples/04-theming/08-color-combinations/vite.config.ts
new file mode 100644
index 0000000000..a96f1f04ff
--- /dev/null
+++ b/examples/04-theming/08-color-combinations/vite.config.ts
@@ -0,0 +1,35 @@
+// AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY
+import react from "@vitejs/plugin-react";
+import * as fs from "fs";
+import * as path from "path";
+import { defineConfig } from "vite";
+// https://vitejs.dev/config/
+export default defineConfig(((conf: { command: string }) => ({
+ plugins: [react()],
+ optimizeDeps: {},
+ build: {
+ sourcemap: true,
+ },
+ resolve: {
+ alias:
+ conf.command === "build" ||
+ !fs.existsSync(path.resolve(__dirname, "../../packages/core/src"))
+ ? {}
+ : ({
+ // The repo-wide alias for the shared test-utils directory (private,
+ // so it only resolves inside the monorepo). Harmless for examples
+ // that don't use it.
+ "@shared": path.resolve(__dirname, "../../../shared/"),
+ // Comment out the lines below to load a built version of blocknote
+ // or, keep as is to load live from sources with live reload working
+ "@blocknote/core": path.resolve(
+ __dirname,
+ "../../packages/core/src/",
+ ),
+ "@blocknote/react": path.resolve(
+ __dirname,
+ "../../packages/react/src/",
+ ),
+ } as any),
+ },
+})) as Parameters[0]);
diff --git a/packages/core/src/editor/Block.css b/packages/core/src/editor/Block.css
index 0bc33e6fc0..ab57679d90 100644
--- a/packages/core/src/editor/Block.css
+++ b/packages/core/src/editor/Block.css
@@ -254,11 +254,15 @@ NESTED BLOCKS
/* QUOTES */
[data-content-type="quote"] blockquote {
border-left: 2px solid rgb(125, 121, 122);
- color: rgb(125, 121, 122);
+ color: #646362;
margin: 0;
padding-left: 1em;
}
+[data-content-type="quote"] blockquote:where(.dark, .dark *) {
+ color: #bebdb8;
+}
+
/* DIVIDERS */
[data-content-type="divider"] hr {
border: none;
@@ -420,13 +424,17 @@ NESTED BLOCKS
.bn-toggle-add-block-button {
font-size: 16px;
- color: var(--bn-colors-side-menu);
+ color: #646362;
font-weight: normal;
margin-left: 22px;
padding-inline: 2px;
width: fit-content;
}
+.bn-toggle-add-block-button:where(.dark, .dark *) {
+ color: #bebdb8;
+}
+
.bn-toggle-button,
.bn-toggle-add-block-button {
background: none;
@@ -736,7 +744,7 @@ NESTED BLOCKS
.bn-preview-placeholder:where(.dark, .dark *) {
background-color: rgb(70, 70, 70);
- color: rgb(190, 190, 190);
+ color: #cfcfcf;
}
.bn-editor[contenteditable="true"]
@@ -835,7 +843,7 @@ NESTED BLOCKS
align-items: center;
background-color: rgb(242, 241, 238);
border-radius: 4px;
- color: rgb(125, 121, 122);
+ color: #646362;
display: flex;
gap: 10px;
padding: 12px;
@@ -843,7 +851,7 @@ NESTED BLOCKS
[data-file-block] .bn-add-file-button:where(.dark, .dark *) {
background-color: rgb(70, 70, 70);
- color: rgb(190, 190, 190);
+ color: #cfcfcf;
}
.bn-editor[contenteditable="true"] [data-file-block] .bn-add-file-button:hover,
diff --git a/packages/react/src/editor/styles.css b/packages/react/src/editor/styles.css
index 8ce0056370..a46a238b5e 100644
--- a/packages/react/src/editor/styles.css
+++ b/packages/react/src/editor/styles.css
@@ -2,41 +2,41 @@
/* Default theme params */
.bn-root {
- --bn-colors-editor-text: #3f3f3f;
- --bn-colors-editor-background: #ffffff;
- --bn-colors-menu-text: #3f3f3f;
- --bn-colors-menu-background: #ffffff;
- --bn-colors-tooltip-text: #3f3f3f;
- --bn-colors-tooltip-background: #efefef;
- --bn-colors-hovered-text: #3f3f3f;
- --bn-colors-hovered-background: #efefef;
- --bn-colors-selected-text: #ffffff;
- --bn-colors-selected-background: #3f3f3f;
- --bn-colors-disabled-text: #afafaf;
- --bn-colors-disabled-background: #efefef;
-
- --bn-colors-shadow: #cfcfcf;
- --bn-colors-border: #efefef;
- --bn-colors-side-menu: #cfcfcf;
-
- --bn-colors-highlights-gray-text: #9b9a97;
- --bn-colors-highlights-gray-background: #ebeced;
- --bn-colors-highlights-brown-text: #64473a;
- --bn-colors-highlights-brown-background: #e9e5e3;
- --bn-colors-highlights-red-text: #e03e3e;
- --bn-colors-highlights-red-background: #fbe4e4;
- --bn-colors-highlights-orange-text: #d9730d;
- --bn-colors-highlights-orange-background: #f6e9d9;
- --bn-colors-highlights-yellow-text: #dfab01;
- --bn-colors-highlights-yellow-background: #fbf3db;
- --bn-colors-highlights-green-text: #4d6461;
- --bn-colors-highlights-green-background: #ddedea;
- --bn-colors-highlights-blue-text: #0b6e99;
- --bn-colors-highlights-blue-background: #ddebf1;
- --bn-colors-highlights-purple-text: #6940a5;
- --bn-colors-highlights-purple-background: #eae4f2;
- --bn-colors-highlights-pink-text: #ad1a72;
- --bn-colors-highlights-pink-background: #f4dfeb;
+ --bn-colors-editor-text: oklch(37% 0 0);
+ --bn-colors-editor-background: oklch(100% 0 0);
+ --bn-colors-menu-text: oklch(37% 0 0);
+ --bn-colors-menu-background: oklch(100% 0 0);
+ --bn-colors-tooltip-text: oklch(37% 0 0);
+ --bn-colors-tooltip-background: oklch(95% 0 0);
+ --bn-colors-hovered-text: oklch(37% 0 0);
+ --bn-colors-hovered-background: oklch(95% 0 0);
+ --bn-colors-selected-text: oklch(100% 0 0);
+ --bn-colors-selected-background: oklch(37% 0 0);
+ --bn-colors-disabled-text: oklch(75% 0 0);
+ --bn-colors-disabled-background: oklch(95% 0 0);
+
+ --bn-colors-shadow: oklch(85% 0 0);
+ --bn-colors-border: oklch(95% 0 0);
+ --bn-colors-side-menu: oklch(85% 0 0);
+
+ --bn-colors-highlights-gray-text: oklch(51.6% 0 0);
+ --bn-colors-highlights-gray-background: oklch(93% 0 0);
+ --bn-colors-highlights-brown-text: oklch(48.5% 0.06 50);
+ --bn-colors-highlights-brown-background: oklch(93% 0.015 50);
+ --bn-colors-highlights-red-text: oklch(50.5% 0.1 25);
+ --bn-colors-highlights-red-background: oklch(93% 0.025 25);
+ --bn-colors-highlights-orange-text: oklch(50.5% 0.1 65);
+ --bn-colors-highlights-orange-background: oklch(93% 0.025 65);
+ --bn-colors-highlights-yellow-text: oklch(50.5% 0.1 95);
+ --bn-colors-highlights-yellow-background: oklch(93% 0.025 95);
+ --bn-colors-highlights-green-text: oklch(50.5% 0.1 135);
+ --bn-colors-highlights-green-background: oklch(93% 0.025 135);
+ --bn-colors-highlights-blue-text: oklch(50.5% 0.1 235);
+ --bn-colors-highlights-blue-background: oklch(93% 0.025 235);
+ --bn-colors-highlights-purple-text: oklch(50.5% 0.1 300);
+ --bn-colors-highlights-purple-background: oklch(93% 0.025 300);
+ --bn-colors-highlights-pink-text: oklch(50.5% 0.1 345);
+ --bn-colors-highlights-pink-background: oklch(93% 0.025 345);
--bn-font-family:
"Inter", "Inter fallback", "SF Pro Display", -apple-system,
@@ -54,41 +54,41 @@
}
.bn-root[data-color-scheme="dark"] {
- --bn-colors-editor-text: #cfcfcf;
- --bn-colors-editor-background: #1f1f1f;
- --bn-colors-menu-text: #cfcfcf;
- --bn-colors-menu-background: #1f1f1f;
- --bn-colors-tooltip-text: #cfcfcf;
- --bn-colors-tooltip-background: #161616;
- --bn-colors-hovered-text: #cfcfcf;
- --bn-colors-hovered-background: #161616;
- --bn-colors-selected-text: #cfcfcf;
- --bn-colors-selected-background: #0f0f0f;
- --bn-colors-disabled-text: #3f3f3f;
- --bn-colors-disabled-background: #161616;
-
- --bn-colors-shadow: #0f0f0f;
- --bn-colors-border: #161616;
- --bn-colors-side-menu: #7f7f7f;
-
- --bn-colors-highlights-gray-text: #bebdb8;
- --bn-colors-highlights-gray-background: #9b9a97;
- --bn-colors-highlights-brown-text: #8e6552;
- --bn-colors-highlights-brown-background: #64473a;
- --bn-colors-highlights-red-text: #ec4040;
- --bn-colors-highlights-red-background: #be3434;
- --bn-colors-highlights-orange-text: #e3790d;
- --bn-colors-highlights-orange-background: #b7600a;
- --bn-colors-highlights-yellow-text: #dfab01;
- --bn-colors-highlights-yellow-background: #b58b00;
- --bn-colors-highlights-green-text: #6b8b87;
- --bn-colors-highlights-green-background: #4d6461;
- --bn-colors-highlights-blue-text: #0e87bc;
- --bn-colors-highlights-blue-background: #0b6e99;
- --bn-colors-highlights-purple-text: #8552d7;
- --bn-colors-highlights-purple-background: #6940a5;
- --bn-colors-highlights-pink-text: #da208f;
- --bn-colors-highlights-pink-background: #ad1a72;
+ --bn-colors-editor-text: oklch(85% 0 0);
+ --bn-colors-editor-background: oklch(24% 0 0);
+ --bn-colors-menu-text: oklch(85% 0 0);
+ --bn-colors-menu-background: oklch(24% 0 0);
+ --bn-colors-tooltip-text: oklch(85% 0 0);
+ --bn-colors-tooltip-background: oklch(20% 0 0);
+ --bn-colors-hovered-text: oklch(85% 0 0);
+ --bn-colors-hovered-background: oklch(20% 0 0);
+ --bn-colors-selected-text: oklch(85% 0 0);
+ --bn-colors-selected-background: oklch(17% 0 0);
+ --bn-colors-disabled-text: oklch(37% 0 0);
+ --bn-colors-disabled-background: oklch(20% 0 0);
+
+ --bn-colors-shadow: oklch(17% 0 0);
+ --bn-colors-border: oklch(20% 0 0);
+ --bn-colors-side-menu: oklch(60% 0 0);
+
+ --bn-colors-highlights-gray-text: oklch(71.5% 0 0);
+ --bn-colors-highlights-gray-background: oklch(34% 0 0);
+ --bn-colors-highlights-brown-text: oklch(73% 0.06 50);
+ --bn-colors-highlights-brown-background: oklch(34% 0.035 50);
+ --bn-colors-highlights-red-text: oklch(75% 0.1 25);
+ --bn-colors-highlights-red-background: oklch(34% 0.065 25);
+ --bn-colors-highlights-orange-text: oklch(75% 0.1 65);
+ --bn-colors-highlights-orange-background: oklch(34% 0.065 65);
+ --bn-colors-highlights-yellow-text: oklch(75% 0.1 95);
+ --bn-colors-highlights-yellow-background: oklch(34% 0.065 95);
+ --bn-colors-highlights-green-text: oklch(75% 0.1 135);
+ --bn-colors-highlights-green-background: oklch(34% 0.065 135);
+ --bn-colors-highlights-blue-text: oklch(75% 0.1 235);
+ --bn-colors-highlights-blue-background: oklch(34% 0.065 235);
+ --bn-colors-highlights-purple-text: oklch(75% 0.1 300);
+ --bn-colors-highlights-purple-background: oklch(34% 0.065 300);
+ --bn-colors-highlights-pink-text: oklch(75% 0.1 345);
+ --bn-colors-highlights-pink-background: oklch(34% 0.065 345);
}
.bn-root {
diff --git a/playground/src/examples.gen.tsx b/playground/src/examples.gen.tsx
index 6fa9173445..6177c913e3 100644
--- a/playground/src/examples.gen.tsx
+++ b/playground/src/examples.gen.tsx
@@ -1034,6 +1034,26 @@ export const examples = {
readme:
"To configure a code block highlighting theme and language, you can extend the editor's default schema with a new `codeBlock`, which you can pass options into when creating. You can then use a shiki highlighter to add custom syntax highlighting.\n\nFirst use the [shiki-codegen](https://shiki.style/packages/codegen) CLI to create a `shiki.bundle.ts` file. You can then pass this file into the `codeBlock` options when creating it.\n\n**Relevant Docs:**\n\n- [Code Blocks](/docs/features/blocks/code-blocks)\n- [shiki-codegen](https://shiki.style/packages/codegen)\n- [Custom Schema](/docs/features/custom-schemas)",
},
+ {
+ projectSlug: "color-combinations",
+ fullSlug: "theming/color-combinations",
+ pathFromRoot: "examples/04-theming/08-color-combinations",
+ config: {
+ playground: true,
+ docs: false,
+ author: "",
+ tags: ["Appearance & Styling"],
+ dependencies: {} as any,
+ pro: false,
+ },
+ title: "Color combinations",
+ group: {
+ pathFromRoot: "examples/04-theming",
+ slug: "theming",
+ },
+ readme:
+ "Inspect every combination of the default text and background colors, including the default color, applied to whole blocks and inline content. Switch between light and dark themes to compare their appearance.\n\n**Try me out!** Use the theme toggle above the editors.\n\n## Relevant docs\n\n- [Themes](https://www.blocknotejs.org/docs/react/styling-theming/themes)",
+ },
],
},
interoperability: {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8900ba6725..150d1e68ac 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2626,6 +2626,49 @@ importers:
specifier: ^8.0.0
version: 8.0.8(@types/node@25.9.5)(esbuild@0.27.5)(jiti@2.6.1)(terser@5.51.2)(tsx@4.21.0)(yaml@2.9.0)
+ examples/04-theming/08-color-combinations:
+ dependencies:
+ '@blocknote/ariakit':
+ specifier: latest
+ version: link:../../../packages/ariakit
+ '@blocknote/core':
+ specifier: latest
+ version: link:../../../packages/core
+ '@blocknote/mantine':
+ specifier: latest
+ version: link:../../../packages/mantine
+ '@blocknote/react':
+ specifier: latest
+ version: link:../../../packages/react
+ '@blocknote/shadcn':
+ specifier: latest
+ version: link:../../../packages/shadcn
+ '@mantine/core':
+ specifier: ^9.0.2
+ version: 9.1.1(@mantine/hooks@9.1.1(react@19.2.5))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
+ '@mantine/hooks':
+ specifier: ^9.0.2
+ version: 9.1.1(react@19.2.5)
+ react:
+ specifier: ^19.2.3
+ version: 19.2.5
+ react-dom:
+ specifier: ^19.2.3
+ version: 19.2.5(react@19.2.5)
+ devDependencies:
+ '@types/react':
+ specifier: ^19.2.3
+ version: 19.2.14
+ '@types/react-dom':
+ specifier: ^19.2.3
+ version: 19.2.3(@types/react@19.2.14)
+ '@vitejs/plugin-react':
+ specifier: ^6.0.1
+ version: 6.0.1(babel-plugin-react-compiler@1.0.0)(vite@8.0.8(@types/node@25.9.5)(esbuild@0.27.5)(jiti@2.6.1)(terser@5.51.2)(tsx@4.21.0)(yaml@2.9.0))
+ vite:
+ specifier: ^8.0.0
+ version: 8.0.8(@types/node@25.9.5)(esbuild@0.27.5)(jiti@2.6.1)(terser@5.51.2)(tsx@4.21.0)(yaml@2.9.0)
+
examples/05-interoperability/01-converting-blocks-to-html:
dependencies:
'@blocknote/ariakit':
diff --git a/tests/src/end-to-end/copypaste/__snapshots__/nonEditableBlock.json b/tests/src/end-to-end/copypaste/__snapshots__/nonEditableBlock.json
index 3a15b219b5..4d67396854 100644
--- a/tests/src/end-to-end/copypaste/__snapshots__/nonEditableBlock.json
+++ b/tests/src/end-to-end/copypaste/__snapshots__/nonEditableBlock.json
@@ -57,13 +57,13 @@
{
"type": "textColor",
"attrs": {
- "stringValue": "rgb(63, 63, 63)"
+ "stringValue": "oklch(0.37 0 0)"
}
},
{
"type": "backgroundColor",
"attrs": {
- "stringValue": "rgb(255, 255, 255)"
+ "stringValue": "oklch(1 0 0)"
}
}
],