Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
03e86dd
Added demo
matthewlipski Aug 3, 2026
e45f5a1
Replaced demo toolbar with actual toolbar
matthewlipski Aug 6, 2026
d9902bf
Properly fixed dropdowns
matthewlipski Aug 7, 2026
af12646
- Fixed link button popover close dismissing virtual keyboard
matthewlipski Aug 7, 2026
1d4fbe3
Added transition to toolbar
matthewlipski Aug 12, 2026
07d9ff7
Replaced hook with pure CSS
matthewlipski Aug 13, 2026
faa72b5
Added docs
matthewlipski Aug 13, 2026
d070f14
Removed redundant `direction` prop
matthewlipski Aug 13, 2026
ece1f83
Merged main
matthewlipski Aug 13, 2026
e23b2f3
Refactored `useVirtualViewportRect`
matthewlipski Aug 14, 2026
57b68bf
Fixed some SSR issues
matthewlipski Aug 17, 2026
dfb89ac
Removed `portalRoot` prop
matthewlipski Aug 17, 2026
5a5fcd1
Merge branch 'main' into mobile-toolbar-demo
matthewlipski Aug 17, 2026
4b920a1
Implemented PR feedback
matthewlipski Aug 17, 2026
52933c2
Removed unused component
matthewlipski Aug 17, 2026
8a03207
Small fix
matthewlipski Aug 17, 2026
f779a4b
Increased mobile formatting toolbar tap target size
matthewlipski Aug 17, 2026
19428d4
- Fixed `getActiveStyles` with empty selections
matthewlipski Aug 20, 2026
a174fef
Refactored `FormattingToolbarController` to handle whether the deskto…
matthewlipski Aug 20, 2026
51aa828
Made mobile toolbar only appear when attached editor instance is focused
matthewlipski Aug 20, 2026
9c748cc
Fixed toolbar select desktop regression
matthewlipski Aug 20, 2026
3a95797
Increased required threshold to detect orientation change
matthewlipski Aug 20, 2026
69c6a71
Fixed formatting toolbar not opening when using touch-capable device …
matthewlipski Aug 20, 2026
a42e93c
Made mobile formatting toolbar center-aligned
matthewlipski Aug 20, 2026
1d0ef95
Small fix
matthewlipski Aug 20, 2026
e441113
docs: name the mobile toolbar layouts + add layout toggle to the exam…
YousefED Aug 20, 2026
09692f4
Merge remote-tracking branch 'origin/mobile-toolbar-demo' into mobile…
matthewlipski Aug 20, 2026
d4079d4
Made `.bn-scroll-host` class name apply all necessary styles automati…
matthewlipski Aug 20, 2026
b05f7ab
Added second editor to example
matthewlipski Aug 20, 2026
cef137d
Cached `isTouchDevice` result
matthewlipski Aug 20, 2026
be8838e
Cleaned up portal element context
matthewlipski Aug 21, 2026
51b89d0
Moved injected styles to stylesheet
matthewlipski Aug 21, 2026
83c2a00
Added `hide` middleware to `GenericPopover`
matthewlipski Aug 21, 2026
22c7645
Minor fixes
matthewlipski Aug 25, 2026
9a9f218
Fixed popovers
matthewlipski Aug 25, 2026
384ffd2
Implemented PR feedback
matthewlipski Aug 25, 2026
5696c41
Small fix
matthewlipski Aug 26, 2026
b54dcf5
Fixed Android gap
matthewlipski Aug 27, 2026
2656d73
Small fixes
matthewlipski Aug 28, 2026
0f80e42
Small docs change
matthewlipski Aug 28, 2026
852849f
Merge branch 'main' into mobile-toolbar-demo
YousefED Aug 28, 2026
0ec8997
Updated docs
matthewlipski Aug 31, 2026
b43ca12
Made formatting toolbar smooth in docs & playground
matthewlipski Aug 31, 2026
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
23 changes: 18 additions & 5 deletions docs/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Footer } from "@/components/Footer";
import { Provider } from "@/components/provider";
import { getFullMetadata } from "@/lib/getFullMetadata";
import { Analytics } from "@vercel/analytics/next";
import { Metadata } from "next";
import { Metadata, Viewport } from "next";
import "./global.css";
import "./gradients.css";
import "./styles.css";
Expand All @@ -13,14 +13,27 @@ export const metadata: Metadata = getFullMetadata({
"A beautiful text editor that just works. Easily add an editor to your app that users will love. Customize it with your own functionality like custom blocks or AI tooling.",
});

// Resizes the layout viewport (not just the visual viewport) when a virtual
// keyboard opens, so `position: fixed` elements can be pinned to the top of the
// keyboard. Must be set in the initial HTML, so it lives here rather than in an
// example's App. Mirrors the examples' generated `index.html` viewport meta.
export const viewport: Viewport = {
width: "device-width",
initialScale: 1,
interactiveWidget: "resizes-content",
};

export default function Layout({ children }: LayoutProps<"/">) {
return (
<html lang="en" suppressHydrationWarning>
<body className="flex min-h-screen flex-col">
<Provider>
{children}
<Footer />
</Provider>
{/* `bn-scroll-container` enables smoother mobile formatting toolbar. */}
<div className="bn-scroll-container flex min-h-screen flex-col">
<Provider>
{children}
<Footer />
</Provider>
</div>
<Analytics />
</body>
</html>
Expand Down
13 changes: 13 additions & 0 deletions docs/content/docs/getting-started/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ For more information about the `useCreateBlockNote` hook and the `BlockNoteView`
guide on setting up Next.js + BlockNote](/docs/getting-started/nextjs)
</Callout>

## Mobile compatibility

If your app is used on touch devices, it's good practice to add `interactive-widget=resizes-content` to your page's viewport meta tag:

```html
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
```

This isn't specific to BlockNote - it mitigates undesired behaviour that some browsers have when the virtual keyboard is open. For more on BlockNote's mobile UX, see the [mobile Formatting Toolbar](/docs/react/components/formatting-toolbar#mobile-formatting-toolbar).

## Next steps

You now know how to integrate BlockNote into your React app! However, this is just scratching the surface of what you can do with BlockNote.
Expand Down
22 changes: 22 additions & 0 deletions docs/content/docs/react/components/formatting-toolbar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,25 @@ The first element in the default Formatting Toolbar is the Block Type Select, an
<Example name="ui-components/formatting-toolbar-block-type-items" />

Here, we use the `FormattingToolbar` component but keep the default buttons (we don't pass any children). Instead, we pass our customized Block Type Select items using the `blockTypeSelectItems` prop.

## Mobile Formatting Toolbar

On touch devices, BlockNote's default UI replaces the floating Formatting Toolbar with a mobile Formatting Toolbar that sits just above the on-screen keyboard. It shows the same items as the regular Formatting Toolbar and is enabled by default - there's nothing to set up. Open any of the examples above on a phone to see it.

### Browser limitations

Mobile browsers vary in how they handle the on-screen keyboard, which can affect the toolbar. Before anything else, make sure your page has the viewport meta tag from the [mobile compatibility guide](/docs/getting-started#mobile-compatibility).

Most notably, iOS doesn't support the aforementioned viewport meta tag, which can result in jitter/lag when scrolling. There is however a workaround for this, which is why you won't see any choppiness in any of the examples here.

The workaround is to wrap all of your app's content in a single element with the `bn-scroll-container` class:

```tsx
<div className="bn-scroll-container">{/* nav, editor, page content... */}</div>
```

This element must be a direct child of `<body>` and cover its full area. BlockNote will keep its size in sync with the [visual viewport](https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport) and render the Formatting Toolbar outside of it, eliminating any jitter/lag.

<Callout type="warning">
Your app should only ever have a single `bn-scroll-container` element. It's pinned to the visual viewport with `position: fixed`, so multiple containers would overlap each other. Wrap all your scrollable page content in one.
</Callout>
7 changes: 7 additions & 0 deletions docs/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ const withMDX = createMDX();
const config = {
// output: "export",
reactStrictMode: true,
// Next.js 16 blocks cross-origin requests to dev resources (`/_next/*`, HMR)
// by default. When testing on a device on the local network - e.g. a phone
// checking the mobile toolbar - the browser's origin is the machine's LAN IP,
// not `localhost`, so those requests get a 403 and the page breaks. Allow the
// common private LAN ranges so network devices can load the dev server. This
// only affects `next dev`.
allowedDevOrigins: ["192.168.*.*", "10.*.*.*", "172.*.*.*"],
serverExternalPackages: ["typescript", "twoslash"],
reactCompiler: true,
// TypeScript 7 ships only the native `tsc` binary; it no longer exposes the
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/01-minimal/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Basic Setup</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/02-block-objects/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Displaying Document JSON</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/03-multi-column/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Multi-Column Blocks</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/04-default-blocks/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Default Schema Showcase</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/05-removing-default-blocks/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Removing Default Blocks from Schema</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/06-block-manipulation/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Manipulating Blocks</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/07-selection-blocks/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Displaying Selected Blocks</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/08-ariakit/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Use with Ariakit</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/09-shadcn/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Use with ShadCN</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/10-localization/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Localization (i18n)</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/11-custom-placeholder/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Change placeholder text</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/12-multi-editor/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Multi-Editor Setup</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/13-custom-paste-handler/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Custom Paste Handler</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/14-editor-scrollable/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Scrollable Editor</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/15-shadowdom/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Shadow DOM</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/16-read-only-editor/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Read-only Editor</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/17-no-trailing-block/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>No Trailing Block</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/01-basic/testing/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Test Editor</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/02-backend/01-file-uploading/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Upload Files</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/02-backend/02-saving-loading/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Saving &amp; Loading</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/02-backend/03-s3/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Upload Files to AWS S3</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/02-backend/04-rendering-static-documents/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Rendering static documents</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
5 changes: 4 additions & 1 deletion examples/03-ui-components/01-ui-elements-remove/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Removing UI Elements</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, interactive-widget=resizes-content"
/>
<title>Adding Formatting Toolbar Buttons</title>
<script>
<!-- AUTO-GENERATED FILE, DO NOT EDIT DIRECTLY -->
Expand Down
Loading
Loading