Documentation Index Fetch the complete documentation index at: https://docs.yoopta.dev/llms.txt
Use this file to discover all available pages before exploring further.
Overview
FloatingToolbar is a self-contained component that displays a formatting toolbar when text is selected. It handles selection tracking internally and exposes visibility state via context.
Features
API — compound components with auto-visibility
Selection tracking — automatically shows/hides on text selection
Block selection support — also works when blocks are selected
frozen prop — pause selection tracking when popups are open
TypeScript — full type safety
Installation
npm install @yoopta/ui
# or
yarn add @yoopta/ui
Basic Usage
import { FloatingToolbar } from '@yoopta/ui/floating-toolbar' ;
import { Marks , useYooptaEditor } from '@yoopta/editor' ;
import { FontBoldIcon , FontItalicIcon , CodeIcon } from '@radix-ui/react-icons' ;
function MyToolbar () {
const editor = useYooptaEditor ();
return (
< FloatingToolbar >
< FloatingToolbar.Content >
< FloatingToolbar.Group >
{ editor . formats . bold && (
< FloatingToolbar.Button
onClick = { () => Marks . toggle ( editor , { type: 'bold' }) }
active = { Marks . isActive ( editor , { type: 'bold' }) }
title = "Bold" >
< FontBoldIcon />
</ FloatingToolbar.Button >
) }
{ editor . formats . italic && (
< FloatingToolbar.Button
onClick = { () => Marks . toggle ( editor , { type: 'italic' }) }
active = { Marks . isActive ( editor , { type: 'italic' }) }
title = "Italic" >
< FontItalicIcon />
</ FloatingToolbar.Button >
) }
{ editor . formats . code && (
< FloatingToolbar.Button
onClick = { () => Marks . toggle ( editor , { type: 'code' }) }
active = { Marks . isActive ( editor , { type: 'code' }) }
title = "Code" >
< CodeIcon />
</ FloatingToolbar.Button >
) }
</ FloatingToolbar.Group >
</ FloatingToolbar.Content >
</ FloatingToolbar >
);
}
// In your editor: create editor with createYooptaEditor({ plugins, marks });
// UI components as children
< YooptaEditor editor = { editor } onChange = { ( value ) => console . log ( value ) } placeholder = "Type / to open menu..." >
< MyToolbar />
</ YooptaEditor >
API Reference
Root component that handles selection tracking.
< FloatingToolbar frozen = { popoverOpen } >
{ /* or with render props */ }
{ ({ isOpen }) => isOpen && < FloatingToolbar.Content > ... </ FloatingToolbar.Content > }
</ FloatingToolbar >
Props:
Prop Type Description childrenReactNode | ((api) => ReactNode)Content or render function frozenbooleanWhen true, selection tracking is paused classNamestringCustom CSS classes
Render Props API:
Property Type Description isOpenbooleanWhether toolbar is visible
FloatingToolbar.Content
Floating content panel. Automatically hides when no selection.
< FloatingToolbar.Content className = "custom-class" >
{ /* Groups and buttons */ }
</ FloatingToolbar.Content >
Props:
Prop Type Description classNamestringCustom CSS classes childrenReactNodeToolbar groups and buttons
Groups related buttons together.
< FloatingToolbar.Group >
< FloatingToolbar.Button > Bold </ FloatingToolbar.Button >
< FloatingToolbar.Button > Italic </ FloatingToolbar.Button >
</ FloatingToolbar.Group >
Individual toolbar button.
< FloatingToolbar.Button onClick = { handleClick } active = { isActive } disabled = { false } title = "Bold" >
< BoldIcon />
</ FloatingToolbar.Button >
Props:
Prop Type Description onClick(event) => voidClick handler activebooleanWhether button is active/pressed disabledbooleanDisable the button titlestringTooltip text classNamestringCustom CSS classes
Visual separator between groups.
< FloatingToolbar.Separator />
Examples
import { useRef , useState } from 'react' ;
import { Blocks , useYooptaEditor } from '@yoopta/editor' ;
import { FloatingToolbar } from '@yoopta/ui/floating-toolbar' ;
import { ActionMenuList } from '@yoopta/ui/action-menu-list' ;
function MyToolbar () {
const editor = useYooptaEditor ();
const turnIntoRef = useRef < HTMLButtonElement >( null );
const [ actionMenuOpen , setActionMenuOpen ] = useState ( false );
const currentBlockId =
typeof editor . path . current === 'number'
? Blocks . getBlock ( editor , { at: editor . path . current })?. id ?? null
: null ;
return (
<>
< FloatingToolbar frozen = { actionMenuOpen } >
< FloatingToolbar.Content >
< FloatingToolbar.Group >
< FloatingToolbar.Button ref = { turnIntoRef } onClick = { () => setActionMenuOpen ( true ) } >
Turn into
< ChevronDownIcon />
</ FloatingToolbar.Button >
</ FloatingToolbar.Group >
< FloatingToolbar.Separator />
< FloatingToolbar.Group > { /* Formatting buttons */ } </ FloatingToolbar.Group >
</ FloatingToolbar.Content >
</ FloatingToolbar >
< ActionMenuList
open = { actionMenuOpen }
onOpenChange = { setActionMenuOpen }
anchor = { turnIntoRef . current }
blockId = { currentBlockId }
view = "small"
placement = "bottom-start" >
< ActionMenuList.Content />
</ ActionMenuList >
</>
);
}
function FormattingToolbar () {
const editor = useYooptaEditor ();
const buttons = [
{ type: 'bold' , icon: < BoldIcon /> , label: 'Bold' },
{ type: 'italic' , icon: < ItalicIcon /> , label: 'Italic' },
{ type: 'underline' , icon: < UnderlineIcon /> , label: 'Underline' },
{ type: 'strike' , icon: < StrikethroughIcon /> , label: 'Strikethrough' },
{ type: 'code' , icon: < CodeIcon /> , label: 'Code' },
];
return (
< FloatingToolbar >
< FloatingToolbar.Content >
< FloatingToolbar.Group >
{ buttons . map (( btn ) => {
const isActive = Marks . isActive ( editor , { type: btn . type });
if ( ! editor . formats [ btn . type ]) return null ;
return (
< FloatingToolbar.Button
key = { btn . type }
onClick = { () => Marks . toggle ( editor , { type: btn . type }) }
active = { isActive }
title = { btn . label } >
{ btn . icon }
</ FloatingToolbar.Button >
);
}) }
</ FloatingToolbar.Group >
</ FloatingToolbar.Content >
</ FloatingToolbar >
);
}
Styling
CSS Variables
:root {
--yoopta-ui-floating-toolbar-gap : 4 px ;
--yoopta-ui-floating-toolbar-padding : 6 px ;
--yoopta-ui-floating-toolbar-radius : 0.5 rem ;
--yoopta-ui-floating-toolbar-shadow : 0 4 px 6 px -1 px rgb ( 0 0 0 / 0.1 );
--yoopta-ui-floating-toolbar-button-min-width : 32 px ;
--yoopta-ui-floating-toolbar-button-min-height : 32 px ;
--yoopta-ui-floating-toolbar-button-hover : var ( --yoopta-ui-accent );
}
Custom Styles
< FloatingToolbar >
< FloatingToolbar.Content className = "bg-slate-900 border-white/10" >
< FloatingToolbar.Group >
< FloatingToolbar.Button className = "text-white hover:bg-white/10" > Bold </ FloatingToolbar.Button >
</ FloatingToolbar.Group >
</ FloatingToolbar.Content >
</ FloatingToolbar >
Best Practices
Use frozen prop when opening popovers
const [ popoverOpen , setPopoverOpen ] = useState ( false );
< FloatingToolbar frozen = { popoverOpen } >
{ /* Prevents toolbar from closing while popover is open */ }
</ FloatingToolbar >
Check if format exists before rendering
Use separators to group related actions
ActionMenuList Open from “Turn into” button
FloatingBlockActions Block-level action buttons