Skip to content

Dashboard Widgets: declarative actions in the widget schema - #80363

Merged
retrofox merged 16 commits into
trunkfrom
update/widget-actions
Jul 17, 2026
Merged

Dashboard Widgets: declarative actions in the widget schema#80363
retrofox merged 16 commits into
trunkfrom
update/widget-actions

Conversation

@retrofox

@retrofox retrofox commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What

Adds an optional actions field to the widget schema: a declarative list of the verbs a widget type exposes, such as navigating to a report or downloading a file.

Each WidgetAction carries id, label, href, and optional download / openInNewTab.

The only fulfillment today is a link: the widget declares the intent and a target, and the host renders it as an anchor and owns placement.

The dashboard surfaces the actions in a "More" (three-dots) menu in the widget toolbar. Because navigation and downloads are handled by the browser, the widget stays host-agnostic.

The field travels from widget.json to the client through the full pipeline (build manifest → PHP registry → REST → TypeScript merge), mirroring help.

Why

Widgets had no way to declare the verbs a user triggers.

How

  • Contract (@wordpress/widget-primitives)
    A WidgetAction type ({ id, label, href, download?, openInNewTab? }), plus actions? on WidgetTypeMetadata and WidgetModuleRecordOverrides, merged in useWidgetTypes.

  • Server pipeline (mirrors help at every layer)
    The build manifest (build.mjs toPhpActionsLiteral), WP_Widget_Type ($actions), registration with sanitization and label i18n, and the REST controller (exposure plus item schema).
    PHP coverage in the widget-modules controller test.

  • UI (@wordpress/widget-dashboard):
    A WidgetActions component rendering a three-dots IconButton that opens a Menu of Link items, mounted in the normal-mode toolbar.

  • Demo
    The hello-dolly widget declares two actions: a link to its plugin page and a lyrics download.

  • Docs:
    The widget-primitives README (WidgetAction), CHANGELOG, and the architecture doc (actions across the four pipeline stages).

The dashboard Storybook includes story exercises, actions, and help notes.

Testing

  1. Build the plugin so the widget manifest regenerates.
  2. Enable the gutenberg-dashboard-widgets experiment.
  3. Open the dashboard: the hello-dolly tile shows a three-dots menu in its toolbar.
image image
  1. Click "About Hello Dolly": it opens the plugin page in a new tab.
  2. Click "Download lyrics": it downloads hello-dolly-lyrics.txt.
Screen.Recording.2026-07-16.at.7.34.36.PM.mov
  1. Run the PHP test: vendor/bin/phpunit phpunit/experimental/class-wp-rest-widget-modules-controller-test.php.
  2. In Storybook, open the Widget Dashboard story: the goal-progress tile surfaces its actions in a "More" menu, and each tile carries a help note.
Screen.Recording.2026-07-16.at.7.24.28.PM.mov

You can take a look at the widget-module endpoint to see the actions property:

image

Follow-ups

  • Add a scope: 'local' | 'global' axis so a host can surface an action beyond the widget (for example, the dashboard command palette).
  • Add a callback fulfillment for client-generated downloads (a handler that produces the file), beyond the declarative link.
  • Add a steps fulfillment backed by the connection language.

retrofox added 8 commits July 16, 2026 15:55
Carry declared actions from widget.json to the client through the build manifest, the widget-modules REST endpoint, and the useWidgetTypes merge.
Render a widget type's declared actions as a More dropdown of links in the normal-mode toolbar.
Cover the actions field in the widget-primitives README and CHANGELOG, and across the four pipeline stages in the architecture doc.
Give the demo widget types help notes and a goal-progress actions example so the story exercises both surfaces.
@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: retrofox <retrofox@git.wordpress.org>
Co-authored-by: chihsuan <chihsuan@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Size Change: +11 B (0%)

Total Size: 7.73 MB

📦 View Changed
Filename Size Change
build/modules/widget-primitives/index.min.js 1.16 kB +11 B (+0.96%)

compressed-size-action

@github-actions

github-actions Bot commented Jul 16, 2026

Copy link
Copy Markdown

Flaky tests detected in b490d34.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/29564835163
📝 Reported issues:

@retrofox
retrofox requested review from chihsuan and simison July 16, 2026 18:33

@chihsuan chihsuan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! @retrofox Overall looks good.

One small issue: Would it make sense to include the actions trigger in the inline-controls reserve? The fit currently calculation reserves room for Settings, but not for the new Actions button.

Add a callback fulfillment for client-generated downloads (a handler that produces the file), beyond the declarative link.

Looking ahead to callbacks, just sharing a few thoughts for the callback follow-up based on reviewing the Premium Analytics CSV POC (Automattic/jetpack#50362, Automattic/jetpack#50569):

  • Some actions need live, per-widget state, such as the rows currently loaded in the widget.
  • Availability may change with feature flags, empty data, missing parameters, or error states.
  • Async actions need a loading state, duplicate-click prevention, and somewhere to surface failures.
  • Downloads may be generated locally or fetched from a server before being handed to the browser.
  • Static action metadata will need a clear way to connect with its runtime handler, likely through the action ID.
  • The full report page may use a different presentation from the compact widget action, while still sharing the same underlying behavior.

Nothing that needs to be addressed here. Just a few scenarios that hope it will be useful when shaping the follow-up.

@retrofox

Copy link
Copy Markdown
Contributor Author

One small issue: Would it make sense to include the actions trigger in the inline-controls reserve? The fit currently calculation reserves room for Settings, but not for the new Actions button.

yes yes, good call.

@retrofox

Copy link
Copy Markdown
Contributor Author

Nice work! @retrofox Overall looks good.

One small issue: Would it make sense to include the actions trigger in the inline-controls reserve? The fit currently calculation reserves room for Settings, but not for the new Actions button.

@chihsuan, we need to keep working on that. I suggest continuing with a follow-up thought. The issue is already in trunk and was not introduced by this PR. WDYT?

Add a callback fulfillment for client-generated downloads (a handler that produces the file), beyond the declarative link.

Looking ahead to callbacks, just sharing a few thoughts for the callback follow-up based on reviewing the Premium Analytics CSV POC (Automattic/jetpack#50362, Automattic/jetpack#50569):

👍

@retrofox

Copy link
Copy Markdown
Contributor Author

Issue #80398

@chihsuan chihsuan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to keep working on that. I suggest continuing with a follow-up thought. The issue is already in trunk and was not introduced by this PR. WDYT?

Sounds good! No further feedback from me. Thanks!

@retrofox
retrofox merged commit 9faa7de into trunk Jul 17, 2026
59 checks passed
@retrofox
retrofox deleted the update/widget-actions branch July 17, 2026 09:04
@github-actions github-actions Bot added this to the Gutenberg 23.7 milestone Jul 17, 2026
shail-mehta pushed a commit that referenced this pull request Jul 17, 2026
* add widget actions to schema and REST pipeline

Carry declared actions from widget.json to the client through the build manifest, the widget-modules REST endpoint, and the useWidgetTypes merge.

* add actions more menu to dashboard widget chrome

Render a widget type's declared actions as a More dropdown of links in the normal-mode toolbar.

* add actions to the hello-dolly widget

* docs: document widget actions

Cover the actions field in the widget-primitives README and CHANGELOG, and across the four pipeline stages in the architecture doc.

* improve jsdoc

* docs: add actions and help to the dashboard story

Give the demo widget types help notes and a goal-progress actions example so the story exercises both surfaces.

* docs: link the field types story from the README

* update: clarify hello-dolly action label

* docs: add WithActions story to widget-render

* docs: cover actions in the anatomy doc

* docs: add the Actions story page

* docs: drop the Storybook link from the README

* simplifies Actions story doc page

* docs: add changelog entries for widget actions
@retrofox retrofox mentioned this pull request Jul 21, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants