@portabletext/toolbar
v5.0.22
Published
Utilities for building a toolbar for the Portable Text Editor
Readme
@portabletext/toolbar
Powered by Behaviors and State Machines, @portabletext/toolbar is a collection of robust React hooks for building toolbars and related UI components
for the Portable Text editor.
Refer to the toolbar in the Portable Text Playground for a comprehensive example.
Features
- Schema Extension: Extend the editor's schema with default values, icons, shortcuts and more. This makes it easier to use the schema to render toolbars, forms and other UI components.
- Hooks: Headless React hooks to help building UI components for toggle buttons, popovers and insert dialogs.
- Keyboard Shortcuts: Seamless integration with
@portabletext/keyboard-shortcutsfor platform-aware shortcuts.
Installation
npm install @portabletext/toolbarBasic Example
import {bold, link} from '@portabletext/keyboard-shortcuts'
import {
useDecoratorButton,
useHistoryButtons,
useToolbarSchema,
type ExtendAnnotationSchemaType,
type ExtendDecoratorSchemaType,
} from '@portabletext/toolbar'
/**
* 1. Define extensions for your schema types
*/
const extendDecorator: ExtendDecoratorSchemaType = (decorator) => {
if (decorator.name === 'strong') {
return {
...decorator,
icon: BoldIcon,
shortcut: bold,
}
}
return decorator
}
const extendAnnotation: ExtendAnnotationSchemaType = (annotation) => {
if (annotation.name === 'link') {
return {
...annotation,
icon: LinkIcon,
defaultValues: {
href: 'https://example.com',
},
shortcut: link,
}
}
return annotation
}
/**
* 2. Create a Toolbar plugin that can be used inside an `EditorProvider`.
*/
function ToolbarPlugin() {
/**
* 3. Obtain a `ToolbarSchema` by extending the `EditorSchema`.
*/
const toolbarSchema = useToolbarSchema({
extendDecorator,
extendAnnotation,
// extendStyle,
// extendList,
// extendBlockObject,
// extendInlineObject,
})
/**
* 4. Render the toolbar
*/
return (
<div>
{toolbarSchema.decorators?.map((decorator) => (
<DecoratorButton key={decorator.name} schemaType={decorator} />
))}
{toolbarSchema.annotations?.map((annotation) => {
/** ... */
})}
<HistoryButtons />
</div>
)
}
function DecoratorButton(props: {schemaType: ToolbarDecoratorSchemaType}) {
/**
* 5. Use the provided hooks to manage state, set up keyboard shortcuts and
* more.
*/
const decoratorButton = useDecoratorButton(props)
return (
<button
onClick={() => decoratorButton.send({type: 'toggle'})}
disabled={decoratorButton.snapshot.matches('disabled')}
className={
decoratorButton.snapshot.matches({enabled: 'active'}) ? 'active' : ''
}
title={props.schemaType.shortcut?.description}
>
{props.schemaType.icon && <props.schemaType.icon />}
{props.schemaType.title}
</button>
)
}
function HistoryButtons() {
const historyButtons = useHistoryButtons()
return (
<>
<button
onClick={() => historyButtons.send({type: 'history.undo'})}
disabled={historyButtons.snapshot.matches('disabled')}
>
Undo
</button>
<button
onClick={() => historyButtons.send({type: 'history.redo'})}
disabled={historyButtons.snapshot.matches('disabled')}
>
Redo
</button>
</>
)
}Hooks
useToolbarSchema
Extends the editor's schema with default values, icons, shortcuts and more to make it easier to render toolbars, forms and other UI components.
function useToolbarSchema(props: {
extendDecorator?: (
decorator: DecoratorSchemaType,
) => ToolbarDecoratorSchemaType
extendAnnotation?: (
annotation: AnnotationSchemaType,
) => ToolbarAnnotationSchemaType
extendList?: (list: ListSchemaType) => ToolbarListSchemaType
extendBlockObject?: (
blockObject: BlockObjectSchemaType,
) => ToolbarBlockObjectSchemaType
extendInlineObject?: (
inlineObject: InlineObjectSchemaType,
) => ToolbarInlineObjectSchemaType
extendStyle?: (style: StyleSchemaType) => ToolbarStyleSchemaType
}): ToolbarSchemauseDecoratorButton
Manages the state and behavior of decorator toggle buttons (bold, italic, etc.) with keyboard shortcut support.
function useDecoratorButton(props: {
schemaType: ToolbarDecoratorSchemaType
}): DecoratorButtonReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'toggle'}
useAnnotationButton
Manages the state and behavior of annotation buttons in the toolbar. Handles adding/removing annotations, keyboard shortcuts, and dialog interactions.
function useAnnotationButton(props: {
schemaType: ToolbarAnnotationSchemaType
}): AnnotationButtonReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'add'},{type: 'remove'},{type: 'open dialog'},{type: 'close dialog'}
useAnnotationPopover
Provides state management for annotation popover dialogs, including form handling and validation.
function useAnnotationPopover(props: {
schemaTypes: ReadonlyArray<ToolbarAnnotationSchemaType>
}): AnnotationPopoverReturns: An object with:
snapshot: Current state snapshot withmatches()method andcontextcontaining active annotationssend: Function to dispatch events like{type: 'remove'},{type: 'edit'},{type: 'close'}
useStyleSelector
Manages style selection (headings, paragraphs, etc.) with keyboard shortcut support.
function useStyleSelector(props: {
schemaTypes: ReadonlyArray<ToolbarStyleSchemaType>
}): StyleSelectorReturns: An object with:
snapshot: Current state snapshot withmatches()method andcontext.activeStylesend: Function to dispatch events like{type: 'toggle', style: 'h1'}
useListButton
Manages list item toggle buttons (bullet lists, numbered lists, etc.).
function useListButton(props: {schemaType: ToolbarListSchemaType}): ListButtonReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'toggle'}
useBlockObjectButton
Manages insertion of block objects like images into the editor.
function useBlockObjectButton(props: {
schemaType: ToolbarBlockObjectSchemaType
}): BlockObjectButtonReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'open dialog'},{type: 'insert'}
useBlockObjectPopover
Provides state management for block object insertion dialogs.
function useBlockObjectPopover(props: {
schemaType: ToolbarBlockObjectSchemaType
}): BlockObjectPopoverReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'open dialog'},{type: 'close dialog'},{type: 'insert'}
useInlineObjectButton
Manages insertion of inline objects into the editor.
function useInlineObjectButton(props: {
schemaType: ToolbarInlineObjectSchemaType
}): InlineObjectButtonReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'open dialog'},{type: 'insert'}
useInlineObjectPopover
Provides state management for inline object insertion dialogs.
function useInlineObjectPopover(props: {
schemaType: ToolbarInlineObjectSchemaType
}): InlineObjectPopoverReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'open dialog'},{type: 'close dialog'},{type: 'insert'}
useHistoryButtons
Provides undo/redo functionality for the editor.
function useHistoryButtons(): HistoryButtonsReturns: An object with:
snapshot: Current state snapshot withmatches()methodsend: Function to dispatch events like{type: 'history.undo'},{type: 'history.redo'}
