Button Components
Excalidraw provides several button components that follow the editor’s design system. These components ensure visual consistency and provide common button patterns used throughout the editor.
The main Button component is a generic button that accepts all standard HTML button props and adds Excalidraw styling.
Basic Usage
Simple Button
Button with Selected State
Custom Styled Button
import { Button } from "@excalidraw/excalidraw" ;
function MyComponent () {
const handleClick = () => {
console . log ( "Button clicked" );
};
return (
< Button onSelect = { handleClick } >
Click Me
</ Button >
);
}
Props
Callback function executed when the button is clicked.
Whether the button is in an active/selected state. Adds visual styling to indicate selection.
The button content (text, icons, or other elements).
type
'button' | 'submit' | 'reset'
default: "'button'"
The HTML button type attribute.
Additional CSS class names to apply to the button.
All standard HTML button attributes are supported (disabled, title, aria-label, etc.).
Styling
The Button component uses the .excalidraw-button CSS class:
.excalidraw-button {
padding : 0.5 rem 1 rem ;
border : 1 px solid #e5e7eb ;
border-radius : 0.375 rem ;
background : white ;
cursor : pointer ;
font-family : inherit ;
font-size : 0.875 rem ;
transition : all 0.2 s ;
}
.excalidraw-button:hover {
background : #f9fafb ;
}
.excalidraw-button.selected {
background : #e0e7ff ;
border-color : #6965db ;
}
.excalidraw-button:disabled {
opacity : 0.5 ;
cursor : not-allowed ;
}
A specialized button component for icon-only buttons, commonly used in toolbars.
Basic Usage
Icon Button
Active Icon Button
Standalone Icon Button
import { ButtonIcon } from "@excalidraw/excalidraw" ;
import { TrashIcon } from "./icons" ;
function MyComponent () {
const handleDelete = ( event ) => {
console . log ( "Delete clicked" );
};
return (
< ButtonIcon
icon = { TrashIcon }
title = "Delete"
onClick = { handleDelete }
/>
);
}
Props
The icon element to display in the button.
Tooltip text shown on hover (also used for accessibility).
Callback function when the button is clicked. onClick : ( event : React . MouseEvent < HTMLButtonElement >) => void ;
Whether the button is in an active state (e.g., tool currently selected).
When true, applies standalone styling that may be better suited for isolated buttons outside of toolbars.
Additional CSS class names to apply.
Test identifier for automated testing (sets data-testid attribute).
Inline styles to apply to the button.
Complete Examples
Button Group
Icon Toolbar
Action Buttons in Sidebar
Custom Icon Button Component
import { Button } from "@excalidraw/excalidraw" ;
import { useState } from "react" ;
function AlignmentButtons () {
const [ alignment , setAlignment ] = useState ( "left" );
return (
< div style = { { display: "flex" , gap: "0.5rem" } } >
< Button
onSelect = { () => setAlignment ( "left" ) }
selected = { alignment === "left" }
>
Left
</ Button >
< Button
onSelect = { () => setAlignment ( "center" ) }
selected = { alignment === "center" }
>
Center
</ Button >
< Button
onSelect = { () => setAlignment ( "right" ) }
selected = { alignment === "right" }
>
Right
</ Button >
</ div >
);
}
Accessibility
Both button components follow accessibility best practices:
Native <button> element for proper keyboard navigation
Accepts aria-label for screen readers
Responds to Enter and Space keys
:focus styles for keyboard users
Uses title prop for tooltip and aria-label
Icon-only buttons always have descriptive titles
Active state is communicated visually and semantically
Supports keyboard navigation
Best Practices
{ /* Good: Has descriptive title */ }
< ButtonIcon
icon = { < TrashIcon /> }
title = "Delete selected elements"
onClick = { handleDelete }
/>
{ /* Good: Disabled state explained */ }
< Button
onSelect = { handleSave }
disabled = { ! hasChanges }
title = { ! hasChanges ? "No changes to save" : "Save changes" }
>
Save
</ Button >
{ /* Good: ARIA label for complex actions */ }
< Button
onSelect = { handleExport }
aria-label = "Export drawing as PNG image"
>
< DownloadIcon /> Export
</ Button >
Styling Patterns
< Button
onSelect = { handleAction }
className = "primary-button"
style = { {
backgroundColor: "#6965db" ,
color: "white" ,
border: "none" ,
fontWeight: 500 ,
} }
>
Primary Action
</ Button >
< Button
onSelect = { handleDelete }
className = "danger-button"
style = { {
backgroundColor: "#dc2626" ,
color: "white" ,
border: "none" ,
} }
>
Delete
</ Button >
< Button
onSelect = { handleCancel }
className = "ghost-button"
style = { {
background: "transparent" ,
border: "none" ,
color: "#6b7280" ,
} }
>
Cancel
</ Button >
< div style = { { position: "relative" } } >
< ButtonIcon
icon = { NotificationIcon }
title = "Notifications"
onClick = { openNotifications }
/>
{ notificationCount > 0 && (
< span style = { {
position: "absolute" ,
top: - 4 ,
right: - 4 ,
background: "#dc2626" ,
color: "white" ,
borderRadius: "50%" ,
width: 16 ,
height: 16 ,
fontSize: 10 ,
display: "flex" ,
alignItems: "center" ,
justifyContent: "center" ,
} } >
{ notificationCount }
</ span >
) }
</ div >
See Also