docs/docs/guides/extending-the-dashboard/customizing-pages/action-bar-items.mdx
The Action Bar is the bar at the top of the page where you can add buttons and other actions.
:::info All available options are documented in the DashboardActionBarItem reference :::
Here's a simple example of adding a button to the action bar:
import { Button, defineDashboardExtension } from '@vendure/dashboard';
import { useState } from 'react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-detail',
component: ({ context }) => {
const [count, setCount] = useState(0);
return (
<Button type="button" variant="secondary" onClick={() => setCount(x => x + 1)}>
Counter: {count}
</Button>
);
},
},
],
});
The pageId property is required in order to specify on which page the action bar item should appear.
By default, the item will be placed to the left of any existing action bar items.
However, since Vendure v3.6.0, you can also specify the position property for more control over the placement of your action bar item.
See the section on finding page and item ids below for help in determining the correct pageId and itemId values.
import { Button, defineDashboardExtension } from '@vendure/dashboard';
import { useState } from 'react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-detail',
component: ({ context }) => {
// omitted for brevity
},
// highlight-start
position: {
// The ID of the existing action bar item to position relative to
itemId: 'save-button',
// Order can be 'before', 'after' or 'replace'
order: 'after',
},
// highlight-end
},
],
});
The context prop provides access to:
entity: The current entity being viewed/edited (e.g., Product, Customer, etc.)form: The React Hook Form instance for the current page (if applicable)route: Route information and parametersYou can also define dropdown menu items for the Action Bar. This is useful for secondary actions that are needed less often by administrators.
Make sure to always wrap these in the DropdownMenuItem component for consistent styling.
import { DropdownMenuItem, defineDashboardExtension } from '@vendure/dashboard';
import { useState } from 'react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-list',
type: 'dropdown',
component: () => <DropdownMenuItem variant="default">My Item</DropdownMenuItem>,
},
],
});
import { Button, defineDashboardExtension } from '@vendure/dashboard';
import { DownloadIcon } from 'lucide-react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-detail',
component: ({ context }) => {
const product = context.entity;
const handleExport = async () => {
// Export product data
const data = JSON.stringify(product, null, 2);
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `product-${product.id}.json`;
a.click();
URL.revokeObjectURL(url);
};
return (
<Button variant="outline" onClick={handleExport} disabled={!product}>
<DownloadIcon className="mr-2 h-4 w-4" />
Export
</Button>
);
},
},
],
});
import { Button, defineDashboardExtension, toast } from '@vendure/dashboard';
import { RefreshCwIcon } from 'lucide-react';
import { useState } from 'react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-detail',
component: ({ context }) => {
const [isSyncing, setIsSyncing] = useState(false);
const product = context.entity;
const handleSync = async () => {
if (!product) return;
setIsSyncing(true);
try {
// Simulate API call to external system
await fetch(`/api/sync-product/${product.id}`, {
method: 'POST',
});
toast.success('Product synced successfully');
} catch (error) {
toast.error('Failed to sync product');
} finally {
setIsSyncing(false);
}
};
return (
<Button variant="outline" onClick={handleSync} disabled={!product || isSyncing}>
<RefreshCwIcon className={`mr-2 h-4 w-4 ${isSyncing ? 'animate-spin' : ''}`} />
{isSyncing ? 'Syncing...' : 'Sync to ERP'}
</Button>
);
},
},
],
});
You can conditionally show action bar items based on the entity or user permissions:
import { Button, defineDashboardExtension, PermissionGuard } from '@vendure/dashboard';
import { SendIcon } from 'lucide-react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'customer-detail',
component: ({ context }) => {
const customer = context.entity;
// Only show for customers with email addresses
if (!customer?.emailAddress) {
return null;
}
const handleSendEmail = () => {
// Open email composer or trigger email send
console.log('Sending email to:', customer.emailAddress);
};
return (
<PermissionGuard requires={['UpdateCustomer']}>
<Button variant="outline" onClick={handleSendEmail}>
<SendIcon className="mr-2 h-4 w-4" />
Send Email
</Button>
</PermissionGuard>
);
},
},
],
});
You can add multiple action bar items to the same page:
import { Button, defineDashboardExtension } from '@vendure/dashboard';
import { DownloadIcon, RefreshCwIcon, SendIcon } from 'lucide-react';
defineDashboardExtension({
actionBarItems: [
{
pageId: 'product-detail',
component: ({ context }) => (
<Button variant="outline">
<DownloadIcon className="mr-2 h-4 w-4" />
Export
</Button>
),
},
{
pageId: 'product-detail',
component: ({ context }) => (
<Button variant="outline">
<RefreshCwIcon className="mr-2 h-4 w-4" />
Sync
</Button>
),
},
{
pageId: 'product-detail',
component: ({ context }) => (
<Button variant="outline">
<SendIcon className="mr-2 h-4 w-4" />
Share
</Button>
),
},
],
});
The dashboard provides several button variants you can use:
default - Primary button stylesecondary - Secondary button styleoutline - Outlined button styleghost - Minimal button styledestructive - For destructive actions (delete, etc.)<Button variant="default">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
PermissionGuard for actions that require specific permissionsTo find the pageId and itemId for your action bar items:
The Extension Targets reference lists the most common built-in page IDs, block IDs, action bar item IDs, and toolbar item IDs.