Skip to content

Behavior Recipes

Below are some common behavior examples. You can also find a list of core behaviors on GitHub.

To add these to your editor, first import defineBehavior and optionally the coreBehaviors.

import {coreBehaviors, defineBehavior} from '@portabletext/editor'

Then, register the behavior with the EditorProvider. Spread the core behaviors if you want to include them.

<EditorProvider
initialConfig={{
schemaDefinition,
behaviors: [
...coreBehaviors,
// Your behaviors here
logInsertText,
],
}}
>
{/* ... */}
</EditorProvider>

Read more about using behaviors and building your own with these guides:

Log inserted text

Send and effect type action along with an effect to perform side effects.

const logInsertText = defineBehavior({
on: 'insert.text',
actions: [
({event}) => [
{
type: 'effect',
effect: () => {
console.log(event)
},
},
event,
],
],
}

Auto-close parenthesis

You can write behaviors to auto-close common paired characters. This example closes parenthesis, and then moves the cursor in between the two characters. This logic can expand to cover more sets.

const autoCloseParens = defineBehavior({
on: 'insert.text',
guard: ({context, event}) => {
return event.text === '('
},
actions: [
({event, context}) => [
// Send the original event that includes the '('
event,
// Send a new insert.text event with a closing parenthesis
{
type: 'insert.text',
text: ')',
},
// Send a select event to move the cursor in between the parens
{
type: 'select',
selection: {
anchor: {
path: context.selection.anchor.path,
offset: context.selection.anchor.offset + 1,
},
focus: {
path: context.selection.focus.path,
offset: context.selection.focus.offset + 1,
},
},
},
],
],
})

Emoji Picker

Using a factory to create behaviors, a state machine, and custom components results in an emoji picker that triggers when you insert :.

Emoji picker in Portable Text Editor

Test it out in the Playground.

You can leverage the behavior by importing createEmojiPickerBehaviors from @portabletext/editor/behaviors. See the editor source above for a usage example.

Raise a synthetic event

Sometimes you want to trigger a synthetic event from within an action. This sends the event back to the editor, where the editor treats it like any other event.

const raisedUppercaseA = defineBehavior({
on: 'insert.text',
guard: ({event, context}) => event.text === 'a',
actions: [
({event, context}) => [
{type: 'raise', event: {type: 'insert.text', text: 'A'}},
],
],
})

The raise action also has a shorthand function:

const raisedUppercaseA = defineBehavior({
on: 'insert.text',
guard: ({event, context}) => event.text === 'a',
actions: [({event, context}) => [raise({type: 'insert.text', text: 'A'})]],
})