FloatingToolbar
A floating format toolbar that appears on text selection.
FloatingToolbar renders a floating toolbar that appears above (or below) the user's text selection. It provides quick access to text formatting, links, colors, fonts, undo/redo, and text direction controls. The toolbar is rendered in a React Portal attached to document.body.
Import
import { FloatingToolbar } from "@blokhaus/core";Props
| Prop | Type | Default | Description |
|---|---|---|---|
colorPalette | ColorPalette | DEFAULT_COLOR_PALETTE | Custom color palette for text color and highlight color pickers. |
fontFamilies | FontFamilyEntry[] | DEFAULT_FONT_FAMILIES | Custom font family options for the font picker. |
Basic usage
Add FloatingToolbar as a child of EditorRoot:
"use client";
import { EditorRoot, FloatingToolbar, InputRulePlugin } from "@blokhaus/core";
export default function EditorPage() {
return (
<EditorRoot
namespace="my-editor"
className="min-h-[400px] p-4 border rounded"
>
<FloatingToolbar />
<InputRulePlugin />
</EditorRoot>
);
}Toolbar buttons
The floating toolbar includes the following controls, organized into groups separated by visual dividers:
Undo / Redo
| Button | Action | Shortcut |
|---|---|---|
| Undo | Undo the last change | Cmd+Z (Mac) / Ctrl+Z |
| Redo | Redo the last undone change | Cmd+Shift+Z (Mac) / Ctrl+Shift+Z |
Undo and Redo buttons are automatically disabled when there is nothing to undo or redo.
Text formatting
| Button | Format | Shortcut |
|---|---|---|
| Bold | bold | Cmd+B |
| Italic | italic | Cmd+I |
| Underline | underline | Cmd+U |
| Strikethrough | strikethrough | Cmd+Shift+S |
| Inline Code | code | Cmd+E |
Active formats are visually highlighted with the --blokhaus-accent color.
Link
Opens the link input dialog. Active when the cursor is inside a link node.
| Button | Action | Shortcut |
|---|---|---|
| Link | Open link input | Cmd+K |
Color picker
Opens an inline dropdown with two sections:
- Text color -- 10 colors (Default, Gray, Brown, Orange, Yellow, Green, Blue, Purple, Pink, Red)
- Background highlight -- 10 colors (same range)
Dispatches SET_TEXT_COLOR_COMMAND and SET_HIGHLIGHT_COLOR_COMMAND.
Font picker
Opens an inline dropdown listing available font families. Each font name is rendered in its own typeface for a visual preview. Dispatches SET_FONT_FAMILY_COMMAND.
Direction toggle
Toggles the current block's text direction between LTR and RTL. The icon changes to indicate the direction that will be applied on click.
Custom color palette
Pass a custom ColorPalette to override the default colors:
import { FloatingToolbar } from "@blokhaus/core";
import type { ColorPalette } from "@blokhaus/core";
const customPalette: ColorPalette = {
text: [
{ label: "Default", value: "", swatch: "currentColor" },
{ label: "Brand", value: "var(--brand-color)", swatch: "#6366f1" },
{ label: "Muted", value: "var(--muted-color)", swatch: "#94a3b8" },
],
highlight: [
{ label: "Default", value: "", swatch: "transparent" },
{ label: "Highlight", value: "var(--highlight-color)", swatch: "#fef08a" },
],
};
<FloatingToolbar colorPalette={customPalette} />;Custom font families
Pass a custom FontFamilyEntry[] to override the default fonts:
import { FloatingToolbar } from "@blokhaus/core";
import type { FontFamilyEntry } from "@blokhaus/core";
const customFonts: FontFamilyEntry[] = [
{ label: "Default", value: "", preview: "system-ui, sans-serif" },
{ label: "Georgia", value: "Georgia, serif", preview: "Georgia, serif" },
{
label: "Courier",
value: '"Courier New", monospace',
preview: '"Courier New", monospace',
},
];
<FloatingToolbar fontFamilies={customFonts} />;Positioning behavior
The toolbar uses position: fixed and is positioned relative to the DOM selection's bounding rectangle:
- Default: appears above the selection, horizontally centered
- Near top of viewport: automatically repositions below the selection to stay visible
Position updates are throttled to one requestAnimationFrame per frame to avoid layout thrashing during rapid selection changes.
Visibility rules
The toolbar shows when:
- A non-collapsed
RangeSelectionexists (text is selected) - The selection has a non-zero bounding rectangle
The toolbar hides when:
- The selection is collapsed (no text selected)
- A
TableSelectionis active (tables have their own context menu) - The user presses Escape
Keyboard accessibility
- The toolbar does not trap focus. Focus remains in the editor at all times.
- Pressing Escape closes the toolbar and returns focus to the editor.
- All buttons include
aria-labelattributes and tooltips with keyboard shortcuts. - Active formatting states are communicated via
aria-pressed.
Styling
The toolbar uses inline styles with CSS custom properties from the Blokhaus theme:
--blokhaus-popover-bg-- toolbar background--blokhaus-popover-border-- toolbar border--blokhaus-popover-shadow-- toolbar shadow--blokhaus-accent-- active button background--blokhaus-accent-foreground-- active button text/icon color--blokhaus-icon-secondary-- inactive button icon color--blokhaus-separator-- divider color between button groups
The toolbar includes a frosted glass effect via backdrop-filter: blur(20px) saturate(180%).
Notes
FloatingToolbaris a client component ('use client').- It renders into a React Portal on
document.body, so it works correctly regardless of the editor's CSS overflow or positioning context. - On touch devices, consider also including
MobileToolbarfor a better mobile experience. TheFloatingToolbarstill works on touch devices but theMobileToolbarprovides a more touch-friendly, fixed-position alternative. - The toolbar automatically closes sub-menus (color picker, font picker) when the toolbar itself hides.
- The floating toolbar is hidden when a table selection is active, since
TableActionMenuprovides its own context menu for table operations.
Related
- ColorPicker -- Standalone color picker component
- FontPicker -- Standalone font picker component
- MobileToolbar -- Fixed-position toolbar for touch devices
- Theming guide -- Customizing colors and styling