Skip to content

Add Strapi Widgets API Documentation and Configuration #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions dev-docs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"aiProvider": "aws"
}
80 changes: 77 additions & 3 deletions docusaurus/docs/cms/admin-panel-customization/extension.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ displayed_sidebar: cmsSidebar
sidebar_label: Extension
toc_max_heading_level: 4
tags:
- admin panel
- admin panel customization

- admin panel
- admin panel customization
---

import HotReloading from '/docs/snippets/hot-reloading-admin-panel.md'
Expand All @@ -28,6 +27,81 @@ There are 2 use cases where you might want to extend the admin panel:

👉 This can be done by directly updating the `/src/admin/app.[tsx|js]` file, which can import any file located in `/src/admin/extensions`.

## Widgets API

The Widgets API allows you to create custom widgets that can be displayed in the admin panel dashboard. Widgets are React components that appear on the dashboard and can provide valuable information or functionality specific to your application.

### Registering a widget

To register a widget, use the `register` method from the Widgets class. Each widget requires specific properties:

```typescript
// Example widget registration
strapi.admin.widgets.register({
// Unique identifier for this widget
id: 'my-custom-widget',
// The icon displayed with the widget
icon: MyCustomIcon,
// The title displayed for the widget
title: { id: 'my-custom-widget.title', defaultMessage: 'My Custom Widget' },
// Optional link to provide additional actions
link: {
label: { id: 'my-custom-widget.link', defaultMessage: 'Learn more' },
href: '/some-path',
},
// The React component to render (lazy loaded)
component: () => import('./components/MyCustomWidget'),
// Optional permissions to restrict who can see this widget
permissions: [
{ action: 'plugin::content-manager.explorer.read', subject: 'api::article.article' }
],
});
```

You can also register multiple widgets at once by passing an array:

```typescript
strapi.admin.widgets.register([
{
id: 'widget-1',
// ...other properties
},
{
id: 'widget-2',
// ...other properties
}
]);
```

### Widget properties

Each widget must have the following properties:

| Property | Type | Description |
|----------|------|-------------|
| `id` | `string` | A unique identifier for the widget |
| `icon` | `React.ComponentType` | The icon component to display with the widget |
| `title` | `MessageDescriptor` | The title of the widget (internationalized) |
| `component` | `() => Promise<{ default: React.ComponentType }>` | The React component to render (lazy loaded) |
| `link` | `{ label: MessageDescriptor, href: To }` | Optional link providing additional context or actions |
| `permissions` | `Permission[]` | Optional array of permissions to restrict widget visibility |
| `pluginId` | `string` | Optional plugin identifier when the widget is provided by a plugin |

### Widget UIDs

When registering a widget, it's assigned a unique identifier (UID) based on its source:

- For widgets from plugins: `plugin::{pluginId}.{id}`
- For global widgets: `global::{id}`

### Retrieving registered widgets

To get all registered widgets, use the `getAll` method:

```typescript
const allWidgets = strapi.admin.widgets.getAll();
```

:::strapi Additional resources
* If you're searching for ways of replacing the default WYSIWYG editor, please refer to the [corresponding page](/cms/admin-panel-customization/wysiwyg-editor).
* The <ExternalLink to="https://design-system.strapi.io/?path=/docs/getting-started-welcome--docs" text="Strapi Design System documentation"/> will also provide additional information on developing for Strapi's admin panel.
Expand Down
184 changes: 184 additions & 0 deletions docusaurus/docs/cms/admin-panel-customization/widgets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
---
title: Widgets API
description: Learn how to use the Widgets API to extend Strapi's admin panel with custom widgets.
displayed_sidebar: cmsSidebar
sidebar_label: Widgets
toc_max_heading_level: 4
tags:
- admin panel
- admin panel customization
- widgets
---

# Widgets API

Strapi's Widgets API allows you to extend the admin panel with custom widgets. Widgets are modular components that can be registered and displayed in specific areas of the admin interface.

## Introduction

Widgets are reusable UI components that can be added to the admin panel. They provide a way to extend the functionality of the admin panel without modifying its core code. Widgets can be used to display various types of information, provide shortcuts to frequently used functions, or integrate with external services.

You can register widgets in two ways:
- As a plugin developer, you can register widgets that will be available whenever your plugin is installed
- As a Strapi developer, you can register widgets for a specific instance of a Strapi application

## API Reference

### Registering Widgets

The Widgets API provides methods to register one or more widgets:

```typescript
// Register a single widget
strapi.admin.widgets.register({
id: 'my-widget',
component: () => import('./components/MyWidget'),
title: { id: 'myWidget.title', defaultMessage: 'My Widget' },
icon: IconComponent,
});

// Register multiple widgets
strapi.admin.widgets.register([
{
id: 'first-widget',
component: () => import('./components/FirstWidget'),
title: { id: 'firstWidget.title', defaultMessage: 'First Widget' },
icon: FirstIconComponent,
},
{
id: 'second-widget',
component: () => import('./components/SecondWidget'),
title: { id: 'secondWidget.title', defaultMessage: 'Second Widget' },
icon: SecondIconComponent,
}
]);
```

### Getting All Registered Widgets

You can retrieve all registered widgets using the `getAll` method:

```typescript
const widgets = strapi.admin.widgets.getAll();
```

## Widget Properties

When registering a widget, you need to provide several properties:

### Required Properties

| Property | Type | Description |
|----------|------|-------------|
| `id` | `string` | A unique identifier for the widget |
| `component` | `() => Promise<{ default: React.ComponentType }>` | A function that returns a promise resolving to the widget component |
| `title` | `MessageDescriptor` | The title of the widget (supports internationalization) |
| `icon` | `React.ComponentType` | The icon component to display with the widget |

### Optional Properties

| Property | Type | Description |
|----------|------|-------------|
| `link` | `{ label: MessageDescriptor; href: To }` | A link to include in the widget |
| `pluginId` | `string` | The ID of the plugin registering the widget |
| `permissions` | `Permission[]` | Permissions required to view the widget |

## Usage Examples

### Basic Widget Registration

```typescript
import { CheckCircle } from '@strapi/icons';

// In your plugin's admin/src/index.js or in src/admin/app.js
export default {
register(app) {
app.widgets.register({
id: 'dashboard-welcome',
component: () => import('./components/DashboardWelcome'),
title: {
id: 'dashboard.welcome.title',
defaultMessage: 'Welcome to your dashboard',
},
icon: CheckCircle,
});
},
};
```

### Widget with a Link and Permissions

```typescript
import { Heart } from '@strapi/icons';

export default {
register(app) {
app.widgets.register({
id: 'content-metrics',
component: () => import('./components/ContentMetrics'),
title: {
id: 'metrics.content.title',
defaultMessage: 'Content Metrics',
},
icon: Heart,
link: {
label: {
id: 'metrics.content.link',
defaultMessage: 'View all metrics',
},
href: '/metrics',
},
permissions: [
{ action: 'plugin::content-manager.read', subject: 'metrics' },
],
});
},
};
```

### Plugin-specific Widget

When registering a widget from a plugin, include the `pluginId` to properly namespace the widget:

```typescript
export default {
register(app) {
app.widgets.register({
id: 'analytics-summary',
pluginId: 'my-analytics-plugin',
component: () => import('./components/AnalyticsSummary'),
title: {
id: 'analytics.summary.title',
defaultMessage: 'Analytics Summary',
},
icon: () => null,
});
},
};
```

## Widget UID

When widgets are registered, they are assigned a unique identifier (UID) based on their `id` and optional `pluginId`:

- For global widgets: `global::{id}`
- For plugin widgets: `plugin::{pluginId}.{id}`

This UID is used internally to track and manage registered widgets.

```doc.dev
Need more information about where/how widgets are displayed in the admin panel UI.
The code reveals the registration mechanism but not how these widgets are rendered or where they appear in the interface.
Additional details about any widget-specific styling or layout considerations would also be helpful.
```

## Error Handling

The Widgets API will throw errors if any required properties are missing when registering a widget:

- If `id` is missing: "An id must be provided"
- If `component` is missing: "A component must be provided"
- If `title` is missing: "A title must be provided"
- If `icon` is missing: "An icon must be provided"

Ensure all required properties are provided to avoid runtime errors.