Skip to main content
Version: 2026.1

Widget Manager

The Widget Manager controls the layout of widgets in Pimcore Studio. It provides functionality to open, close, and manipulate widgets programmatically from custom components.

Opening a Widget

Use the useWidgetManager hook to open a widget programmatically:

import { Button } from 'antd'
import { useWidgetManager } from '@pimcore/studio-ui-bundle/modules/widget-manager'

export const MyFirstTabComponent = (): React.JSX.Element => {
const widgetManager = useWidgetManager()

function onClick(): void {
widgetManager.openBottomWidget({
name: 'My first widget',
component: 'my-first-widget',
})
}

return (
<div>
<h1>My First Tab</h1>
<p>This is a simple tab component.</p>
<Button type="primary" onClick={onClick}>Open my first widget</Button>
</div>
)
}

useWidgetManager Hook

The hook returns the following methods:

MethodSignatureDescription
openMainWidget(tabConfig: WidgetManagerTabConfig) => voidOpens a widget in the main content area
openBottomWidget(tabConfig: WidgetManagerTabConfig) => voidOpens a widget in the bottom panel
openLeftWidget(tabConfig: WidgetManagerTabConfig) => voidOpens a widget in the left sidebar
openRightWidget(tabConfig: WidgetManagerTabConfig) => voidOpens a widget in the right sidebar
updateWidget(tabConfig: WidgetManagerTabConfig) => voidUpdates an existing widget's configuration
switchToWidget(id: string) => voidActivates/focuses a widget by ID
closeWidget(id: string) => voidCloses a widget by ID
isMainWidgetOpen(id: string) => booleanChecks if a widget is open in the main area
hasOuterWidget(id: string) => booleanChecks if a widget exists in the outer layout (sidebars/bottom)
getOpenedMainWidget() => TabNode | undefinedReturns the currently active main widget node

Transform Configuration

Use transformConfig to dynamically modify widget configuration when widgets are created:

widgetRegistry.registerWidget({
name: 'my-widget',
component: MyWidgetComponent,
transformConfig: (config) => ({
...config,
translationKey: `widgets.${config.name}`
})
})

Title Components

Customize both the tab/button titles and widget content headers using specialized title components.

titleComponent - Tab/Button Titles

Controls the title displayed in tabs or sidebar buttons. Use TabTitleContainer for full functionality with auto-detection:

import {
TabTitleContainer,
type TabTitleContainerProps
} from '@pimcore/studio-ui-bundle/modules/widget-manager'

const MyCustomTitle = ({ node, modified }: TabTitleContainerProps) => {
const config = node.getConfig()
const customTitle = `${config.elementType || 'Widget'}`

return <TabTitleContainer node={node} modified={modified} title={customTitle} />
}

widgetRegistry.registerWidget({
name: 'my-widget',
component: MyWidgetComponent,
titleComponent: MyCustomTitle
})

contentTitleComponent - Widget Content Headers

Controls the header inside the widget content area. Use WidgetContentTitleView for styled headers:

import {
WidgetContentTitleView,
type WidgetContentTitleViewProps
} from '@pimcore/studio-ui-bundle/modules/widget-manager'

const MyContentTitle = ({ node, icon, title }: WidgetContentTitleViewProps) => {
const customTitle = `Dashboard: ${title}`

return (
<WidgetContentTitleView
node={node}
icon={icon}
title={customTitle}
/>
)
}

widgetRegistry.registerWidget({
name: 'my-widget',
component: MyWidgetComponent,
contentTitleComponent: MyContentTitle
})

Custom Conditional Logic

For advanced use cases with different behavior for sidebar buttons vs tabs, use BorderTitleView and TabTitleView directly. Widgets appear as border buttons in sidebars and as tabs in the main content area:

import { BorderNode } from 'flexlayout-react'
import {
BorderTitleView,
TabTitleView,
type TabTitleContainerProps,
useWidgetManager
} from '@pimcore/studio-ui-bundle/modules/widget-manager'

const MyAdvancedTitle = ({ node, modified }: TabTitleContainerProps) => {
const { closeWidget } = useWidgetManager()
const config = node.getConfig()
const isBorderNode = node.getParent() instanceof BorderNode
const icon = config.icon ?? { value: 'widget-default', type: 'name' }
const title = `Custom ${config.elementType ?? 'Widget'}`

const onClose = () => closeWidget(node.getId())

if (isBorderNode) {
return (
<BorderTitleView
icon={icon}
title={title}
/>
)
}

return (
<TabTitleView
icon={icon}
title={title + (modified ? ' *' : '')}
onClose={node.isEnableClose() ? onClose : undefined}
onConfirm={modified ? onClose : undefined}
/>
)
}

widgetRegistry.registerWidget({
name: 'my-advanced-widget',
component: MyWidgetComponent,
titleComponent: MyAdvancedTitle
})

Available Title Components

ComponentImport fromPurpose
TabTitleContainer@pimcore/studio-ui-bundle/modules/widget-managerFull-featured with auto-detection, close buttons, modified state
BorderTitleView@pimcore/studio-ui-bundle/modules/widget-managerSidebar button style only
TabTitleView@pimcore/studio-ui-bundle/modules/widget-managerTab style only
WidgetContentTitleView@pimcore/studio-ui-bundle/modules/widget-managerContent header without translation

Step-by-Step Guide

For a step-by-step guide on adding a widget, refer to the Widget Manager example.

Source