Skip to content

@vizel/react

React 19 components and hooks for Vizel editor.

Looking for a guide?

See the React Guide for step-by-step tutorials and common patterns.

Installation

bash
npm install @vizel/react

Components

Vizel

All-in-one editor component with built-in bubble menu. This is the recommended way to get started.

tsx
import { Vizel } from '@vizel/react';
import '@vizel/core/styles.css';

<Vizel
  initialContent={{ type: 'doc', content: [] }}
  placeholder="Start writing..."
  editable={true}
  autofocus="end"
  showBubbleMenu={true}
  enableEmbed={true}
  className="my-editor"
  features={{ markdown: true }}
  onUpdate={({ editor }) => {}}
  onCreate={({ editor }) => {}}
  onFocus={({ editor }) => {}}
  onBlur={({ editor }) => {}}
/>

Props:

PropTypeDefaultDescription
initialContentJSONContent-Initial editor content (JSON)
initialMarkdownstring-Initial editor content (Markdown)
placeholderstring-Placeholder text
editablebooleantrueEditable state
autofocusboolean | 'start' | 'end' | 'all' | number-Auto focus behavior
featuresVizelFeatureOptions-Feature configuration
classNamestring-CSS class name
showToolbarbooleanfalseShow fixed toolbar above editor
toolbarContentReactNode-Custom toolbar content
showBubbleMenubooleantrueShow bubble menu on selection
enableEmbedboolean-Enable embed in link editor
flavorVizelMarkdownFlavor"gfm"Markdown output flavor
localeVizelLocale-Locale for translated UI strings
extensionsExtensions-Additional Tiptap extensions
transformDiagramsOnImportbooleantrueTransform diagram code blocks when importing markdown
markdownstring-Controlled markdown content
onMarkdownChange(markdown: string) => void-Callback when markdown changes
onUpdate({ editor }) => void-Update callback
onCreate({ editor }) => void-Create callback
onDestroy() => void-Destroy callback
onSelectionUpdate({ editor }) => void-Selection change callback
onFocus({ editor }) => void-Focus callback
onBlur({ editor }) => void-Blur callback
onError(error: VizelError) => void-Error callback

Hooks

useVizelEditor

This hook creates and manages a Vizel editor instance.

tsx
import { useVizelEditor } from '@vizel/react';

const editor = useVizelEditor(options?: VizelEditorOptions);

Returns: Editor | null

useVizelState

This hook forces a re-render on editor state changes.

tsx
import { useVizelState } from '@vizel/react';

const updateCount = useVizelState(() => editor);

Returns: number (update count)

useVizelEditorState

This hook returns a VizelEditorState object that reactively tracks editor state (bold, italic, heading level, etc.).

tsx
import { useVizelEditorState } from '@vizel/react';

const state = useVizelEditorState(() => editor);
// state.isBold, state.isItalic, state.headingLevel, etc.

Returns: VizelEditorState — reactive object with boolean flags for formatting state and current node info

useVizelAutoSave

This hook auto-saves editor content with debouncing.

tsx
import { useVizelAutoSave } from '@vizel/react';

const result = useVizelAutoSave(
  () => editor,
  options?: VizelAutoSaveOptions
);

Returns:

PropertyTypeDescription
statusVizelSaveStatusCurrent save status
hasUnsavedChangesbooleanWhether unsaved changes exist
lastSavedDate | nullLast save timestamp
errorError | nullLast error
save() => Promise<void>Save content manually
restore() => Promise<JSONContent | null>Restore content manually

useVizelMarkdown

This hook provides two-way Markdown synchronization with debouncing.

tsx
import { useVizelMarkdown } from '@vizel/react';

const result = useVizelMarkdown(
  () => editor,
  options?: VizelMarkdownSyncOptions
);

Options:

OptionTypeDefaultDescription
debounceMsnumber300Debounce delay in milliseconds
transformDiagramsbooleantrueTransform diagram code blocks when setting markdown

Returns:

PropertyTypeDescription
markdownstringCurrent Markdown content
setMarkdown(md: string) => voidUpdate editor from Markdown
isPendingbooleanWhether sync is pending

useVizelTheme

This hook accesses theme state within VizelThemeProvider.

tsx
import { useVizelTheme } from '@vizel/react';

const { theme, resolvedTheme, systemTheme, setTheme } = useVizelTheme();

Returns:

PropertyTypeDescription
themeVizelThemeCurrent theme setting
resolvedThemeVizelResolvedThemeResolved theme
systemThemeVizelResolvedThemeSystem preference
setTheme(theme: VizelTheme) => voidSet theme function

useVizelContext

This hook accesses the editor from VizelProvider context.

tsx
import { useVizelContext } from '@vizel/react';

const { editor } = useVizelContext();

useVizelCollaboration

This hook tracks real-time collaboration state with a Yjs provider.

tsx
import { useVizelCollaboration } from '@vizel/react';

const {
  isConnected,
  isSynced,
  peerCount,
  error,
  connect,
  disconnect,
  updateUser,
} = useVizelCollaboration(
  () => wsProvider,
  { user: { name: 'Alice', color: '#ff0000' } }
);

Parameters:

ParameterTypeDescription
getProvider() => VizelYjsProvider | null | undefinedGetter function for the Yjs provider
optionsVizelCollaborationOptionsCollaboration options including user info

Returns: UseVizelCollaborationResult

PropertyTypeDescription
isConnectedbooleanWhether the editor is connected to the server
isSyncedbooleanWhether initial sync is complete
peerCountnumberNumber of connected peers
errorError | nullLast error
connect() => voidConnect to the server
disconnect() => voidDisconnect from the server
updateUser(user: VizelCollaborationUser) => voidUpdate user cursor info

useVizelComment

This hook manages document comments and annotations.

tsx
import { useVizelComment } from '@vizel/react';

const {
  comments,
  activeCommentId,
  isLoading,
  error,
  addComment,
  removeComment,
  resolveComment,
  reopenComment,
  replyToComment,
  setActiveComment,
  loadComments,
  getCommentById,
} = useVizelComment(() => editor, { key: 'my-comments' });

Parameters:

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor
optionsVizelCommentOptionsComment configuration options

Returns: UseVizelCommentResult

PropertyTypeDescription
commentsVizelComment[]All stored comments (newest first)
activeCommentIdstring | nullCurrently active comment ID
isLoadingbooleanWhether comments are loading
errorError | nullLast error
addComment(text: string, author?: string) => Promise<VizelComment | null>Add a comment to the selection
removeComment(commentId: string) => Promise<void>Remove a comment
resolveComment(commentId: string) => Promise<boolean>Resolve a comment
reopenComment(commentId: string) => Promise<boolean>Reopen a comment
replyToComment(commentId: string, text: string, author?: string) => Promise<VizelCommentReply | null>Reply to a comment
setActiveComment(commentId: string | null) => voidSet the active comment
loadComments() => Promise<VizelComment[]>Load comments from storage
getCommentById(commentId: string) => VizelComment | undefinedGet a comment by ID

useVizelVersionHistory

This hook manages document version history with save, restore, and delete operations.

tsx
import { useVizelVersionHistory } from '@vizel/react';

const {
  snapshots,
  isLoading,
  error,
  saveVersion,
  restoreVersion,
  loadVersions,
  deleteVersion,
  clearVersions,
} = useVizelVersionHistory(() => editor, { maxVersions: 20 });

Parameters:

ParameterTypeDescription
getEditor() => Editor | null | undefinedGetter function for the editor
optionsVizelVersionHistoryOptionsVersion history configuration

Returns: UseVizelVersionHistoryResult

PropertyTypeDescription
snapshotsVizelVersionSnapshot[]All stored snapshots (newest first)
isLoadingbooleanWhether history is loading
errorError | nullLast error
saveVersion(description?: string, author?: string) => Promise<VizelVersionSnapshot | null>Save a new version
restoreVersion(versionId: string) => Promise<boolean>Restore a version
loadVersions() => Promise<VizelVersionSnapshot[]>Load versions from storage
deleteVersion(versionId: string) => Promise<void>Delete a version
clearVersions() => Promise<void>Delete all versions

Components

VizelFindReplace

Find & Replace panel component. This component renders when the Find & Replace extension is open.

tsx
import { VizelFindReplace } from '@vizel/react';

<VizelFindReplace
  editor={editor}
  className="my-find-replace"
  onClose={() => console.log('Closed')}
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name
localeVizelLocale-Locale for translated UI strings
onClose() => void-Called when the panel closes

VizelEditor

This component renders the editor content area.

tsx
import { VizelEditor } from '@vizel/react';

<VizelEditor editor={editor} className="my-editor" />

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name

VizelBlockMenu

Block context menu that appears when clicking the drag handle.

tsx
import { VizelBlockMenu } from '@vizel/react';

<VizelBlockMenu />
PropTypeDefaultDescription
actionsVizelBlockMenuAction[]vizelDefaultBlockMenuActionsCustom menu actions
nodeTypesVizelNodeTypeOption[]vizelDefaultNodeTypesNode types for "Turn into" submenu
classNamestring-CSS class name
localeVizelLocale-Locale for translated UI strings

VizelBubbleMenu

This component renders a floating formatting bubble menu.

tsx
import { VizelBubbleMenu } from '@vizel/react';

<VizelBubbleMenu 
  editor={editor}
  className="my-bubble-menu"
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
classNamestring-CSS class name
childrenReactNode-Custom content
showDefaultMenubooleantrueShow default formatting menu when no children
pluginKeystring-Custom plugin key for the bubble menu
updateDelaynumber-Delay in ms before updating menu position
shouldShow(props) => boolean-Custom function to control menu visibility
enableEmbedboolean-Enable embed option in link editor

VizelBubbleMenuDefault

This component renders the default bubble menu with all formatting buttons.

tsx
import { VizelBubbleMenuDefault } from '@vizel/react';

<VizelBubbleMenuDefault 
  editor={editor}
  enableEmbed={false}
/>

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance
enableEmbedbooleanfalseEnable embed in links

VizelBubbleMenuButton

This component renders an individual bubble menu button.

tsx
import { VizelBubbleMenuButton } from '@vizel/react';

<VizelBubbleMenuButton
  icon="lucide:bold"
  isActive={editor.isActive('bold')}
  onClick={() => editor.chain().focus().toggleBold().run()}
/>

VizelBubbleMenuDivider

This component renders a bubble menu divider.

tsx
import { VizelBubbleMenuDivider } from '@vizel/react';

<VizelBubbleMenuDivider />

VizelToolbar

This component renders a fixed toolbar.

tsx
import { VizelToolbar } from '@vizel/react';

<VizelToolbar editor={editor} className="my-toolbar" />

Props:

PropTypeDefaultDescription
editorEditor | null-Editor instance (falls back to context)
classNamestring-CSS class name
showDefaultToolbarbooleantrueShow default toolbar content
localeVizelLocale-Locale for translated UI strings
childrenReactNode-Custom toolbar content

VizelToolbarDefault

This component renders the default toolbar content with grouped formatting buttons.

tsx
import { VizelToolbarDefault } from '@vizel/react';

<VizelToolbarDefault editor={editor} actions={customActions} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
classNamestring-CSS class name
localeVizelLocale-Locale for translated UI strings
actionsVizelToolbarActionItem[]vizelDefaultToolbarActionsCustom actions (supports dropdowns)

VizelToolbarDropdown

This component renders a dropdown toolbar button with a popover of nested actions.

tsx
import { VizelToolbarDropdown } from '@vizel/react';

<VizelToolbarDropdown editor={editor} dropdown={headingDropdown} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
dropdownVizelToolbarDropdownAction-Dropdown action definition (required)
classNamestring-CSS class name

VizelToolbarOverflow

This component renders a "..." overflow button that shows hidden actions in a popover.

tsx
import { VizelToolbarOverflow } from '@vizel/react';

<VizelToolbarOverflow editor={editor} actions={overflowActions} />

Props:

PropTypeDefaultDescription
editorEditor-Editor instance (required)
actionsVizelToolbarActionItem[]-Actions to show in overflow (required)
classNamestring-CSS class name
localeVizelLocale-Locale for translated UI strings

VizelToolbarButton

This component renders an individual toolbar button.

tsx
import { VizelToolbarButton } from '@vizel/react';

<VizelToolbarButton
  onClick={() => editor.chain().focus().toggleBold().run()}
  isActive={editor.isActive("bold")}
  title="Bold (Cmd+B)"
>
  <VizelIcon name="bold" />
</VizelToolbarButton>

Props:

PropTypeDefaultDescription
onClick() => void-Click handler
isActivebooleanfalseActive state
disabledbooleanfalseDisabled state
childrenReactNode-Button content
titlestring-Tooltip text
classNamestring-CSS class name
actionstring-Action identifier

VizelToolbarDivider

This component renders a divider between toolbar button groups.

tsx
import { VizelToolbarDivider } from '@vizel/react';

<VizelToolbarDivider />

VizelThemeProvider

This component provides theme context to its children.

tsx
import { VizelThemeProvider } from '@vizel/react';

<VizelThemeProvider
  defaultTheme="system"
  storageKey="vizel-theme"
  disableTransitionOnChange={false}
>
  {children}
</VizelThemeProvider>

Props:

PropTypeDefaultDescription
defaultThemeVizelTheme"system"Default theme
storageKeystring"vizel-theme"Storage key
targetSelectorstring-Theme target
disableTransitionOnChangebooleanfalseDisable transitions
childrenReactNode-Children

VizelSaveIndicator

This component displays the save status.

tsx
import { VizelSaveIndicator } from '@vizel/react';

<VizelSaveIndicator status={status} lastSaved={lastSaved} />

Props:

PropTypeDescription
statusVizelSaveStatusSave status
lastSavedDate | nullLast save time
classNamestringCSS class name

VizelPortal

This component renders its children in a portal.

tsx
import { VizelPortal } from '@vizel/react';

<VizelPortal container={document.body}>{children}</VizelPortal>

Props:

PropTypeDescription
childrenReactNodeContent to render
containerHTMLElementPortal target

VizelColorPicker

This component renders a color selection interface.

tsx
import { VizelColorPicker } from '@vizel/react';

<VizelColorPicker
  colors={colors}
  value={currentColor}
  onChange={setColor}
  recentColors={recentColors}
/>

VizelIconProvider

This component provides custom icons for Vizel components.

tsx
import { VizelIconProvider } from '@vizel/react';
import type { CustomIconMap } from '@vizel/core';

const icons: CustomIconMap = {
  bold: 'mdi:format-bold',
  italic: 'mdi:format-italic',
};

<VizelIconProvider icons={icons}>
  <Vizel />
</VizelIconProvider>

Props:

PropTypeDescription
iconsCustomIconMapMap of icon names to Iconify icon IDs
childrenReactNodeChildren

VizelSlashMenu

This component renders the slash command menu.

tsx
import { VizelSlashMenu } from '@vizel/react';

<VizelSlashMenu
  items={items}
  command={handleCommand}
  className="my-menu"
/>

Utilities

createVizelSlashMenuRenderer

This function creates a slash menu renderer for the SlashCommand extension.

tsx
import { createVizelSlashMenuRenderer } from '@vizel/react';

const suggestion = createVizelSlashMenuRenderer();

const editor = useVizelEditor({
  features: {
    slashCommand: {
      suggestion,
    },
  },
});

Importing from @vizel/core and @tiptap/core

Framework packages do not re-export from @vizel/core. You must import directly:

tsx
// Framework-specific components and hooks
import { 
  Vizel, 
  VizelEditor, 
  VizelBubbleMenu, 
  VizelThemeProvider,
  useVizelEditor,
  useVizelMarkdown,
  useVizelAutoSave,
} from '@vizel/react';

// Vizel types and utilities from @vizel/core
import { getVizelEditorState, VIZEL_TEXT_COLORS } from '@vizel/core';
import type { VizelEditorOptions, VizelSaveStatus } from '@vizel/core';

// Tiptap types from @tiptap/core
import { Editor } from '@tiptap/core';
import type { JSONContent } from '@tiptap/core';

Released under the MIT License.