Skip to main content

UI Components API

Excalidraw provides a set of composable UI components that can be used to customize the editor interface. These components can be passed as children to the main Excalidraw component.

Import

import {
  MainMenu,
  Sidebar,
  Footer,
  WelcomeScreen,
  Button,
  LiveCollaborationTrigger,
  Stats,
  DefaultSidebar,
  Ellipsify,
  TTDDialog,
  TTDDialogTrigger,
  TTDStreamFetch,
  DiagramToCodePlugin,
  CommandPalette,
  useEditorInterface,
  useStylesPanelMode,
} from "@excalidraw/excalidraw";
The MainMenu component provides a customizable dropdown menu accessed via a hamburger icon.

Props

children
React.ReactNode
required
Menu items and components to display in the dropdown. Can include MainMenu.Item, MainMenu.ItemLink, MainMenu.DefaultItems.*, MainMenu.Separator, MainMenu.Group, and MainMenu.Sub.
onSelect
function
Callback fired when any menu item is selected (clicked on).
onSelect?: (event: Event) => void;

Subcomponents

A clickable menu item that triggers an action.
<MainMenu.Item 
  onSelect={handleAction}
  icon={<MyIcon />}
  shortcut="⌘K"
>
  Menu Item Label
</MainMenu.Item>
onSelect
function
required
Callback when item is clicked.
onSelect: () => void;
icon
JSX.Element
Icon to display before the label.
shortcut
string
Keyboard shortcut to display (e.g., “⌘K”, “Ctrl+S”).
children
React.ReactNode
required
Label content for the menu item.
A menu item that opens a link in a new tab.
<MainMenu.ItemLink 
  href="https://example.com"
  icon={<LinkIcon />}
  shortcut="⌘L"
>
  External Link
</MainMenu.ItemLink>
href
string
required
URL to open when clicked.
icon
JSX.Element
Icon to display before the label.
shortcut
string
Keyboard shortcut to display.
children
React.ReactNode
required
Label content for the menu item.
A fully custom menu item with complete control over rendering.
<MainMenu.ItemCustom>
  <div className="custom-menu-item">
    {/* Your custom content */}
  </div>
</MainMenu.ItemCustom>
children
React.ReactNode
required
Custom content to render.
A visual separator between menu items.
<MainMenu.Separator />
No props. Groups related menu items together.
<MainMenu.Group>
  <MainMenu.Item onSelect={handler1}>Item 1</MainMenu.Item>
  <MainMenu.Item onSelect={handler2}>Item 2</MainMenu.Item>
</MainMenu.Group>
children
React.ReactNode
required
Menu items to group together.
Creates a submenu.
<MainMenu.Sub label="More Options" icon={<MoreIcon />}>
  <MainMenu.Item onSelect={handler1}>Sub Item 1</MainMenu.Item>
  <MainMenu.Item onSelect={handler2}>Sub Item 2</MainMenu.Item>
</MainMenu.Sub>
label
string
required
Label for the submenu trigger.
icon
JSX.Element
Icon to display before the label.
children
React.ReactNode
required
Menu items to display in the submenu.
Custom trigger component to open the menu (overrides default hamburger icon).
<MainMenu.Trigger>
  <button>Open Menu</button>
</MainMenu.Trigger>
children
React.ReactNode
required
Custom trigger element.

Default Items

Excalidraw provides pre-built menu items accessible via MainMenu.DefaultItems:
MainMenu.DefaultItems.LoadScene
component
Opens a file picker to load a scene from a .excalidraw file.
<MainMenu.DefaultItems.LoadScene />
MainMenu.DefaultItems.SaveToActiveFile
component
Saves the current scene to the active file (requires File System Access API).
<MainMenu.DefaultItems.SaveToActiveFile />
MainMenu.DefaultItems.Export
component
Opens the export dialog to save as PNG, SVG, or JSON.
<MainMenu.DefaultItems.Export />
MainMenu.DefaultItems.SaveAsImage
component
Quickly export the canvas as an image.
<MainMenu.DefaultItems.SaveAsImage />
MainMenu.DefaultItems.Help
component
Opens the help dialog showing keyboard shortcuts.
<MainMenu.DefaultItems.Help />
MainMenu.DefaultItems.ClearCanvas
component
Clears all elements from the canvas.
<MainMenu.DefaultItems.ClearCanvas />
MainMenu.DefaultItems.ToggleTheme
component
Toggles between light and dark themes.
<MainMenu.DefaultItems.ToggleTheme />
MainMenu.DefaultItems.ChangeCanvasBackground
component
Opens a color picker to change the canvas background.
<MainMenu.DefaultItems.ChangeCanvasBackground />

Example

import { Excalidraw, MainMenu } from "@excalidraw/excalidraw";

function App() {
  const handleCustomAction = () => {
    console.log("Custom action triggered");
  };

  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw>
        <MainMenu onSelect={(e) => console.log("Menu item selected", e)}>
          <MainMenu.DefaultItems.LoadScene />
          <MainMenu.DefaultItems.Export />
          <MainMenu.Separator />
          <MainMenu.Item onSelect={handleCustomAction} icon={customIcon}>
            Custom Action
          </MainMenu.Item>
          <MainMenu.DefaultItems.Help />
        </MainMenu>
      </Excalidraw>
    </div>
  );
}
The Sidebar component provides a customizable sidebar that can be docked or floating.

Props

name
string
required
Unique name for the sidebar. Used to identify and control the sidebar state.
name: SidebarName; // string
children
React.ReactNode
required
Sidebar content including Sidebar.Header, Sidebar.Tabs, Sidebar.Tab, etc.
onStateChange
function
Called on sidebar open/close or tab change.
onStateChange?: (state: { name: string; tab?: string } | null) => void;
Parameters:
  • state - Current open sidebar state, or null if closed
onDock
function
Supply alongside docked prop to make the sidebar user-dockable.
onDock?: (docked: boolean) => void;
docked
boolean
Controls whether the sidebar is docked. Must be used with onDock to enable user docking.
docked?: boolean;
className
string
Additional CSS class name for styling.

Subcomponents

Header component for the sidebar with title and optional dock/close buttons.
<Sidebar.Header>
  <h2>My Sidebar</h2>
</Sidebar.Header>
children
React.ReactNode
required
Header content (typically a title).
Button to open/close the sidebar.
<Sidebar.Trigger 
  name="my-sidebar"
  icon={<MyIcon />}
  title="Open Sidebar"
/>
name
string
required
Name of the sidebar to trigger (must match the Sidebar’s name prop).
name: SidebarName;
tab
string
Optional tab name to open when triggering the sidebar.
tab?: SidebarTabName;
icon
JSX.Element
Icon to display in the trigger button.
title
string
Tooltip text for the trigger button.
className
string
Additional CSS class name.
onToggle
function
Callback when the trigger is clicked.
onToggle?: (open: boolean) => void;
style
React.CSSProperties
Inline styles for the trigger button.
Container for sidebar tabs.
<Sidebar.Tabs>
  <Sidebar.Tab tab="tab1">Tab 1 Content</Sidebar.Tab>
  <Sidebar.Tab tab="tab2">Tab 2 Content</Sidebar.Tab>
</Sidebar.Tabs>
children
React.ReactNode
required
Sidebar.Tab components.
Individual tab content.
<Sidebar.Tab tab="my-tab">
  <div>Tab content goes here</div>
</Sidebar.Tab>
tab
string
required
Unique identifier for the tab.
tab: SidebarTabName;
children
React.ReactNode
required
Tab content.
Container for tab trigger buttons.
<Sidebar.TabTriggers>
  <Sidebar.TabTrigger tab="tab1">Tab 1</Sidebar.TabTrigger>
  <Sidebar.TabTrigger tab="tab2">Tab 2</Sidebar.TabTrigger>
</Sidebar.TabTriggers>
children
React.ReactNode
required
Sidebar.TabTrigger components.
Button to switch between tabs.
<Sidebar.TabTrigger tab="my-tab">
  Tab Label
</Sidebar.TabTrigger>
tab
string
required
Tab identifier to activate.
tab: SidebarTabName;
children
React.ReactNode
required
Tab trigger label.

Example

import { useState } from "react";
import { Excalidraw, Sidebar } from "@excalidraw/excalidraw";

function App() {
  const [docked, setDocked] = useState(true);

  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw>
        <Sidebar
          name="custom-sidebar"
          docked={docked}
          onDock={setDocked}
          onStateChange={(state) => console.log("Sidebar state:", state)}
        >
          <Sidebar.Header>
            Custom Sidebar
          </Sidebar.Header>
          
          <Sidebar.TabTriggers>
            <Sidebar.TabTrigger tab="tab1">Tab 1</Sidebar.TabTrigger>
            <Sidebar.TabTrigger tab="tab2">Tab 2</Sidebar.TabTrigger>
          </Sidebar.TabTriggers>
          
          <Sidebar.Tabs>
            <Sidebar.Tab tab="tab1">
              <div style={{ padding: "1rem" }}>
                <h3>Tab 1 Content</h3>
                <p>Your custom content here</p>
              </div>
            </Sidebar.Tab>
            
            <Sidebar.Tab tab="tab2">
              <div style={{ padding: "1rem" }}>
                <h3>Tab 2 Content</h3>
                <p>More custom content</p>
              </div>
            </Sidebar.Tab>
          </Sidebar.Tabs>
        </Sidebar>
        
        {/* Sidebar trigger button in the UI */}
        <Sidebar.Trigger 
          name="custom-sidebar"
          icon={sidebarIcon}
          title="Open Custom Sidebar"
        />
      </Excalidraw>
    </div>
  );
}
The Footer component renders the bottom toolbar with zoom controls and undo/redo buttons. It’s exported for use when building custom layouts, but is typically rendered automatically by Excalidraw.
import { Footer } from "@excalidraw/excalidraw";
The Footer component is usually rendered automatically. You only need to import it if you’re building a completely custom layout.

WelcomeScreen

The WelcomeScreen component displays a welcome message when the canvas is empty.

Props

children
React.ReactNode
Custom welcome screen content. If not provided, renders default hints and center content.

Subcomponents

WelcomeScreen.Center

Central welcome message area.
<WelcomeScreen>
  <WelcomeScreen.Center>
    <WelcomeScreen.Center.Logo />
    <WelcomeScreen.Center.Heading>
      Welcome to My App!
    </WelcomeScreen.Center.Heading>
    <WelcomeScreen.Center.Menu>
      <WelcomeScreen.Center.MenuItemLoadScene />
      <WelcomeScreen.Center.MenuItemHelp />
    </WelcomeScreen.Center.Menu>
  </WelcomeScreen.Center>
</WelcomeScreen>
Sub-subcomponents:
  • WelcomeScreen.Center.Logo - Excalidraw logo
  • WelcomeScreen.Center.Heading - Custom heading text
  • WelcomeScreen.Center.Menu - Container for menu items
  • WelcomeScreen.Center.MenuItemLoadScene - Load scene button
  • WelcomeScreen.Center.MenuItemHelp - Help button
  • WelcomeScreen.Center.MenuItemLiveCollaborationTrigger - Collaboration button

WelcomeScreen.Hints

UI hints around the editor.
<WelcomeScreen>
  <WelcomeScreen.Hints.MenuHint />
  <WelcomeScreen.Hints.ToolbarHint />
  <WelcomeScreen.Hints.HelpHint />
</WelcomeScreen>
Available hints:
  • WelcomeScreen.Hints.MenuHint - Points to main menu
  • WelcomeScreen.Hints.ToolbarHint - Points to toolbar
  • WelcomeScreen.Hints.HelpHint - Points to help button

Example

import { Excalidraw, WelcomeScreen } from "@excalidraw/excalidraw";

function App() {
  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw>
        <WelcomeScreen>
          <WelcomeScreen.Center>
            <WelcomeScreen.Center.Logo />
            <WelcomeScreen.Center.Heading>
              Start Drawing Amazing Diagrams!
            </WelcomeScreen.Center.Heading>
            <WelcomeScreen.Center.Menu>
              <WelcomeScreen.Center.MenuItemLoadScene />
              <WelcomeScreen.Center.MenuItemHelp />
            </WelcomeScreen.Center.Menu>
          </WelcomeScreen.Center>
          <WelcomeScreen.Hints.MenuHint />
          <WelcomeScreen.Hints.ToolbarHint />
          <WelcomeScreen.Hints.HelpHint />
        </WelcomeScreen>
      </Excalidraw>
    </div>
  );
}

Button

A generic button component that follows Excalidraw’s design system.

Props

onSelect
function
required
Callback when button is clicked.
onSelect: () => void;
children
React.ReactNode
required
Button content (text, icons, etc.).
type
'button' | 'submit' | 'reset'
default:"button"
HTML button type.
selected
boolean
Whether button is in active/selected state.
className
string
Additional CSS class name for styling.
...rest
ButtonHTMLAttributes
All standard HTML button attributes are supported (disabled, style, aria-*, etc.).

Example

import { Button } from "@excalidraw/excalidraw";

function MyComponent() {
  const handleClick = () => {
    console.log("Button clicked");
  };

  return (
    <Button 
      onSelect={handleClick}
      selected={false}
      className="my-custom-button"
      disabled={false}
    >
      Click Me
    </Button>
  );
}

LiveCollaborationTrigger

A button component for triggering live collaboration mode, displaying the share icon and active collaborator count.

Props

isCollaborating
boolean
required
Whether collaboration mode is active.
isCollaborating: boolean;
onSelect
function
required
Callback when the button is clicked.
onSelect: () => void;
editorInterface
EditorInterface
Editor interface details for responsive behavior.
editorInterface?: EditorInterface;
...rest
ButtonHTMLAttributes
All standard HTML button attributes are supported.

Example

import { useState } from "react";
import { Excalidraw, LiveCollaborationTrigger } from "@excalidraw/excalidraw";

function App() {
  const [isCollaborating, setIsCollaborating] = useState(false);

  const handleCollaboration = () => {
    setIsCollaborating(!isCollaborating);
    // Your collaboration logic here
  };

  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw isCollaborating={isCollaborating}>
        <LiveCollaborationTrigger
          isCollaborating={isCollaborating}
          onSelect={handleCollaboration}
        />
      </Excalidraw>
    </div>
  );
}

Complete Example

Here’s a comprehensive example using multiple UI components together:
import { useState } from "react";
import {
  Excalidraw,
  MainMenu,
  Sidebar,
  WelcomeScreen,
  LiveCollaborationTrigger,
  Button,
} from "@excalidraw/excalidraw";

function App() {
  const [isCollaborating, setIsCollaborating] = useState(false);
  const [sidebarDocked, setSidebarDocked] = useState(true);

  const handleExport = () => {
    console.log("Export triggered");
  };

  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw isCollaborating={isCollaborating}>
        {/* Main Menu */}
        <MainMenu>
          <MainMenu.DefaultItems.LoadScene />
          <MainMenu.DefaultItems.Export />
          <MainMenu.Separator />
          <MainMenu.Item onSelect={handleExport} icon={exportIcon}>
            Export to Cloud
          </MainMenu.Item>
          <MainMenu.Separator />
          <MainMenu.DefaultItems.Help />
        </MainMenu>

        {/* Custom Sidebar */}
        <Sidebar
          name="my-sidebar"
          docked={sidebarDocked}
          onDock={setSidebarDocked}
        >
          <Sidebar.Header>Tools</Sidebar.Header>
          <Sidebar.TabTriggers>
            <Sidebar.TabTrigger tab="shapes">Shapes</Sidebar.TabTrigger>
            <Sidebar.TabTrigger tab="assets">Assets</Sidebar.TabTrigger>
          </Sidebar.TabTriggers>
          <Sidebar.Tabs>
            <Sidebar.Tab tab="shapes">
              <div style={{ padding: "1rem" }}>
                <h3>Custom Shapes</h3>
                {/* Your custom shapes */}
              </div>
            </Sidebar.Tab>
            <Sidebar.Tab tab="assets">
              <div style={{ padding: "1rem" }}>
                <h3>Assets Library</h3>
                {/* Your assets */}
              </div>
            </Sidebar.Tab>
          </Sidebar.Tabs>
        </Sidebar>

        {/* Welcome Screen */}
        <WelcomeScreen>
          <WelcomeScreen.Center>
            <WelcomeScreen.Center.Logo />
            <WelcomeScreen.Center.Heading>
              Create Amazing Diagrams
            </WelcomeScreen.Center.Heading>
            <WelcomeScreen.Center.Menu>
              <WelcomeScreen.Center.MenuItemLoadScene />
              <WelcomeScreen.Center.MenuItemHelp />
            </WelcomeScreen.Center.Menu>
          </WelcomeScreen.Center>
          <WelcomeScreen.Hints.MenuHint />
          <WelcomeScreen.Hints.ToolbarHint />
          <WelcomeScreen.Hints.HelpHint />
        </WelcomeScreen>

        {/* Collaboration Trigger */}
        <LiveCollaborationTrigger
          isCollaborating={isCollaborating}
          onSelect={() => setIsCollaborating(!isCollaborating)}
        />
      </Excalidraw>
    </div>
  );
}

export default App;

Styling

All UI components can be styled using CSS classes:
/* MainMenu */
.main-menu-trigger { }
.main-menu { }
.main-menu-item { }

/* Sidebar */
.excalidraw-sidebar { }
.excalidraw-sidebar.sidebar--docked { }

/* Button */
.excalidraw-button { }
.excalidraw-button.selected { }

/* LiveCollaborationTrigger */
.collab-button { }
.collab-button.active { }
.CollabButton-collaborators { }

Stats

The Stats component displays canvas statistics and element properties in a floating panel. It provides detailed information about selected elements and the overall scene.

Props

app
AppClassProperties
required
The Excalidraw app instance.
app: AppClassProperties;
onClose
function
required
Callback when the stats panel is closed.
onClose: () => void;
renderCustomStats
function
Render custom statistics in the panel.
renderCustomStats?: (
  elements: readonly NonDeletedExcalidrawElement[],
  appState: AppState
) => React.ReactNode;

Subcomponents

Stats.StatsRow

Renders a row in the stats panel.
<Stats.StatsRow columns={2}>
  <div>Width</div>
  <div>100</div>
</Stats.StatsRow>
columns
number
default:"1"
Number of columns in the row grid.
heading
boolean
Whether this row is a heading.

Stats.StatsRows

Container for multiple stat rows with optional ordering.
<Stats.StatsRows order={1}>
  {/* Multiple StatsRow components */}
</Stats.StatsRows>
order
number
Display order of this stats group.

Example

import { Stats } from "@excalidraw/excalidraw";

function CustomStats() {
  const renderCustomStats = (elements, appState) => (
    <Stats.StatsRows order={999}>
      <Stats.StatsRow heading>Custom Stats</Stats.StatsRow>
      <Stats.StatsRow columns={2}>
        <div>Total Elements</div>
        <div>{elements.length}</div>
      </Stats.StatsRow>
    </Stats.StatsRows>
  );

  return (
    <Excalidraw
      renderCustomStats={renderCustomStats}
    />
  );
}

DefaultSidebar

The DefaultSidebar component provides the default sidebar with library and search functionality.

Props

children
React.ReactNode
Custom sidebar tabs to add to the default sidebar.
docked
boolean
Whether the sidebar is docked.
onDock
function | false
Callback when sidebar dock state changes. Pass false to disable docking.
onDock?: ((docked: boolean) => void) | false;
className
string
Additional CSS class name.

Subcomponents

DefaultSidebar.Trigger

Trigger button for the default sidebar.
<DefaultSidebar.Trigger
  icon={<MyIcon />}
  title="Open Sidebar"
/>

DefaultSidebar.TabTriggers

Container for adding custom tab triggers to the default sidebar.
<DefaultSidebar.TabTriggers>
  <Sidebar.TabTrigger tab="my-custom-tab">
    My Tab
  </Sidebar.TabTrigger>
</DefaultSidebar.TabTriggers>

Example

import { Excalidraw, DefaultSidebar, Sidebar } from "@excalidraw/excalidraw";

function App() {
  return (
    <div style={{ height: "100vh" }}>
      <Excalidraw>
        <DefaultSidebar>
          <Sidebar.Tab tab="custom-tab">
            <div style={{ padding: "1rem" }}>
              Custom tab content
            </div>
          </Sidebar.Tab>
        </DefaultSidebar>
        
        <DefaultSidebar.Trigger />
      </Excalidraw>
    </div>
  );
}

Ellipsify

A utility component that adds text ellipsis overflow handling.

Props

children
React.ReactNode
required
Content to ellipsify.
...rest
React.HTMLAttributes<HTMLSpanElement>
All standard HTML span attributes are supported.

Example

import { Ellipsify } from "@excalidraw/excalidraw";

<Ellipsify style={{ maxWidth: "200px" }}>
  This is a very long text that will be truncated with ellipsis
</Ellipsify>

TTDDialog

Text-to-Diagram dialog component for AI-powered diagram generation.

Props

onTextSubmit
function
required
Callback when text is submitted for diagram generation.
onTextSubmit: (props: {
  prompt: string;
  sessionId: string;
}) => Promise<{
  generatedResponse: string;
  error: Error | null;
}>;
renderWelcomeScreen
function
Render custom welcome screen content.
renderWelcomeScreen?: () => React.ReactNode;
renderWarning
function
Render custom warning message.
renderWarning?: () => React.ReactNode;
persistenceAdapter
TTDPersistenceAdapter
required
Adapter for persisting chat history.
persistenceAdapter: {
  load: () => Promise<SavedChats | null>;
  save: (chats: SavedChats) => Promise<void>;
  clear: () => Promise<void>;
};

Subcomponents

TTDDialog.WelcomeMessage

Default welcome message component.
<TTDDialog.WelcomeMessage />

Example

import { Excalidraw, TTDDialog } from "@excalidraw/excalidraw";

function App() {
  const handleTextSubmit = async ({ prompt }) => {
    // Call your AI API
    const response = await fetch("/api/generate-diagram", {
      method: "POST",
      body: JSON.stringify({ prompt }),
    });
    
    const data = await response.json();
    return {
      generatedResponse: data.mermaidCode,
      error: null,
    };
  };

  const persistenceAdapter = {
    load: async () => {
      const saved = localStorage.getItem("ttd-chats");
      return saved ? JSON.parse(saved) : null;
    },
    save: async (chats) => {
      localStorage.setItem("ttd-chats", JSON.stringify(chats));
    },
    clear: async () => {
      localStorage.removeItem("ttd-chats");
    },
  };

  return (
    <Excalidraw>
      <TTDDialog
        onTextSubmit={handleTextSubmit}
        persistenceAdapter={persistenceAdapter}
      />
    </Excalidraw>
  );
}

TTDDialogTrigger

Trigger button to open the Text-to-Diagram dialog.

Props

children
React.ReactNode
Custom button label. Defaults to “Text to Diagram”.
icon
JSX.Element
Custom icon for the trigger button.

Example

import { MainMenu, TTDDialogTrigger } from "@excalidraw/excalidraw";

<MainMenu>
  <TTDDialogTrigger>
    Generate Diagram with AI
  </TTDDialogTrigger>
</MainMenu>

TTDStreamFetch

Utility function for streaming text-to-diagram API responses.
function TTDStreamFetch(options: {
  url: string;
  messages: readonly LLMMessage[];
  onChunk?: (chunk: string) => void;
  extractRateLimits?: boolean;
  signal?: AbortSignal;
  onStreamCreated?: () => void;
}): Promise<{
  generatedResponse?: string;
  error: Error | null;
  rateLimit?: number;
  rateLimitRemaining?: number;
}>;

Parameters

url
string
required
API endpoint URL for streaming.
messages
readonly LLMMessage[]
required
Array of messages to send to the LLM.
onChunk
function
Callback for each chunk of streamed text.
onChunk?: (chunk: string) => void;
extractRateLimits
boolean
default:"true"
Whether to extract rate limit headers from the response.
signal
AbortSignal
AbortSignal for cancelling the request.
onStreamCreated
function
Callback when the stream is created.

Example

import { TTDStreamFetch } from "@excalidraw/excalidraw";

const controller = new AbortController();

const result = await TTDStreamFetch({
  url: "/api/generate-diagram",
  messages: [
    { role: "user", content: "Create a flowchart for user authentication" }
  ],
  onChunk: (chunk) => {
    console.log("Received chunk:", chunk);
  },
  signal: controller.signal,
});

if (!result.error) {
  console.log("Generated:", result.generatedResponse);
}

DiagramToCodePlugin

Plugin component for adding diagram-to-code conversion functionality.

Props

generate
function
required
Function to generate code from the diagram.
generate: (opts: {
  elements: readonly NonDeletedExcalidrawElement[];
  files: BinaryFiles;
  appState: AppState;
  frameId?: string;
}) => Promise<{
  code: string;
  language: string;
}>;

Example

import { Excalidraw, DiagramToCodePlugin } from "@excalidraw/excalidraw";

function App() {
  const generateCode = async ({ elements, frameId }) => {
    // Your code generation logic
    const code = await convertElementsToCode(elements);
    
    return {
      code,
      language: "typescript",
    };
  };

  return (
    <Excalidraw>
      <DiagramToCodePlugin generate={generateCode} />
    </Excalidraw>
  );
}

CommandPalette

Command palette component for quick access to editor actions via keyboard shortcuts.

Props

customCommandPaletteItems
CommandPaletteItem[]
Custom commands to add to the palette.
interface CommandPaletteItem {
  label: string;
  category: string;
  icon?: JSX.Element;
  shortcut?: string;
  keywords?: string[];
  viewMode?: boolean;
  predicate?: boolean | PredicateFunction;
  perform: (opts: { 
    actionManager: ActionManager;
    event: React.MouseEvent | React.KeyboardEvent | KeyboardEvent;
  }) => void;
}

Default Items

The CommandPalette.defaultItems export provides access to pre-built command items:
import { CommandPalette } from "@excalidraw/excalidraw";

// Available default items include:
// - exportImage
// - loadScene
// - clearCanvas
// - changeViewBackgroundColor
// And more...

Example

import { Excalidraw, CommandPalette } from "@excalidraw/excalidraw";

function App() {
  const customCommands = [
    {
      label: "Export to Cloud",
      category: "Export",
      icon: <CloudIcon />,
      keywords: ["save", "upload"],
      perform: ({ actionManager }) => {
        // Your export logic
        console.log("Exporting to cloud...");
      },
    },
  ];

  return (
    <Excalidraw>
      <CommandPalette customCommandPaletteItems={customCommands} />
    </Excalidraw>
  );
}
The command palette opens with Cmd/Ctrl + Shift + P or Cmd/Ctrl + /.

Hooks

useEditorInterface

Hook to access the editor’s interface information including form factor and sidebar visibility.
function useEditorInterface(): {
  formFactor: "desktop" | "tablet" | "phone";
  isSidebarDocked: boolean;
};
Example:
import { useEditorInterface } from "@excalidraw/excalidraw";

function MyComponent() {
  const editorInterface = useEditorInterface();
  
  if (editorInterface.formFactor === "phone") {
    return <MobileView />;
  }
  
  return <DesktopView />;
}

useStylesPanelMode

Hook to get the current styles panel mode derived from the editor interface.
function useStylesPanelMode(): "inline" | "popover";
Example:
import { useStylesPanelMode } from "@excalidraw/excalidraw";

function MyComponent() {
  const mode = useStylesPanelMode();
  
  return (
    <div className={`styles-panel-${mode}`}>
      {/* Your component content */}
    </div>
  );
}

See Also