Skip to content

Conversation

@ntsekouras
Copy link
Contributor

@ntsekouras ntsekouras commented Oct 29, 2025

What?

An exploration related to: #65186 and #70714.

I spent some time exploring the above issues that are about adding some semantic info in media blocks that could potentially normalize some behaviors across blocks, that right now have very specific handling per block.

I didn't want to spend much time for it and start some discussions about whether such an API could be valuable and worths the effort.

Initially the obvious use cases for me that can use this, are the cases handled in this POC:

  1. List view images. With this approach we can detect images from more blocks besides the already hardcoded ones. You can see in the small video below for example that we can show images that are children of Group or more images in Cover, if they have more images nested. Is this something we would want though design wise? 🤔 This opens of course the opportunity to show images from 3rd party blocks too.
  2. We can support uploading external images in post publish panel even from 3rd party blocks that use the API.

Possible use cases without exploring them

  1. Integrate with media inserter for handling preview and probably insert different blocks than the default ones (Image, Video and Audio blocks`.
  2. Could this be useful in some way to pattern content only editing? --cc @ramonjd
  3. Could this be helpful in block transforms in any way
  4. Could this be helpful in drag and drop functionality? We have for example some logic for detecting image blocks in useOnBlockDrop to create a gallery with core/image hardcoded checks.

Current suggestion rationale and alternatives

Media blocks would need to identify at least these roles: url, id(persisted data), alt(for images) and type(image|video|audio). type is an important part because different media types have different tags and handling.

Approaches that I considered

  1. At first I considered using the existing role prop of block attributes, but many of them already have the content role applied. We could consider media roles as content, but not being explicit can lead to bugs and unwanted behaviors. Another alternative is to make role also accept and array of roles (ex ['content', 'mediaId']). It's doable but didn't chose this for start because it feels to me right now that content has been overused for content only editing and might entangle things more. That is a concern I already have and it's worth discussing on its own, although I don't have a clear way forward to solve this.. Another main obstacle for this approach or even having a new prop in block attributes like mediaRole is that block need to define their type media role but don't have such an attribute. Adding a new attribute in blocks just for this doesn't seem like a good approach.
  2. I considered using a block supports but it didn't seem a good approach for the above point of adding more attributes in a block without any good reason.

Current suggestion

I ended up trying this with a new top level mediaRoles prop in block config. I'm not sure about the name either since this prop is a map of the media roles to each block's related attributes. This solves the type media role for blocks without adding any new attributes.

Questions

  1. Would an API like this (with any approach and not necessarily the suggested one) make sense to introduce? TBH I'm still not sure, unless we validate a bit more use cases or we deem that the already implemented two ones provide enough value.
  2. Since such an API is about adding semantic info in some block attributes we should consider if and how could we scale in the future. What other cases of block attributes would benefit from a more specific role?

--cc @WordPress/gutenberg-core @youknowriad @mcsf @Mamaduka @mtias

Screenshots

List view

Screen.Recording.2025-10-30.at.8.20.49.AM.mov

@ntsekouras ntsekouras self-assigned this Oct 29, 2025
@ntsekouras ntsekouras added [Type] Enhancement A suggestion for improvement. [Feature] Block API API that allows to express the block paradigm. labels Oct 29, 2025
@github-actions
Copy link

Size Change: +132 B (+0.01%)

Total Size: 2.37 MB

Filename Size Change
build/scripts/block-editor/index.min.js 295 kB -16 B (-0.01%)
build/scripts/block-library/index.min.js 267 kB +131 B (+0.05%)
build/scripts/blocks/index.min.js 56.3 kB +86 B (+0.15%)
build/scripts/edit-site/index.min.js 228 kB -69 B (-0.03%)
ℹ️ View Unchanged
Filename Size
build/modules/a11y/index.min.js 355 B
build/modules/block-editor/utils/fit-text-frontend.min.js 550 B
build/modules/block-library/accordion/view.min.js 520 B
build/modules/block-library/file/view.min.js 346 B
build/modules/block-library/form/view.min.js 528 B
build/modules/block-library/image/view.min.js 1.66 kB
build/modules/block-library/navigation/view.min.js 1.03 kB
build/modules/block-library/query/view.min.js 518 B
build/modules/block-library/search/view.min.js 498 B
build/modules/interactivity-router/full-page.min.js 451 B
build/modules/interactivity-router/index.min.js 11.6 kB
build/modules/interactivity/index.min.js 14.9 kB
build/modules/latex-to-mathml/index.min.js 56.5 kB
build/modules/latex-to-mathml/loader.min.js 131 B
build/scripts/a11y/index.min.js 1.06 kB
build/scripts/annotations/index.min.js 2.38 kB
build/scripts/api-fetch/index.min.js 2.83 kB
build/scripts/autop/index.min.js 2.18 kB
build/scripts/blob/index.min.js 631 B
build/scripts/block-directory/index.min.js 8.04 kB
build/scripts/block-serialization-default-parser/index.min.js 1.16 kB
build/scripts/block-serialization-spec-parser/index.min.js 3.08 kB
build/scripts/commands/index.min.js 17.4 kB
build/scripts/components/index.min.js 271 kB
build/scripts/compose/index.min.js 13.8 kB
build/scripts/core-commands/index.min.js 4.13 kB
build/scripts/core-data/index.min.js 85.7 kB
build/scripts/customize-widgets/index.min.js 12.3 kB
build/scripts/data-controls/index.min.js 793 B
build/scripts/data/index.min.js 9.61 kB
build/scripts/date/index.min.js 23.6 kB
build/scripts/deprecated/index.min.js 755 B
build/scripts/dom-ready/index.min.js 476 B
build/scripts/dom/index.min.js 4.91 kB
build/scripts/edit-post/index.min.js 16.8 kB
build/scripts/edit-widgets/index.min.js 20 kB
build/scripts/editor/index.min.js 282 kB
build/scripts/element/index.min.js 5.19 kB
build/scripts/escape-html/index.min.js 586 B
build/scripts/format-library/index.min.js 10.6 kB
build/scripts/hooks/index.min.js 1.83 kB
build/scripts/html-entities/index.min.js 494 B
build/scripts/i18n/index.min.js 2.46 kB
build/scripts/is-shallow-equal/index.min.js 568 B
build/scripts/keyboard-shortcuts/index.min.js 1.57 kB
build/scripts/keycodes/index.min.js 1.53 kB
build/scripts/latex-to-mathml/index.min.js 56.7 kB
build/scripts/list-reusable-blocks/index.min.js 2.44 kB
build/scripts/media-utils/index.min.js 64.5 kB
build/scripts/notices/index.min.js 1.11 kB
build/scripts/nux/index.min.js 1.88 kB
build/scripts/patterns/index.min.js 8.62 kB
build/scripts/plugins/index.min.js 2.14 kB
build/scripts/preferences-persistence/index.min.js 2.15 kB
build/scripts/preferences/index.min.js 3.31 kB
build/scripts/primitives/index.min.js 1.01 kB
build/scripts/priority-queue/index.min.js 1.61 kB
build/scripts/private-apis/index.min.js 1.05 kB
build/scripts/react-i18n/index.min.js 832 B
build/scripts/react-refresh-entry/index.min.js 9.44 kB
build/scripts/react-refresh-runtime/index.min.js 3.59 kB
build/scripts/redux-routine/index.min.js 3.36 kB
build/scripts/reusable-blocks/index.min.js 2.92 kB
build/scripts/rich-text/index.min.js 12.9 kB
build/scripts/router/index.min.js 5.96 kB
build/scripts/server-side-render/index.min.js 1.9 kB
build/scripts/shortcode/index.min.js 1.58 kB
build/scripts/style-engine/index.min.js 2.31 kB
build/scripts/theme/index.min.js 28.4 kB
build/scripts/token-list/index.min.js 740 B
build/scripts/undo-manager/index.min.js 915 B
build/scripts/url/index.min.js 3.98 kB
build/scripts/vendors/react-dom.min.js 43 kB
build/scripts/vendors/react-jsx-runtime.min.js 691 B
build/scripts/vendors/react.min.js 4.27 kB
build/scripts/viewport/index.min.js 1.22 kB
build/scripts/warning/index.min.js 454 B
build/scripts/widgets/index.min.js 7.83 kB
build/scripts/wordcount/index.min.js 1.04 kB
build/styles/block-directory/style-rtl.css 1.05 kB
build/styles/block-directory/style.css 1.05 kB
build/styles/block-editor/content-rtl.css 4.81 kB
build/styles/block-editor/content.css 4.8 kB
build/styles/block-editor/default-editor-styles-rtl.css 224 B
build/styles/block-editor/default-editor-styles.css 224 B
build/styles/block-editor/style-rtl.css 16.2 kB
build/styles/block-editor/style.css 16.2 kB
build/styles/block-library/accordion-heading/style-rtl.css 340 B
build/styles/block-library/accordion-heading/style.css 340 B
build/styles/block-library/accordion-item/style-rtl.css 213 B
build/styles/block-library/accordion-item/style.css 213 B
build/styles/block-library/accordion-panel/style-rtl.css 99 B
build/styles/block-library/accordion-panel/style.css 99 B
build/styles/block-library/archives/editor-rtl.css 61 B
build/styles/block-library/archives/editor.css 61 B
build/styles/block-library/archives/style-rtl.css 90 B
build/styles/block-library/archives/style.css 90 B
build/styles/block-library/audio/editor-rtl.css 149 B
build/styles/block-library/audio/editor.css 151 B
build/styles/block-library/audio/style-rtl.css 132 B
build/styles/block-library/audio/style.css 132 B
build/styles/block-library/audio/theme-rtl.css 134 B
build/styles/block-library/audio/theme.css 134 B
build/styles/block-library/avatar/editor-rtl.css 115 B
build/styles/block-library/avatar/editor.css 115 B
build/styles/block-library/avatar/style-rtl.css 104 B
build/styles/block-library/avatar/style.css 104 B
build/styles/block-library/breadcrumbs/style-rtl.css 203 B
build/styles/block-library/breadcrumbs/style.css 203 B
build/styles/block-library/button/editor-rtl.css 265 B
build/styles/block-library/button/editor.css 265 B
build/styles/block-library/button/style-rtl.css 554 B
build/styles/block-library/button/style.css 554 B
build/styles/block-library/buttons/editor-rtl.css 291 B
build/styles/block-library/buttons/editor.css 291 B
build/styles/block-library/buttons/style-rtl.css 349 B
build/styles/block-library/buttons/style.css 349 B
build/styles/block-library/calendar/style-rtl.css 239 B
build/styles/block-library/calendar/style.css 239 B
build/styles/block-library/categories/editor-rtl.css 132 B
build/styles/block-library/categories/editor.css 131 B
build/styles/block-library/categories/style-rtl.css 152 B
build/styles/block-library/categories/style.css 152 B
build/styles/block-library/classic-rtl.css 179 B
build/styles/block-library/classic.css 179 B
build/styles/block-library/code/editor-rtl.css 53 B
build/styles/block-library/code/editor.css 53 B
build/styles/block-library/code/style-rtl.css 139 B
build/styles/block-library/code/style.css 139 B
build/styles/block-library/code/theme-rtl.css 122 B
build/styles/block-library/code/theme.css 122 B
build/styles/block-library/columns/editor-rtl.css 108 B
build/styles/block-library/columns/editor.css 108 B
build/styles/block-library/columns/style-rtl.css 421 B
build/styles/block-library/columns/style.css 421 B
build/styles/block-library/comment-author-avatar/editor-rtl.css 124 B
build/styles/block-library/comment-author-avatar/editor.css 124 B
build/styles/block-library/comment-author-name/style-rtl.css 72 B
build/styles/block-library/comment-author-name/style.css 72 B
build/styles/block-library/comment-content/style-rtl.css 120 B
build/styles/block-library/comment-content/style.css 120 B
build/styles/block-library/comment-date/style-rtl.css 65 B
build/styles/block-library/comment-date/style.css 65 B
build/styles/block-library/comment-edit-link/style-rtl.css 70 B
build/styles/block-library/comment-edit-link/style.css 70 B
build/styles/block-library/comment-reply-link/style-rtl.css 71 B
build/styles/block-library/comment-reply-link/style.css 71 B
build/styles/block-library/comment-template/style-rtl.css 191 B
build/styles/block-library/comment-template/style.css 191 B
build/styles/block-library/comments-pagination-numbers/editor-rtl.css 122 B
build/styles/block-library/comments-pagination-numbers/editor.css 121 B
build/styles/block-library/comments-pagination/editor-rtl.css 168 B
build/styles/block-library/comments-pagination/editor.css 168 B
build/styles/block-library/comments-pagination/style-rtl.css 201 B
build/styles/block-library/comments-pagination/style.css 201 B
build/styles/block-library/comments-title/editor-rtl.css 75 B
build/styles/block-library/comments-title/editor.css 75 B
build/styles/block-library/comments/editor-rtl.css 842 B
build/styles/block-library/comments/editor.css 842 B
build/styles/block-library/comments/style-rtl.css 637 B
build/styles/block-library/comments/style.css 637 B
build/styles/block-library/common-rtl.css 1.11 kB
build/styles/block-library/common.css 1.11 kB
build/styles/block-library/cover/editor-rtl.css 631 B
build/styles/block-library/cover/editor.css 631 B
build/styles/block-library/cover/style-rtl.css 1.7 kB
build/styles/block-library/cover/style.css 1.69 kB
build/styles/block-library/details/editor-rtl.css 65 B
build/styles/block-library/details/editor.css 65 B
build/styles/block-library/details/style-rtl.css 86 B
build/styles/block-library/details/style.css 86 B
build/styles/block-library/editor-elements-rtl.css 75 B
build/styles/block-library/editor-elements.css 75 B
build/styles/block-library/editor-rtl.css 11.6 kB
build/styles/block-library/editor.css 11.6 kB
build/styles/block-library/elements-rtl.css 54 B
build/styles/block-library/elements.css 54 B
build/styles/block-library/embed/editor-rtl.css 331 B
build/styles/block-library/embed/editor.css 331 B
build/styles/block-library/embed/style-rtl.css 419 B
build/styles/block-library/embed/style.css 419 B
build/styles/block-library/embed/theme-rtl.css 133 B
build/styles/block-library/embed/theme.css 133 B
build/styles/block-library/file/editor-rtl.css 324 B
build/styles/block-library/file/editor.css 324 B
build/styles/block-library/file/style-rtl.css 278 B
build/styles/block-library/file/style.css 278 B
build/styles/block-library/footnotes/style-rtl.css 198 B
build/styles/block-library/footnotes/style.css 197 B
build/styles/block-library/form-input/editor-rtl.css 229 B
build/styles/block-library/form-input/editor.css 229 B
build/styles/block-library/form-input/style-rtl.css 366 B
build/styles/block-library/form-input/style.css 366 B
build/styles/block-library/form-submission-notification/editor-rtl.css 344 B
build/styles/block-library/form-submission-notification/editor.css 341 B
build/styles/block-library/form-submit-button/style-rtl.css 69 B
build/styles/block-library/form-submit-button/style.css 69 B
build/styles/block-library/freeform/editor-rtl.css 2.59 kB
build/styles/block-library/freeform/editor.css 2.59 kB
build/styles/block-library/gallery/editor-rtl.css 615 B
build/styles/block-library/gallery/editor.css 616 B
build/styles/block-library/gallery/style-rtl.css 1.84 kB
build/styles/block-library/gallery/style.css 1.84 kB
build/styles/block-library/gallery/theme-rtl.css 108 B
build/styles/block-library/gallery/theme.css 108 B
build/styles/block-library/group/editor-rtl.css 335 B
build/styles/block-library/group/editor.css 335 B
build/styles/block-library/group/style-rtl.css 103 B
build/styles/block-library/group/style.css 103 B
build/styles/block-library/group/theme-rtl.css 79 B
build/styles/block-library/group/theme.css 79 B
build/styles/block-library/heading/style-rtl.css 188 B
build/styles/block-library/heading/style.css 188 B
build/styles/block-library/html/editor-rtl.css 357 B
build/styles/block-library/html/editor.css 358 B
build/styles/block-library/image/editor-rtl.css 763 B
build/styles/block-library/image/editor.css 763 B
build/styles/block-library/image/style-rtl.css 1.6 kB
build/styles/block-library/image/style.css 1.59 kB
build/styles/block-library/image/theme-rtl.css 137 B
build/styles/block-library/image/theme.css 137 B
build/styles/block-library/latest-comments/style-rtl.css 355 B
build/styles/block-library/latest-comments/style.css 354 B
build/styles/block-library/latest-posts/editor-rtl.css 139 B
build/styles/block-library/latest-posts/editor.css 138 B
build/styles/block-library/latest-posts/style-rtl.css 520 B
build/styles/block-library/latest-posts/style.css 520 B
build/styles/block-library/list/style-rtl.css 107 B
build/styles/block-library/list/style.css 107 B
build/styles/block-library/loginout/style-rtl.css 61 B
build/styles/block-library/loginout/style.css 61 B
build/styles/block-library/math/editor-rtl.css 105 B
build/styles/block-library/math/editor.css 105 B
build/styles/block-library/math/style-rtl.css 61 B
build/styles/block-library/math/style.css 61 B
build/styles/block-library/media-text/editor-rtl.css 321 B
build/styles/block-library/media-text/editor.css 320 B
build/styles/block-library/media-text/style-rtl.css 543 B
build/styles/block-library/media-text/style.css 542 B
build/styles/block-library/more/editor-rtl.css 393 B
build/styles/block-library/more/editor.css 393 B
build/styles/block-library/navigation-link/editor-rtl.css 626 B
build/styles/block-library/navigation-link/editor.css 628 B
build/styles/block-library/navigation-link/style-rtl.css 190 B
build/styles/block-library/navigation-link/style.css 188 B
build/styles/block-library/navigation-submenu/editor-rtl.css 295 B
build/styles/block-library/navigation-submenu/editor.css 294 B
build/styles/block-library/navigation/editor-rtl.css 2.24 kB
build/styles/block-library/navigation/editor.css 2.24 kB
build/styles/block-library/navigation/style-rtl.css 2.27 kB
build/styles/block-library/navigation/style.css 2.25 kB
build/styles/block-library/nextpage/editor-rtl.css 392 B
build/styles/block-library/nextpage/editor.css 392 B
build/styles/block-library/page-list/editor-rtl.css 356 B
build/styles/block-library/page-list/editor.css 356 B
build/styles/block-library/page-list/style-rtl.css 192 B
build/styles/block-library/page-list/style.css 192 B
build/styles/block-library/paragraph/editor-rtl.css 251 B
build/styles/block-library/paragraph/editor.css 251 B
build/styles/block-library/paragraph/style-rtl.css 341 B
build/styles/block-library/paragraph/style.css 340 B
build/styles/block-library/post-author-biography/style-rtl.css 74 B
build/styles/block-library/post-author-biography/style.css 74 B
build/styles/block-library/post-author-name/style-rtl.css 69 B
build/styles/block-library/post-author-name/style.css 69 B
build/styles/block-library/post-author/style-rtl.css 188 B
build/styles/block-library/post-author/style.css 189 B
build/styles/block-library/post-comments-count/style-rtl.css 72 B
build/styles/block-library/post-comments-count/style.css 72 B
build/styles/block-library/post-comments-form/editor-rtl.css 96 B
build/styles/block-library/post-comments-form/editor.css 96 B
build/styles/block-library/post-comments-form/style-rtl.css 525 B
build/styles/block-library/post-comments-form/style.css 525 B
build/styles/block-library/post-comments-link/style-rtl.css 71 B
build/styles/block-library/post-comments-link/style.css 71 B
build/styles/block-library/post-content/style-rtl.css 61 B
build/styles/block-library/post-content/style.css 61 B
build/styles/block-library/post-date/style-rtl.css 62 B
build/styles/block-library/post-date/style.css 62 B
build/styles/block-library/post-excerpt/editor-rtl.css 71 B
build/styles/block-library/post-excerpt/editor.css 71 B
build/styles/block-library/post-excerpt/style-rtl.css 155 B
build/styles/block-library/post-excerpt/style.css 155 B
build/styles/block-library/post-featured-image/editor-rtl.css 719 B
build/styles/block-library/post-featured-image/editor.css 717 B
build/styles/block-library/post-featured-image/style-rtl.css 347 B
build/styles/block-library/post-featured-image/style.css 347 B
build/styles/block-library/post-navigation-link/style-rtl.css 215 B
build/styles/block-library/post-navigation-link/style.css 214 B
build/styles/block-library/post-template/style-rtl.css 414 B
build/styles/block-library/post-template/style.css 414 B
build/styles/block-library/post-terms/style-rtl.css 96 B
build/styles/block-library/post-terms/style.css 96 B
build/styles/block-library/post-time-to-read/style-rtl.css 70 B
build/styles/block-library/post-time-to-read/style.css 70 B
build/styles/block-library/post-title/style-rtl.css 162 B
build/styles/block-library/post-title/style.css 162 B
build/styles/block-library/preformatted/style-rtl.css 125 B
build/styles/block-library/preformatted/style.css 125 B
build/styles/block-library/pullquote/editor-rtl.css 133 B
build/styles/block-library/pullquote/editor.css 133 B
build/styles/block-library/pullquote/style-rtl.css 365 B
build/styles/block-library/pullquote/style.css 365 B
build/styles/block-library/pullquote/theme-rtl.css 176 B
build/styles/block-library/pullquote/theme.css 176 B
build/styles/block-library/query-pagination-numbers/editor-rtl.css 121 B
build/styles/block-library/query-pagination-numbers/editor.css 118 B
build/styles/block-library/query-pagination/editor-rtl.css 154 B
build/styles/block-library/query-pagination/editor.css 154 B
build/styles/block-library/query-pagination/style-rtl.css 237 B
build/styles/block-library/query-pagination/style.css 237 B
build/styles/block-library/query-title/style-rtl.css 64 B
build/styles/block-library/query-title/style.css 64 B
build/styles/block-library/query-total/style-rtl.css 64 B
build/styles/block-library/query-total/style.css 64 B
build/styles/block-library/query/editor-rtl.css 438 B
build/styles/block-library/query/editor.css 438 B
build/styles/block-library/quote/style-rtl.css 238 B
build/styles/block-library/quote/style.css 238 B
build/styles/block-library/quote/theme-rtl.css 233 B
build/styles/block-library/quote/theme.css 236 B
build/styles/block-library/read-more/style-rtl.css 131 B
build/styles/block-library/read-more/style.css 131 B
build/styles/block-library/reset-rtl.css 472 B
build/styles/block-library/reset.css 472 B
build/styles/block-library/rss/editor-rtl.css 126 B
build/styles/block-library/rss/editor.css 126 B
build/styles/block-library/rss/style-rtl.css 284 B
build/styles/block-library/rss/style.css 283 B
build/styles/block-library/search/editor-rtl.css 199 B
build/styles/block-library/search/editor.css 199 B
build/styles/block-library/search/style-rtl.css 665 B
build/styles/block-library/search/style.css 666 B
build/styles/block-library/search/theme-rtl.css 113 B
build/styles/block-library/search/theme.css 113 B
build/styles/block-library/separator/editor-rtl.css 100 B
build/styles/block-library/separator/editor.css 100 B
build/styles/block-library/separator/style-rtl.css 248 B
build/styles/block-library/separator/style.css 248 B
build/styles/block-library/separator/theme-rtl.css 195 B
build/styles/block-library/separator/theme.css 195 B
build/styles/block-library/shortcode/editor-rtl.css 286 B
build/styles/block-library/shortcode/editor.css 286 B
build/styles/block-library/site-logo/editor-rtl.css 773 B
build/styles/block-library/site-logo/editor.css 770 B
build/styles/block-library/site-logo/style-rtl.css 218 B
build/styles/block-library/site-logo/style.css 218 B
build/styles/block-library/site-tagline/editor-rtl.css 87 B
build/styles/block-library/site-tagline/editor.css 87 B
build/styles/block-library/site-tagline/style-rtl.css 65 B
build/styles/block-library/site-tagline/style.css 65 B
build/styles/block-library/site-title/editor-rtl.css 85 B
build/styles/block-library/site-title/editor.css 85 B
build/styles/block-library/site-title/style-rtl.css 143 B
build/styles/block-library/site-title/style.css 143 B
build/styles/block-library/social-link/editor-rtl.css 314 B
build/styles/block-library/social-link/editor.css 314 B
build/styles/block-library/social-links/editor-rtl.css 339 B
build/styles/block-library/social-links/editor.css 338 B
build/styles/block-library/social-links/style-rtl.css 1.51 kB
build/styles/block-library/social-links/style.css 1.51 kB
build/styles/block-library/spacer/editor-rtl.css 346 B
build/styles/block-library/spacer/editor.css 346 B
build/styles/block-library/spacer/style-rtl.css 48 B
build/styles/block-library/spacer/style.css 48 B
build/styles/block-library/style-rtl.css 15.6 kB
build/styles/block-library/style.css 15.6 kB
build/styles/block-library/table-of-contents/style-rtl.css 83 B
build/styles/block-library/table-of-contents/style.css 83 B
build/styles/block-library/table/editor-rtl.css 394 B
build/styles/block-library/table/editor.css 394 B
build/styles/block-library/table/style-rtl.css 641 B
build/styles/block-library/table/style.css 640 B
build/styles/block-library/table/theme-rtl.css 152 B
build/styles/block-library/table/theme.css 152 B
build/styles/block-library/tag-cloud/editor-rtl.css 92 B
build/styles/block-library/tag-cloud/editor.css 92 B
build/styles/block-library/tag-cloud/style-rtl.css 248 B
build/styles/block-library/tag-cloud/style.css 248 B
build/styles/block-library/template-part/editor-rtl.css 368 B
build/styles/block-library/template-part/editor.css 368 B
build/styles/block-library/template-part/theme-rtl.css 113 B
build/styles/block-library/template-part/theme.css 113 B
build/styles/block-library/term-count/style-rtl.css 63 B
build/styles/block-library/term-count/style.css 63 B
build/styles/block-library/term-description/style-rtl.css 126 B
build/styles/block-library/term-description/style.css 126 B
build/styles/block-library/term-name/style-rtl.css 62 B
build/styles/block-library/term-name/style.css 62 B
build/styles/block-library/term-template/editor-rtl.css 225 B
build/styles/block-library/term-template/editor.css 225 B
build/styles/block-library/term-template/style-rtl.css 114 B
build/styles/block-library/term-template/style.css 114 B
build/styles/block-library/text-columns/editor-rtl.css 95 B
build/styles/block-library/text-columns/editor.css 95 B
build/styles/block-library/text-columns/style-rtl.css 165 B
build/styles/block-library/text-columns/style.css 165 B
build/styles/block-library/theme-rtl.css 715 B
build/styles/block-library/theme.css 719 B
build/styles/block-library/verse/style-rtl.css 98 B
build/styles/block-library/verse/style.css 98 B
build/styles/block-library/video/editor-rtl.css 415 B
build/styles/block-library/video/editor.css 416 B
build/styles/block-library/video/style-rtl.css 202 B
build/styles/block-library/video/style.css 202 B
build/styles/block-library/video/theme-rtl.css 134 B
build/styles/block-library/video/theme.css 134 B
build/styles/commands/style-rtl.css 999 B
build/styles/commands/style.css 1 kB
build/styles/components/style-rtl.css 14 kB
build/styles/components/style.css 14 kB
build/styles/customize-widgets/style-rtl.css 1.44 kB
build/styles/customize-widgets/style.css 1.44 kB
build/styles/edit-post/classic-rtl.css 426 B
build/styles/edit-post/classic.css 427 B
build/styles/edit-post/style-rtl.css 3.33 kB
build/styles/edit-post/style.css 3.33 kB
build/styles/edit-site/posts-rtl.css 9.85 kB
build/styles/edit-site/posts.css 9.84 kB
build/styles/edit-site/style-rtl.css 15.4 kB
build/styles/edit-site/style.css 15.4 kB
build/styles/edit-widgets/style-rtl.css 4.59 kB
build/styles/edit-widgets/style.css 4.59 kB
build/styles/editor/style-rtl.css 18 kB
build/styles/editor/style.css 18 kB
build/styles/format-library/style-rtl.css 308 B
build/styles/format-library/style.css 308 B
build/styles/list-reusable-blocks/style-rtl.css 1.02 kB
build/styles/list-reusable-blocks/style.css 1.02 kB
build/styles/nux/style-rtl.css 622 B
build/styles/nux/style.css 618 B
build/styles/patterns/style-rtl.css 703 B
build/styles/patterns/style.css 703 B
build/styles/preferences/style-rtl.css 415 B
build/styles/preferences/style.css 415 B
build/styles/reusable-blocks/style-rtl.css 275 B
build/styles/reusable-blocks/style.css 275 B
build/styles/widgets/style-rtl.css 1.17 kB
build/styles/widgets/style.css 1.18 kB

compressed-size-action

@github-actions
Copy link

Flaky tests detected in be2f49d.
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/18915118688
📝 Reported issues:

Copy link
Member

@Mamaduka Mamaduka left a comment

Choose a reason for hiding this comment

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

The top-level setting name aside, I like that the definition can be static and doesn't require. This will also allow developers to extend existing blocks and enable the feature.

cc @fabiankaegy

Comment on lines +151 to +156
"mediaRoles": {
"id": "id",
"url": "url",
"alt": "alt",
"type": { "attribute": "backgroundType" }
},
Copy link
Member

Choose a reason for hiding this comment

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

If I understand this correctly, the type can have a hardcoded value or derive it from a specific attribute. Is that correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. This is needed to handle both blocks without a type attribute like Image and the ones that have a type.

What I haven't thought much right now is what happens if blocks have already a similar type attribute, but its values are not strictly among image|video|audio. This is not the case for the core blocks, but something that we might need to consider for 3rd party development.

@youknowriad
Copy link
Contributor

I wonder how this relates with the idea of block attributes being the same thing as "dataviews field API" and also the same thing conceptually as JSON Schema.

How do images get represented in JSON Schema is something we should be looking at. Maybe it's a type (current approach in DataViews), maybe it's something else.

There's some consolidation to think about it here.

@gziolo
Copy link
Member

gziolo commented Oct 30, 2025

Interesting exploration. Enforcing some structure for content attributes is becoming more critical as we scale the block editor capabilities.

@ockham did a bit of different but related research on how to map an image object properties to the Image block or Featured Image block attributes through Pattern Overrides or other forms of Block Bindings to support native functions like get_the_post_thumbnail_url or custom post meta:

My only comment is that this proposal is very specific to a small number of blocks, so it's worth considering generalizing it to content where media is only one of several formats.

@ntsekouras
Copy link
Contributor Author

I wonder how this relates with the idea of block attributes being the same thing as "dataviews field API" and also the same thing conceptually as JSON Schema.

How do images get represented in JSON Schema is something we should be looking at. Maybe it's a type (current approach in DataViews), maybe it's something else.

@youknowriad can you elaborate a bit on these?

@mcsf
Copy link
Contributor

mcsf commented Oct 30, 2025

This is a cool exploration, useful regardless of outcome. You got me thinking about a couple of things: the possible overuse of role: content that you mentioned, and the semantics of "media blocks". By the latter, I mean questions like: Are there blocks that are solely about media, mainly, or secondarily about media? Does that distinction matter? How does "content" and "media" relate? And so on.

If, like me, you're curious about what roles are currently used in the core block library:

fig.: all attributes with a set role
{
  "core/accordion-heading": {
    "title": "content"
  },
  "core/audio": {
    "blob": "local",
    "src": "content",
    "caption": "content",
    "id": "content"
  },
  "core/button": {
    "url": "content",
    "title": "content",
    "text": "content",
    "linkTarget": "content",
    "rel": "content"
  },
  "core/categories": {
    "label": "content"
  },
  "core/code": {
    "content": "content"
  },
  "core/cover": {
    "url": "content"
  },
  "core/details": {
    "summary": "content"
  },
  "core/embed": {
    "url": "content",
    "caption": "content",
    "type": "content",
    "providerNameSlug": "content",
    "responsive": "content",
    "previewable": "content"
  },
  "core/file": {
    "blob": "local",
    "href": "content",
    "fileName": "content",
    "textLinkHref": "content",
    "downloadButtonText": "content"
  },
  "core/form-input": {
    "label": "content",
    "placeholder": "content"
  },
  "core/gallery": {
    "caption": "content"
  },
  "core/heading": {
    "content": "content"
  },
  "core/home-link": {
    "label": "content"
  },
  "core/html": {
    "content": "content"
  },
  "core/image": {
    "blob": "local",
    "url": "content",
    "alt": "content",
    "caption": "content",
    "title": "content",
    "href": "content",
    "id": "content"
  },
  "core/list-item": {
    "content": "content"
  },
  "core/list": {
    "ordered": "content",
    "values": "content"
  },
  "core/math": {
    "latex": "content"
  },
  "core/media-text": {
    "mediaAlt": "content",
    "mediaId": "content",
    "mediaUrl": "content",
    "href": "content",
    "mediaType": "content"
  },
  "core/more": {
    "customText": "content"
  },
  "core/navigation-link": {
    "label": "content"
  },
  "core/navigation-submenu": {
    "label": "content"
  },
  "core/paragraph": {
    "content": "content"
  },
  "core/post-author-name": {
    "isLink": "content",
    "linkTarget": "content"
  },
  "core/post-author": {
    "isLink": "content",
    "linkTarget": "content"
  },
  "core/post-date": {
    "datetime": "content",
    "isLink": "content"
  },
  "core/post-excerpt": {
    "moreText": "content"
  },
  "core/post-featured-image": {
    "isLink": "content",
    "rel": "content",
    "linkTarget": "content"
  },
  "core/post-navigation-link": {
    "label": "content"
  },
  "core/post-terms": {
    "prefix": "content",
    "suffix": "content"
  },
  "core/post-title": {
    "isLink": "content",
    "rel": "content",
    "linkTarget": "content"
  },
  "core/preformatted": {
    "content": "content"
  },
  "core/pullquote": {
    "value": "content",
    "citation": "content"
  },
  "core/quote": {
    "value": "content",
    "citation": "content"
  },
  "core/read-more": {
    "content": "content"
  },
  "core/rss": {
    "feedURL": "content"
  },
  "core/search": {
    "label": "content",
    "placeholder": "content",
    "buttonText": "content"
  },
  "core/shortcode": {
    "text": "content"
  },
  "core/site-logo": {
    "isLink": "content",
    "linkTarget": "content"
  },
  "core/site-title": {
    "isLink": "content",
    "linkTarget": "content"
  },
  "core/social-link": {
    "url": "content",
    "label": "content"
  },
  "core/table": {
    "caption": "content"
  },
  "core/verse": {
    "content": "content"
  },
  "core/video": {
    "caption": "content",
    "id": "content",
    "blob": "local",
    "src": "content",
    "tracks": "content"
  }
}
src: jq program to produce the above
jq -s '
	map(
		{
			key: .name,
			value: (
				.attributes
				| to_entries?
				| map(select(.value | has("role")))
				| map({key: .key, value: .value.role})
				| select(length > 0)
				| from_entries
			)
		}
	)
	| from_entries
' packages/block-library/src/*/block.json

Some generalisations from this:

  • The content role absorbs a lot of data that could be re-modelled as media
  • The content role feels more like an annotation that says "preserve me" (e.g. over a transformation). If it has any real meaning left, I'd argue that it's content = ⌐ design

@ramonjd
Copy link
Member

ramonjd commented Oct 30, 2025

Could this be useful in some way to pattern content only editing?

Thanks for the ping! I can't say for sure, but I'd wager such metadata would be useful, for example, to target bespoke behaviour for various media blocks in content only mode. The first thing that comes to mind is editable fields.

cc @talldan

@tellthemachines
Copy link
Contributor

  • The content role feels more like an annotation that says "preserve me" (e.g. over a transformation). If it has any real meaning left, I'd argue that it's content = ⌐ design

This distinction is central to contentOnly mode, because the attributes that have the content role are still editable in that mode (this should apply not only to the contentOnly patterns experiment but also to the templateLock)

I'm not sure a media role would solve any specific problems we have with contentOnly mode, because generally we want media to be editable similarly to text: you should be able to replace it, and edit text attributes such as alt, captions etc. In other words, there hasn't been a need so far to treat media in any way differently from text content.

@talldan
Copy link
Contributor

talldan commented Nov 3, 2025

Thanks for the ping! I can't say for sure, but I'd wager such metadata would be useful, for example, to target bespoke behaviour for various media blocks in content only mode. The first thing that comes to mind is #71557.

It's still quite an early draft, but agree it could be helpful for that - I added some very similar 'mapping' code in the PR, which I planned to make optional, but this would hopefully allow me to remove that completely for media fields.

Another use case might be related to an idea I had - being able to surface all the 'attachments' that are used within a post.

One thing I'll mention is that the mediaRoles feels quite specific for the one use case. For example, a wp/block also maps to pattern post types in a similar way to images mapping to attachments. Navigation blocks, template parts and probably others also map to entities.

So I wonder if this can be made more general to map any kind of entity or resource. That way it could allow for discovering any kind of entity usage within block content and support parsing values. It might contribute to solving this - Tracking and providing insights about consumption of global elements, and also be useful for things like preloading entities.

@ntsekouras
Copy link
Contributor Author

For example, a wp/block also maps to pattern post types in a similar way to images mapping to attachments. Navigation blocks, template parts and probably others also map to entities.

@talldan can you expand a bit on this? What kind of config would be useful to handle the wp/block to pattern post types for example?

@talldan
Copy link
Contributor

talldan commented Nov 3, 2025

@talldan can you expand a bit on this? What kind of config would be useful to handle the wp/block to pattern post types for example?

Something like this to indicate that the wp:block block loads the 'block' post type, with the 'ref' attribute being the post id?

resources: {
    block: { id: 'ref' } // maps to `postType/block` resource
}

getBlockResource( 'block' ) // { id: 12 }
getBlockResource( 'attachment' ) // { id: 32, src: 'https://example.com/cover.png', mediaType: 'image' }

Though I'm not sure the more I think on it, this is quite different to what others are discussing and maybe it's not the right use case to solve with this API.

What has been mentioned in other comments is the config is more related to dataview fields. So I think it's similar to what I'm working on in #71730. In that PR I'm trying to generate a 'form' (I plan to make it a DataForm at some point) for editing blocks in the inspector. At the moment it's only concerned with content attributes, and across our core blocks that's really only Text, Links and Media field types. Link and Media are the two that have very inconsistent attribute definitions so need some kind of mapping.

I think for your use case in List View, you could possibly render a 'read only' version of a media field.

@ntsekouras
Copy link
Contributor Author

ntsekouras commented Nov 12, 2025

I shared here what I think about the connection of this PR with the formats+type PRs for fields API and block attributes. I'll past the part that is relative to this PR.

Regarding my media roles experiment, it seems it's also a different thing from JSON format and types. In general it tries to add semantic info in some attributes, which I cannot see how they fit in these format+type approaches. Sure, we could have some kind of convention that for example a mediaAlt prop should always be type:string and use that info for whatever we'd need.

So, to answer @youknowriad's question, I don't think the semantic info we want should be part of type or format. We could have conventions/mappers about the roles to match a specific type (mediaAlt->string), but probably that would be it.

So maybe this exploration, expanded to support more things other than media roles, with some kind of mapping with specific roles to attributes might be helpful for more cases besides the media roles. If that would be the case, @talldan could your example about resources be part of such a config in block.json, and actually be helpful?

@talldan
Copy link
Contributor

talldan commented Dec 11, 2025

Sorry for the delay in responding @ntsekouras, I had some AFK and missed the ping.

I think it's pretty difficult to predict right now what's going to happen as there's a lot of work happening in parallel. I would say what's known is that there's going to be a way in the near future to map block attributes to dataviews fields. There is already a rudimentary API that's being explored as part of the contentOnly experiments (Pattern fields in the inspector panel: use the DataForms API). I think that needs to becomes a lot more mature, and I think it'll need to expand to more block attributes.

Whether that's enough to satisfy your use case, I'm not sure. I think there will be a way to associate attributes with their purpose for a media field. MediaUpload particularly, but perhaps it's also enough to show a MediaThumbnail in List View. I guess the field type might be loose enough that you could use different field implementations, or the same field could appear in different ways for different contexts.

@oandregal is the fields expert, so might be able to help with interpretation. 😄

TBH, the proposals feel quite closely associated, so maybe it's worth waiting to see how the block fields develop.

@mcsf
Copy link
Contributor

mcsf commented Dec 12, 2025

Just noting, for the purposes of traceability, that this work is also very related to #73845.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Feature] Block API API that allows to express the block paradigm. [Type] Enhancement A suggestion for improvement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants