> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/excalidraw/excalidraw/llms.txt
> Use this file to discover all available pages before exploring further.

# UI Components API

> Complete API reference for Excalidraw UI components including MainMenu, Sidebar, Footer, and more

# 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

```jsx theme={null}
import {
  MainMenu,
  Sidebar,
  Footer,
  WelcomeScreen,
  Button,
  LiveCollaborationTrigger,
  Stats,
  DefaultSidebar,
  Ellipsify,
  TTDDialog,
  TTDDialogTrigger,
  TTDStreamFetch,
  DiagramToCodePlugin,
  CommandPalette,
  useEditorInterface,
  useStylesPanelMode,
} from "@excalidraw/excalidraw";
```

## MainMenu

The `MainMenu` component provides a customizable dropdown menu accessed via a hamburger icon.

### Props

<ParamField path="children" type="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`.
</ParamField>

<ParamField path="onSelect" type="function">
  Callback fired when any menu item is selected (clicked on).

  ```typescript theme={null}
  onSelect?: (event: Event) => void;
  ```
</ParamField>

### Subcomponents

#### MainMenu.Item

A clickable menu item that triggers an action.

```jsx theme={null}
<MainMenu.Item 
  onSelect={handleAction}
  icon={<MyIcon />}
  shortcut="⌘K"
>
  Menu Item Label
</MainMenu.Item>
```

<ParamField path="onSelect" type="function" required>
  Callback when item is clicked.

  ```typescript theme={null}
  onSelect: () => void;
  ```
</ParamField>

<ParamField path="icon" type="JSX.Element">
  Icon to display before the label.
</ParamField>

<ParamField path="shortcut" type="string">
  Keyboard shortcut to display (e.g., "⌘K", "Ctrl+S").
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Label content for the menu item.
</ParamField>

#### MainMenu.ItemLink

A menu item that opens a link in a new tab.

```jsx theme={null}
<MainMenu.ItemLink 
  href="https://example.com"
  icon={<LinkIcon />}
  shortcut="⌘L"
>
  External Link
</MainMenu.ItemLink>
```

<ParamField path="href" type="string" required>
  URL to open when clicked.
</ParamField>

<ParamField path="icon" type="JSX.Element">
  Icon to display before the label.
</ParamField>

<ParamField path="shortcut" type="string">
  Keyboard shortcut to display.
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Label content for the menu item.
</ParamField>

#### MainMenu.ItemCustom

A fully custom menu item with complete control over rendering.

```jsx theme={null}
<MainMenu.ItemCustom>
  <div className="custom-menu-item">
    {/* Your custom content */}
  </div>
</MainMenu.ItemCustom>
```

<ParamField path="children" type="React.ReactNode" required>
  Custom content to render.
</ParamField>

#### MainMenu.Separator

A visual separator between menu items.

```jsx theme={null}
<MainMenu.Separator />
```

No props.

#### MainMenu.Group

Groups related menu items together.

```jsx theme={null}
<MainMenu.Group>
  <MainMenu.Item onSelect={handler1}>Item 1</MainMenu.Item>
  <MainMenu.Item onSelect={handler2}>Item 2</MainMenu.Item>
</MainMenu.Group>
```

<ParamField path="children" type="React.ReactNode" required>
  Menu items to group together.
</ParamField>

#### MainMenu.Sub

Creates a submenu.

```jsx theme={null}
<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>
```

<ParamField path="label" type="string" required>
  Label for the submenu trigger.
</ParamField>

<ParamField path="icon" type="JSX.Element">
  Icon to display before the label.
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Menu items to display in the submenu.
</ParamField>

#### MainMenu.Trigger

Custom trigger component to open the menu (overrides default hamburger icon).

```jsx theme={null}
<MainMenu.Trigger>
  <button>Open Menu</button>
</MainMenu.Trigger>
```

<ParamField path="children" type="React.ReactNode" required>
  Custom trigger element.
</ParamField>

### Default Items

Excalidraw provides pre-built menu items accessible via `MainMenu.DefaultItems`:

<ParamField path="MainMenu.DefaultItems.LoadScene" type="component">
  Opens a file picker to load a scene from a .excalidraw file.

  ```jsx theme={null}
  <MainMenu.DefaultItems.LoadScene />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.SaveToActiveFile" type="component">
  Saves the current scene to the active file (requires File System Access API).

  ```jsx theme={null}
  <MainMenu.DefaultItems.SaveToActiveFile />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.Export" type="component">
  Opens the export dialog to save as PNG, SVG, or JSON.

  ```jsx theme={null}
  <MainMenu.DefaultItems.Export />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.SaveAsImage" type="component">
  Quickly export the canvas as an image.

  ```jsx theme={null}
  <MainMenu.DefaultItems.SaveAsImage />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.Help" type="component">
  Opens the help dialog showing keyboard shortcuts.

  ```jsx theme={null}
  <MainMenu.DefaultItems.Help />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.ClearCanvas" type="component">
  Clears all elements from the canvas.

  ```jsx theme={null}
  <MainMenu.DefaultItems.ClearCanvas />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.ToggleTheme" type="component">
  Toggles between light and dark themes.

  ```jsx theme={null}
  <MainMenu.DefaultItems.ToggleTheme />
  ```
</ParamField>

<ParamField path="MainMenu.DefaultItems.ChangeCanvasBackground" type="component">
  Opens a color picker to change the canvas background.

  ```jsx theme={null}
  <MainMenu.DefaultItems.ChangeCanvasBackground />
  ```
</ParamField>

### Example

```jsx theme={null}
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>
  );
}
```

## Sidebar

The `Sidebar` component provides a customizable sidebar that can be docked or floating.

### Props

<ParamField path="name" type="string" required>
  Unique name for the sidebar. Used to identify and control the sidebar state.

  ```typescript theme={null}
  name: SidebarName; // string
  ```
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Sidebar content including `Sidebar.Header`, `Sidebar.Tabs`, `Sidebar.Tab`, etc.
</ParamField>

<ParamField path="onStateChange" type="function">
  Called on sidebar open/close or tab change.

  ```typescript theme={null}
  onStateChange?: (state: { name: string; tab?: string } | null) => void;
  ```

  **Parameters:**

  * `state` - Current open sidebar state, or `null` if closed
</ParamField>

<ParamField path="onDock" type="function">
  Supply alongside `docked` prop to make the sidebar user-dockable.

  ```typescript theme={null}
  onDock?: (docked: boolean) => void;
  ```
</ParamField>

<ParamField path="docked" type="boolean">
  Controls whether the sidebar is docked. Must be used with `onDock` to enable user docking.

  ```typescript theme={null}
  docked?: boolean;
  ```
</ParamField>

<ParamField path="className" type="string">
  Additional CSS class name for styling.
</ParamField>

### Subcomponents

#### Sidebar.Header

Header component for the sidebar with title and optional dock/close buttons.

```jsx theme={null}
<Sidebar.Header>
  <h2>My Sidebar</h2>
</Sidebar.Header>
```

<ParamField path="children" type="React.ReactNode" required>
  Header content (typically a title).
</ParamField>

#### Sidebar.Trigger

Button to open/close the sidebar.

```jsx theme={null}
<Sidebar.Trigger 
  name="my-sidebar"
  icon={<MyIcon />}
  title="Open Sidebar"
/>
```

<ParamField path="name" type="string" required>
  Name of the sidebar to trigger (must match the Sidebar's `name` prop).

  ```typescript theme={null}
  name: SidebarName;
  ```
</ParamField>

<ParamField path="tab" type="string">
  Optional tab name to open when triggering the sidebar.

  ```typescript theme={null}
  tab?: SidebarTabName;
  ```
</ParamField>

<ParamField path="icon" type="JSX.Element">
  Icon to display in the trigger button.
</ParamField>

<ParamField path="title" type="string">
  Tooltip text for the trigger button.
</ParamField>

<ParamField path="className" type="string">
  Additional CSS class name.
</ParamField>

<ParamField path="onToggle" type="function">
  Callback when the trigger is clicked.

  ```typescript theme={null}
  onToggle?: (open: boolean) => void;
  ```
</ParamField>

<ParamField path="style" type="React.CSSProperties">
  Inline styles for the trigger button.
</ParamField>

#### Sidebar.Tabs

Container for sidebar tabs.

```jsx theme={null}
<Sidebar.Tabs>
  <Sidebar.Tab tab="tab1">Tab 1 Content</Sidebar.Tab>
  <Sidebar.Tab tab="tab2">Tab 2 Content</Sidebar.Tab>
</Sidebar.Tabs>
```

<ParamField path="children" type="React.ReactNode" required>
  `Sidebar.Tab` components.
</ParamField>

#### Sidebar.Tab

Individual tab content.

```jsx theme={null}
<Sidebar.Tab tab="my-tab">
  <div>Tab content goes here</div>
</Sidebar.Tab>
```

<ParamField path="tab" type="string" required>
  Unique identifier for the tab.

  ```typescript theme={null}
  tab: SidebarTabName;
  ```
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Tab content.
</ParamField>

#### Sidebar.TabTriggers

Container for tab trigger buttons.

```jsx theme={null}
<Sidebar.TabTriggers>
  <Sidebar.TabTrigger tab="tab1">Tab 1</Sidebar.TabTrigger>
  <Sidebar.TabTrigger tab="tab2">Tab 2</Sidebar.TabTrigger>
</Sidebar.TabTriggers>
```

<ParamField path="children" type="React.ReactNode" required>
  `Sidebar.TabTrigger` components.
</ParamField>

#### Sidebar.TabTrigger

Button to switch between tabs.

```jsx theme={null}
<Sidebar.TabTrigger tab="my-tab">
  Tab Label
</Sidebar.TabTrigger>
```

<ParamField path="tab" type="string" required>
  Tab identifier to activate.

  ```typescript theme={null}
  tab: SidebarTabName;
  ```
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Tab trigger label.
</ParamField>

### Example

```jsx theme={null}
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>
  );
}
```

## Footer

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.

```jsx theme={null}
import { Footer } from "@excalidraw/excalidraw";
```

<Info>The Footer component is usually rendered automatically. You only need to import it if you're building a completely custom layout.</Info>

## WelcomeScreen

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

### Props

<ParamField path="children" type="React.ReactNode">
  Custom welcome screen content. If not provided, renders default hints and center content.
</ParamField>

### Subcomponents

#### WelcomeScreen.Center

Central welcome message area.

```jsx theme={null}
<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.

```jsx theme={null}
<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

```jsx theme={null}
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

<ParamField path="onSelect" type="function" required>
  Callback when button is clicked.

  ```typescript theme={null}
  onSelect: () => void;
  ```
</ParamField>

<ParamField path="children" type="React.ReactNode" required>
  Button content (text, icons, etc.).
</ParamField>

<ParamField path="type" type="'button' | 'submit' | 'reset'" default="button">
  HTML button type.
</ParamField>

<ParamField path="selected" type="boolean">
  Whether button is in active/selected state.
</ParamField>

<ParamField path="className" type="string">
  Additional CSS class name for styling.
</ParamField>

<ParamField path="...rest" type="ButtonHTMLAttributes">
  All standard HTML button attributes are supported (disabled, style, aria-\*, etc.).
</ParamField>

### Example

```jsx theme={null}
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

<ParamField path="isCollaborating" type="boolean" required>
  Whether collaboration mode is active.

  ```typescript theme={null}
  isCollaborating: boolean;
  ```
</ParamField>

<ParamField path="onSelect" type="function" required>
  Callback when the button is clicked.

  ```typescript theme={null}
  onSelect: () => void;
  ```
</ParamField>

<ParamField path="editorInterface" type="EditorInterface">
  Editor interface details for responsive behavior.

  ```typescript theme={null}
  editorInterface?: EditorInterface;
  ```
</ParamField>

<ParamField path="...rest" type="ButtonHTMLAttributes">
  All standard HTML button attributes are supported.
</ParamField>

### Example

```jsx theme={null}
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:

```jsx theme={null}
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:

```css theme={null}
/* 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

<ParamField path="app" type="AppClassProperties" required>
  The Excalidraw app instance.

  ```typescript theme={null}
  app: AppClassProperties;
  ```
</ParamField>

<ParamField path="onClose" type="function" required>
  Callback when the stats panel is closed.

  ```typescript theme={null}
  onClose: () => void;
  ```
</ParamField>

<ParamField path="renderCustomStats" type="function">
  Render custom statistics in the panel.

  ```typescript theme={null}
  renderCustomStats?: (
    elements: readonly NonDeletedExcalidrawElement[],
    appState: AppState
  ) => React.ReactNode;
  ```
</ParamField>

### Subcomponents

#### Stats.StatsRow

Renders a row in the stats panel.

```jsx theme={null}
<Stats.StatsRow columns={2}>
  <div>Width</div>
  <div>100</div>
</Stats.StatsRow>
```

<ParamField path="columns" type="number" default="1">
  Number of columns in the row grid.
</ParamField>

<ParamField path="heading" type="boolean">
  Whether this row is a heading.
</ParamField>

#### Stats.StatsRows

Container for multiple stat rows with optional ordering.

```jsx theme={null}
<Stats.StatsRows order={1}>
  {/* Multiple StatsRow components */}
</Stats.StatsRows>
```

<ParamField path="order" type="number">
  Display order of this stats group.
</ParamField>

### Example

```jsx theme={null}
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

<ParamField path="children" type="React.ReactNode">
  Custom sidebar tabs to add to the default sidebar.
</ParamField>

<ParamField path="docked" type="boolean">
  Whether the sidebar is docked.
</ParamField>

<ParamField path="onDock" type="function | false">
  Callback when sidebar dock state changes. Pass `false` to disable docking.

  ```typescript theme={null}
  onDock?: ((docked: boolean) => void) | false;
  ```
</ParamField>

<ParamField path="className" type="string">
  Additional CSS class name.
</ParamField>

### Subcomponents

#### DefaultSidebar.Trigger

Trigger button for the default sidebar.

```jsx theme={null}
<DefaultSidebar.Trigger
  icon={<MyIcon />}
  title="Open Sidebar"
/>
```

#### DefaultSidebar.TabTriggers

Container for adding custom tab triggers to the default sidebar.

```jsx theme={null}
<DefaultSidebar.TabTriggers>
  <Sidebar.TabTrigger tab="my-custom-tab">
    My Tab
  </Sidebar.TabTrigger>
</DefaultSidebar.TabTriggers>
```

### Example

```jsx theme={null}
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

<ParamField path="children" type="React.ReactNode" required>
  Content to ellipsify.
</ParamField>

<ParamField path="...rest" type="React.HTMLAttributes<HTMLSpanElement>">
  All standard HTML span attributes are supported.
</ParamField>

### Example

```jsx theme={null}
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

<ParamField path="onTextSubmit" type="function" required>
  Callback when text is submitted for diagram generation.

  ```typescript theme={null}
  onTextSubmit: (props: {
    prompt: string;
    sessionId: string;
  }) => Promise<{
    generatedResponse: string;
    error: Error | null;
  }>;
  ```
</ParamField>

<ParamField path="renderWelcomeScreen" type="function">
  Render custom welcome screen content.

  ```typescript theme={null}
  renderWelcomeScreen?: () => React.ReactNode;
  ```
</ParamField>

<ParamField path="renderWarning" type="function">
  Render custom warning message.

  ```typescript theme={null}
  renderWarning?: () => React.ReactNode;
  ```
</ParamField>

<ParamField path="persistenceAdapter" type="TTDPersistenceAdapter" required>
  Adapter for persisting chat history.

  ```typescript theme={null}
  persistenceAdapter: {
    load: () => Promise<SavedChats | null>;
    save: (chats: SavedChats) => Promise<void>;
    clear: () => Promise<void>;
  };
  ```
</ParamField>

### Subcomponents

#### TTDDialog.WelcomeMessage

Default welcome message component.

```jsx theme={null}
<TTDDialog.WelcomeMessage />
```

### Example

```jsx theme={null}
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

<ParamField path="children" type="React.ReactNode">
  Custom button label. Defaults to "Text to Diagram".
</ParamField>

<ParamField path="icon" type="JSX.Element">
  Custom icon for the trigger button.
</ParamField>

### Example

```jsx theme={null}
import { MainMenu, TTDDialogTrigger } from "@excalidraw/excalidraw";

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

## TTDStreamFetch

Utility function for streaming text-to-diagram API responses.

```typescript theme={null}
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

<ParamField path="url" type="string" required>
  API endpoint URL for streaming.
</ParamField>

<ParamField path="messages" type="readonly LLMMessage[]" required>
  Array of messages to send to the LLM.
</ParamField>

<ParamField path="onChunk" type="function">
  Callback for each chunk of streamed text.

  ```typescript theme={null}
  onChunk?: (chunk: string) => void;
  ```
</ParamField>

<ParamField path="extractRateLimits" type="boolean" default="true">
  Whether to extract rate limit headers from the response.
</ParamField>

<ParamField path="signal" type="AbortSignal">
  AbortSignal for cancelling the request.
</ParamField>

<ParamField path="onStreamCreated" type="function">
  Callback when the stream is created.
</ParamField>

### Example

```jsx theme={null}
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

<ParamField path="generate" type="function" required>
  Function to generate code from the diagram.

  ```typescript theme={null}
  generate: (opts: {
    elements: readonly NonDeletedExcalidrawElement[];
    files: BinaryFiles;
    appState: AppState;
    frameId?: string;
  }) => Promise<{
    code: string;
    language: string;
  }>;
  ```
</ParamField>

### Example

```jsx theme={null}
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

<ParamField path="customCommandPaletteItems" type="CommandPaletteItem[]">
  Custom commands to add to the palette.

  ```typescript theme={null}
  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;
  }
  ```
</ParamField>

### Default Items

The `CommandPalette.defaultItems` export provides access to pre-built command items:

```jsx theme={null}
import { CommandPalette } from "@excalidraw/excalidraw";

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

### Example

```jsx theme={null}
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.

```typescript theme={null}
function useEditorInterface(): {
  formFactor: "desktop" | "tablet" | "phone";
  isSidebarDocked: boolean;
};
```

**Example:**

```jsx theme={null}
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.

```typescript theme={null}
function useStylesPanelMode(): "inline" | "popover";
```

**Example:**

```jsx theme={null}
import { useStylesPanelMode } from "@excalidraw/excalidraw";

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

## See Also

* [Excalidraw Component API](/api/excalidraw-component) - Main component API reference
* [MainMenu](/components/main-menu) - MainMenu usage guide
* [Sidebar](/components/sidebar) - Sidebar usage guide
* [WelcomeScreen](/components/welcome-screen) - WelcomeScreen usage guide
* [Customization Guide](/guides/customization) - Customize component appearance
