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
showBubbleMenubooleantrueShow bubble menu on selection
enableEmbedboolean-Enable embed in link editor
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

Hooks

useVizelEditor

Creates and manages a Vizel editor instance.

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

const editor = useVizelEditor(options?: VizelEditorOptions);

Returns: Editor | null

useVizelState

Forces re-render on editor state changes.

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

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

Returns: number (update count)

useVizelEditorState

Tracks specific editor state properties reactively.

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

const isBold = useVizelEditorState(
  () => editor,
  (editor) => editor.isActive('bold')
);

Returns: The value returned by the selector function

useVizelAutoSave

Auto-saves editor content with debouncing.

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

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

Returns:

PropertyTypeDescription
statusVizelSaveStatusCurrent save status
hasUnsavedChangesbooleanWhether there are unsaved changes
lastSavedDate | nullLast save timestamp
errorError | nullLast error
save() => Promise<void>Manual save function
restore() => Promise<JSONContent | null>Manual restore function

useVizelMarkdown

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

Returns:

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

useVizelTheme

Access 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

Access editor from VizelProvider context.

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

const { editor } = useVizelContext();

Components

VizelEditor

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

VizelBubbleMenu

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

VizelBubbleMenuDefault

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

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

Bubble menu divider.

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

<VizelBubbleMenuDivider />

VizelThemeProvider

Provides theme context.

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

Displays 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

Renders content in a portal.

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

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

Props:

PropTypeDescription
childrenReactNodeContent to render
containerHTMLElementPortal target

VizelColorPicker

Color selection component.

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

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

VizelIconProvider

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

Slash command menu component.

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

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

Utilities

createVizelSlashMenuRenderer

Creates 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. 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.