UI extensions
This page describes the UI extensions API in detail.
Extension points in Grafana
A list of available extension points within Grafana that can be extended by plugins. All these extension point IDs can be accessed using the PluginExtensionPoints
enum exposed by the @grafana/data
package.
import { PluginExtensionPoints } from '@grafana/data';
const extensionPointId = PluginExtensionPoints.DashboardPanelMenu;
Extension Point ID | Type | Description |
---|---|---|
AlertingAlertingRuleAction | Link | Extend the alert rule menu with custom actions for alerting rules. |
AlertingHomePage | Component | Extend the alerting home page with custom alert-creation experience. |
AlertingRecordingRuleAction | Link | Extend the alert rule menu with custom actions for recording rules. |
AlertInstanceAction | Link | Extend the alert instances table with custom actions. |
CommandPalette | Link | Extend the command palette with custom actions. |
DashboardPanelMenu | Link | Extend the panel menu with custom actions. |
ExploreToolbarAction | Link | Extend the "Add" button on the Explore page with custom actions. |
UserProfileTab | Component | Extend the user profile page with custom tabs. |
Methods
addComponent
Available in Grafana >=v11.1.0.
This method can be used to register a React component to a certain extension point to contribute a new ui experience.
export const plugin = new AppPlugin<{}>().addComponent({
targets: ['grafana/user/profile/tab/v1'],
title: 'New user profile tab',
description: 'A new tab that shows extended user profile information',
component: () => {
return <div>Hello World!</div>;
},
});
Parameters
The addComponent()
method takes a single config
object with the following properties:
Property | Description |
---|---|
targets | A list of extension point IDs where the extension will be registered. Example: "grafana/dashboard/panel/menu/v1" . See available extension points in Grafana → |
title | A human readable title for the component. |
description | A human readable description for the component. |
component | The React component that will be rendered by the extension point. Note: the props passed to the component are defined by each extension point. |
Return value
The method returns the AppPlugin
instance to allow for chaining.
Examples
- Accessing plugin meta-data in the component
- Access your plugin's state inside the component
- Hide a component in certain conditions
See also
addLink
Available in Grafana >=v11.1.0.
This method can be used to register a link extension to a certain extension point. Link extensions are used to navigate to different parts of the Grafana UI or other plugins, and can include modal elements declared via an onClick.
export const plugin = new AppPlugin<{}>().addLink({
targets: ['grafana/dashboard/panel/menu/v1'],
title: 'Declare incident',
description: 'Declare an incident and attach the panel context to it',
path: '/a/myorg-incidents-app/incidents',
});
Parameters
The addLink()
method takes a single config
object with the following properties:
Property | Description | Required |
---|---|---|
targets | A list of extension point IDs where the extension will be registered. Example: "grafana/dashboard/panel/menu/v1" . See available extension points in Grafana → | true |
title | A human readable title for the link. | true |
description | A human readable description for the link. | true |
path? | A path within your app plugin where you would like to send users when they click the link. (Use either path or onClick .) Example: "/a/myorg-incidents-app/incidents" | true |
onClick? | A callback that should be triggered when the user clicks the link. (Use either path or onClick .) | false |
category? | A category that should be used to group your link with other links. | false |
icon? | An icon that should be used while displaying your link. Example: "edit" or "bookmark" . See all available icon names → | false |
configure? | A function that is called prior to displaying the link which enables you to dynamically change or hide your link depending on its context . | false |
Return value
The method returns the AppPlugin
instance to allow for chaining.
Examples
- Hide a link in certain conditions
- Update the path based on the context
- Open a modal from the
onClick()
exposeComponent
Available in Grafana >=v11.1.0.
This method exposes a React component and makes it available for other plugins to use. Other plugins can render the component within their app by calling usePluginComponent() and referencing the id
of the exposed component.
export const plugin = new AppPlugin<{}>()
.exposeComponent({
id: "myorg-incidents-app/create-incident-form/v1",],
title: "Create incident form",
description: "A form to create a new incident.",
component: () => {
return <div>Hello World!</div>;
},
});
Parameters
The exposeComponent()
method takes a single config
object with the following properties:
Property | Description |
---|---|
id | A unique string identifier of the component you are exposing. It must be prefixed with your plugin ID. Example: "myorg-incidents-app/create-incident-form/v1" . |
title | A human readable title for the component. |
description | A human readable description for the component. |
component | A React component that you are exposing. Make sure to wrap it with the necessary React context providers that the component is relying on, as this component is not going to be rendered under the same React tree as your plugin. |
Return value
The method returns the AppPlugin
instance to allow for chaining.
Examples
See also
getPluginExtensions
⚠️
This function can be used to fetch extensions (both links and components) that are registered to a certain extension point.
This function is deprecated and will be removed in Grafana v12.
Please use either the usePluginLinks()
or usePluginComponents()
hooks instead.
import { getPluginExtensions } from '@grafana/runtime';
const { extensions } = getPluginExtensions({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
Parameters
The getPluginExtensions()
function takes a single options
object with the following properties:
Property | Description | Required |
---|---|---|
extensionPointId | A unique id to fetch link extensions for. In case you are implementing a new extension point, this is what plugins reference when registering extensions. Plugins must prefix this with their plugin id, while core Grafana extensions points have to use a "grafana/" prefix. Example: "grafana/dashboard/panel/menu/v1" | true |
context? | An arbitrary object that you would like to share with the extensions. This can be used to pass data to the extensions. | false |
limitPerPlugin? | - The maximum number of extensions to return per plugin. Default is no limit. | false |
Return value
The hook returns the following object:
const {
// An empty array if no plugins have registered extensions for this extension point yet
extensions: PluginExtension[];
} = getPluginExtensions(options);
For more information, see PluginExtension
.
Hooks
usePluginComponent
Available in Grafana >=v11.1.0.
This react hook can be used to fetch a single react component that was exposed by a plugin with a unique ID. Plugins can expose components using the AppPlugin.exposeComponent()
method.
import { usePluginComponent } from '@grafana/runtime';
const { component: Component, isLoading } = usePluginComponent('myorg-incidents-app/create-incident-form/v1');
Parameters
id
- A unique id that identifies the component.
Return value
The hook returns the following object:
const {
// The react component that was exposed by the plugin
// (`null` if no component is exposed with that id)
component: React.ComponentType<Props> | undefined | null;
// `true` until the plugin exposing the component is still loading
isLoading: boolean;
} = usePluginComponent(id);
Examples
usePluginComponents
Available in Grafana >=v11.1.0.
This react hook can be used to fetch components that are registered to a certain extension point. Component extensions can be used to render custom UI components. Plugins can register components using the AppPlugin.addComponent()
method.
import { usePluginComponents } from '@grafana/runtime';
const { components, isLoading } = usePluginComponents({
extensionPointId: 'grafana/user/profile/tab/v1',
limitPerPlugin: 1,
});
Parameters
The .usePluginComponents()
method takes a single options
object with the following properties:
Property | Description | Required |
---|---|---|
extensionPointId | A unique id to fetch link extensions for. In case you are implementing a new extension point, this is what plugins reference when registering extensions. Plugins must prefix this with their plugin id, while core Grafana extensions points have to use a "grafana/" prefix. Example: "grafana/user/profile/tab/v1" | true |
limitPerPlugin? | - The maximum number of extensions to return per plugin. Default is no limit. | False |
Return value
The hook returns the following object (for more info check PluginExtensionComponent
:
const {
// An empty array if no plugins have registered extensions for this extension point yet
components: PluginExtensionComponent[];
// `true` until any plugins extending this extension point
// are still loading
isLoading: boolean;
} = usePluginComponents(options);
Examples
- Pass data to the components using props
- Limit which plugins can register components to your extension point
See also
usePluginLinks
Available in Grafana >=v11.1.0.
This react hook can be used to fetch links that are registered to a certain extension point. Plugins can register links using the AppPlugin.addLink()
method.
import { usePluginLinks } from '@grafana/runtime';
const { links, isLoading } = usePluginLinks({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
Parameters
The .usePluginLinks()
method takes a single options
object with the following properties:
Property | Description | Required |
---|---|---|
extensionPointId | A unique id to fetch link extensions for. In case you are implementing a new extension point, this is what plugins reference when registering extensions. Plugins must prefix this with their plugin id, while core Grafana extensions points have to use a "grafana/" prefix. Example: "grafana/dashboard/panel/menu/v1" | true |
context? | An arbitrary object that you would like to share with the extensions. This can be used to pass data to the extensions. | false |
limitPerPlugin? | The maximum number of extensions to return per plugin. Default is no limit. | false |
Return value
The hook returns the following object (for more info check PluginExtensionLink
):
const {
// An empty array if no plugins have registered extensions for this extension point yet
links: PluginExtensionLink[];
// `true` until any plugins extending this extension point
// are still loading
isLoading: boolean;
} = usePluginLinks(options);
Examples
- Pass data to the links
- Limit the number of links by plugins
- Limit which plugins can register links to your extension point
See also
usePluginExtensions
⚠️
This react hook can be used to fetch extensions (both links and components) that are registered to a certain extension point.
This hook is deprecated and will be removed in Grafana v12.
Please use either the usePluginLinks()
or usePluginComponents()
hooks instead.
import { usePluginExtensions } from '@grafana/runtime';
const { extensions, isLoading } = usePluginExtensions({
extensionPointId: 'grafana/dashboard/panel/menu/v1',
limitPerPlugin: 2,
context: {
panelId: '...',
},
});
Parameters
The .usePluginExtensions()
method takes a single options
object with the following properties:
Property | Description | Required |
---|---|---|
extensionPointId | A unique id to fetch link extensions for. In case you are implementing a new extension point, this is what plugins reference when registering extensions. Plugins must prefix this with their plugin id, while core Grafana extensions points have to use a "grafana/" prefix. Example: "grafana/dashboard/panel/menu/v1" | true |
context? | An arbitrary object that you would like to share with the extensions. This can be used to pass data to the extensions. | false |
limitPerPlugin? | The maximum number of extensions to return per plugin. Default is no limit. | false |
Return value
The hook returns the following object:
const {
// An empty array if no plugins have registered extensions for this extension point yet
extensions: PluginExtension[];
// `true` until any plugins extending this extension point
// are still loading
isLoading: boolean;
} = usePluginExtensions(options);
For more information, see PluginExtension
.