Skip to content

Accordion block: experiment with the concept of a 'composite' container block - #73510

Closed
talldan wants to merge 8 commits into
trunkfrom
experiment/accordion-composite-blocks
Closed

Accordion block: experiment with the concept of a 'composite' container block#73510
talldan wants to merge 8 commits into
trunkfrom
experiment/accordion-composite-blocks

Conversation

@talldan

@talldan talldan commented Nov 24, 2025

Copy link
Copy Markdown
Contributor

What?

Attempts a simple first iteration of #70994, using the Accordion Item block. The accordion block previously used templateLock as a way to compose blocks in this structure:

  • Accordion Item (templateLock: all)
    • Accordion Heading
    • Accordion Panel (templateLock: false)

But as noted below, the use of templateLock causes some bugs.

Why?

It was noted in the discussion here that there are currently 2-3 bugs with the accordion block:

  • If a user tries to lock a parent of an accordion and uses "Apply to all block inside", the accordion doesn't respect it. The core/accordion-panel block explicitly sets templateLock: false in its block attributes, and this unexpectedly overrides any templateLock set by an ancestor.
  • The new contentOnly insertion feature was interfering with the accordion block allowing extra core/accordion-header and core/accordion-panel blocks to be inserted into a core/accordion-item.
  • core/accordion-header and core/accordion-panel display lock icons, but the user can't unlock them, so that can be misleading.

There might be ways to work around these problems, but this type of block composition is what #70994 proposes to solve, so I think it might be an idea to ship an early iteration.

How?

Adds a (private for now) composite flag to the core/accordion-item block. The flag indicates to the editor that all direct children of this block are fixed. While they can still be edited, they cannot be moved or removed, and additional blocks cannot be inserted into a composite container. The idea is to use this flag with a template. It's a separate API to templateLock so that it doesn't interfere with templateLock's inheritance rules. Another reason to keep it separate is that templateLock can be modified by users, and this should be something not modifiable by users.

Also adds supports.inserter = false to core/accordion-header and core/accordion-panel so that they don't ever appear in the inserter.

Testing Instructions

tempateLock: 'contentOnly'

  1. Add the following block markup, which has an accordion in a contentOnly group:
<!-- wp:group {"templateLock":"contentOnly"} -->
<div class="wp-block-group"><!-- wp:accordion {"iconPosition":"left"} -->
<div role="group" class="wp-block-accordion"><!-- wp:accordion-item -->
<div class="wp-block-accordion-item"><!-- wp:accordion-heading {"iconPosition":"left"} -->
<h3 class="wp-block-accordion-heading"><button class="wp-block-accordion-heading__toggle"><span class="wp-block-accordion-heading__toggle-icon" aria-hidden="true">+</span><span class="wp-block-accordion-heading__toggle-title">test</span></button></h3>
<!-- /wp:accordion-heading -->

<!-- wp:accordion-panel {"isSelected":true} -->
<div role="region" class="wp-block-accordion-panel"><!-- wp:paragraph -->
<p>accordion content</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>also accordion content</p>
<!-- /wp:paragraph --></div>
<!-- /wp:accordion-panel --></div>
<!-- /wp:accordion-item --></div>
<!-- /wp:accordion --></div>
<!-- /wp:group -->
  1. Observe that Accordion Heading and Accordion Panel no longer have lock icons
  2. You could be able to add/remove paragraphs within the Accordion Panel
  3. Select the accordion block, you should be able to add/remove Accordion Items (though for some reason Add before / after don't work, I think that's also an issue in trunk)
  4. Test that you can't move or remove the Accordion Heading or Panel, and you can't insert more Accordion Headings or Panels in an Accordion Item.

Block locking

  1. Add an accordion block, add some paragraph content inside the panel
  2. Group the accordion block
  3. Select the lock option on the group from the block settings menu
  4. Select 'Lock all' and 'Apply to all blocks inside'
  5. Observe that the paragraphs inside the accordion are correctly locked, and you also can't add new Accordion Items

Screenshots or screencast

Kapture.2025-11-25.at.14.54.03.mp4
@github-actions

github-actions Bot commented Nov 24, 2025

Copy link
Copy Markdown

Size Change: -7 B (0%)

Total Size: 2.54 MB

Filename Size Change
build/scripts/block-editor/index.min.js 322 kB +2 B (0%)
build/scripts/block-library/index.min.js 275 kB +55 B (+0.02%)
build/scripts/blocks/index.min.js 56.3 kB +14 B (+0.02%)
build/scripts/edit-site/index.min.js 233 kB -12 B (-0.01%)
build/styles/edit-site/style-rtl.css 16.1 kB -17 B (-0.11%)
build/styles/edit-site/style.css 16.1 kB -18 B (-0.11%)
build/styles/editor/style-rtl.css 18.7 kB -15 B (-0.08%)
build/styles/editor/style.css 18.7 kB -16 B (-0.09%)
ℹ️ View Unchanged
Filename Size
build/modules/a11y/index.min.js 355 B
build/modules/abilities/index.min.js 43 kB
build/modules/block-editor/utils/fit-text-frontend.min.js 549 B
build/modules/block-library/accordion/view.min.js 779 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.95 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/block-library/tabs/view.min.js 859 B
build/modules/boot/index.min.js 69.7 kB
build/modules/edit-site-init/index.min.js 1.3 kB
build/modules/interactivity-router/full-page.min.js 451 B
build/modules/interactivity-router/index.min.js 11.5 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/modules/lazy-editor/index.min.js 18.8 kB
build/modules/route/index.min.js 24.5 kB
build/modules/workflow/index.min.js 36.8 kB
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.03 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 19.9 kB
build/scripts/components/index.min.js 271 kB
build/scripts/compose/index.min.js 13.9 kB
build/scripts/core-commands/index.min.js 4.13 kB
build/scripts/core-data/index.min.js 86.1 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 752 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.3 kB
build/scripts/edit-widgets/index.min.js 20 kB
build/scripts/editor/index.min.js 284 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.8 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/list-reusable-blocks/index.min.js 2.44 kB
build/scripts/media-utils/index.min.js 66.7 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 7.88 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.11 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.93 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.91 kB
build/scripts/shortcode/index.min.js 1.58 kB
build/scripts/style-engine/index.min.js 2.32 kB
build/scripts/theme/index.min.js 20.8 kB
build/scripts/token-list/index.min.js 739 B
build/scripts/undo-manager/index.min.js 917 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.81 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.8 kB
build/styles/block-editor/content.css 4.79 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.4 kB
build/styles/block-editor/style.css 16.3 kB
build/styles/block-library/accordion-heading/style-rtl.css 387 B
build/styles/block-library/accordion-heading/style.css 387 B
build/styles/block-library/accordion-item/style-rtl.css 180 B
build/styles/block-library/accordion-item/style.css 180 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/accordion/style-rtl.css 62 B
build/styles/block-library/accordion/style.css 62 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.8 kB
build/styles/block-library/editor.css 11.8 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 448 B
build/styles/block-library/embed/style.css 448 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 205 B
build/styles/block-library/heading/style.css 205 B
build/styles/block-library/html/editor-rtl.css 419 B
build/styles/block-library/html/editor.css 419 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 645 B
build/styles/block-library/navigation-link/editor.css 647 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 16.5 kB
build/styles/block-library/style.css 16.5 kB
build/styles/block-library/tab/style-rtl.css 202 B
build/styles/block-library/tab/style.css 202 B
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/tabs/editor-rtl.css 236 B
build/styles/block-library/tabs/editor.css 236 B
build/styles/block-library/tabs/style-rtl.css 983 B
build/styles/block-library/tabs/style.css 983 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 1.72 kB
build/styles/commands/style.css 1.72 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.42 kB
build/styles/edit-post/style.css 3.42 kB
build/styles/edit-widgets/style-rtl.css 4.67 kB
build/styles/edit-widgets/style.css 4.67 kB
build/styles/format-library/style-rtl.css 326 B
build/styles/format-library/style.css 326 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 611 B
build/styles/patterns/style.css 611 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

expect( canRemoveBlock( state, 'block1' ) ).toBe( false );
} );

it( 'denies removal when parent has templateLock set to all', () => {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Claude did add tests for stuff not introduced in this PR, but I'm not complaining, the tests look good to me and broadens the code coverage.

@talldan talldan added [Type] Enhancement A suggestion for improvement. [Block] Accordion Affects the Accordion Block labels Nov 25, 2025
@talldan
talldan force-pushed the experiment/accordion-composite-blocks branch from 21ba1eb to c9887e1 Compare November 25, 2025 07:56
@ramonjd
ramonjd marked this pull request as ready for review November 25, 2025 23:16
@github-actions

github-actions Bot commented Nov 25, 2025

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: talldan <talldanwp@git.wordpress.org>
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: youknowriad <youknowriad@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: andrewserong <andrewserong@git.wordpress.org>

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

@ramonjd

ramonjd commented Nov 26, 2025

Copy link
Copy Markdown
Member

This is working well for me:

Kapture.2025-11-26.at.14.39.50.mp4

I think it's a good base for iteration, but would prefer to wait for @t-hamano's advice.

Just so I understand, with the composite block API, is the intention that templateLock be fully removed from accordion the or kept for compatibility?

Also, Claude flagged the following edge cases - is it worth writing unit tests for these?

// Composite + block lock attributes: What if a child of a composite block has lock.remove: false or lock.move: false? Does composite take precedence?
it( 'composite parent prevents removal even when child has lock.remove set to false', () => {
	// Test that composite overrides lock.remove: false
} );

// Composite + templateLock: What if a composite block also has templateLock: 'contentOnly' or templateLock: 'insert'? Does composite take precedence?
it( 'composite parent prevents removal even when templateLock is insert', () => {
	// Test that composite overrides templateLock: 'insert'
} );

Happy to add these tests, but just wanted to be sure of the implementation

@t-hamano

t-hamano commented Dec 1, 2025

Copy link
Copy Markdown
Contributor

Thanks for the PR!

Personally, I'm a bit hesitant to add yet another API, especially since two related APIs, templateLock and contentRole, are already exposed 😅

In the future, it certainly might make sense to add new APIs for composite components, but for now, I prefer to investigate why the parent's templateLock overrides the child's templateLock. I would like to know if there are any technical limitations.

For example, I'm wondering if we can make a small change here to prioritize this setting.

const _templateLock =
	// Inherit the parent lock only when the child does not explicitly define a template lock
	templateLock === undefined ? parentLock : templateLock;

That said, the API this PR adds is private, so if no other ideal solution exists, I think it's OK to go ahead with this PR.

@ramonjd

ramonjd commented Dec 1, 2025

Copy link
Copy Markdown
Member

Personally, I'm a bit hesitant to add yet another API, especially since two related APIs, templateLock and contentRole, are already exposed

Fair point. Let's see what other folks think before rushing in. Are there alternatives to fixing this issue?

@talldan

talldan commented Dec 8, 2025

Copy link
Copy Markdown
Contributor Author

I prefer to investigate why the parent's templateLock overrides the child's templateLock. I would like to know if there are any technical limitations.

@t-hamano It is documented that this is how contentOnly works - "Unlike the other lock types, this is not overridable by children.":
https://developer.wordpress.org/block-editor/reference-guides/block-api/block-templates/#locking

I'm not sure how to change that without a back compat break. There are also quite a few UX considerations if some parts of a contentOnly block tree could be set back to templateLock: false.

That's also only one of the 3 issues mentioned. Continuing to use templateLock won't solve the other two bugs.

@ramonjd ramonjd 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.

For what it's worth, this is working well for me.

The icons don't appear in a "templateLock":"contentOnly" group. I can add/remove paragraphs in the panel too, but I can't remove the accordion heading/panel

With grouping and locking:

Screenshot 2025-12-10 at 4 04 10 pm

This solves a few bugs - could we merge and see how it goes?

I had a couple of questions about extra edge case test coverage here: #73510 (comment)

I wasn't sure whether it was overkill.

@talldan

talldan commented Dec 10, 2025

Copy link
Copy Markdown
Contributor Author

I had a couple of questions about extra edge case test coverage here: #73510 (comment)

I can add the tests, I also don't mind if you commit that kind of thing directly to the PR, seeing as you were already half way there. Claude mostly wrote the tests for me in the first place, so it's funny that your Claude mentioned some missing cases.

Just so I understand, with the composite block API, is the intention that templateLock be fully removed from accordion the or kept for compatibility?

I don't think there's any back compat concerns with removing templateLock. None that I can think of. I'll test with an older version of the block to make sure there's no validation issues before merging.

@ramonjd

ramonjd commented Dec 10, 2025

Copy link
Copy Markdown
Member

Claude mostly wrote the tests for me in the first place, so it's funny that your Claude mentioned some missing cases.

No worries, thanks for the explainer. LGTM

@youknowriad youknowriad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can I have a summary of what this "composite" is supposed to do. I think we should be very intentional when introducing new things to the block API and I want to make sure we're not adding something new to fix an edge case that might be solved differently.

@talldan

talldan commented Dec 10, 2025

Copy link
Copy Markdown
Contributor Author

@youknowriad The long-term aim is a way to build a single block that's composed of other inner blocks.

'Accordion Item' is already trying to do this in trunk (the idea is that it's inner 'Accordion Heading' and 'Accordion Panel' blocks are present by default and should never be removable).

The code in trunk tries to achieve this by hard-coding templateLock, but that causes problems:

  • Lock icons appear on the blocks .
  • The accordion block doesn't work correctly when nested in a parent block that has templateLock - it's own hard-coded templateLock interferes with templateLock inheritance.
@youknowriad

Copy link
Copy Markdown
Contributor

The long-term aim is a way to build a single block that's composed of other inner blocks.

For me that's what simplified pattern editing is about, so I'm a bit concerned about duplication here.

@ramonjd

ramonjd commented Dec 10, 2025

Copy link
Copy Markdown
Member

For me that's what simplified pattern editing is about, so I'm a bit concerned about duplication here.

My understanding is the that intent and scope are different between composite blocks and pattern editing, probably with some nuance that I'm missing.

  1. For me composite blocks are about block architecture - a single logical block composed of fixed inner blocks. In other words, defining that certain blocks are permanently composed together as a single conceptual unit.
  2. Pattern contentOnly is about editing modes - temporarily restricting what users can modify in a collection of blocks.

I think I see the direction you're going: both systems do deal with "restricting what users can modify in composite structures", so there's overlap in the problem space. I'm just wondering if the problems aren't at different architectural levels.

E.g., When editing a pattern in "Pattern editing" mode, there's an Accordion block inside that is permanently in "pattern editing" mode?

I guess if "content only" could permanently be applied to section, but then you'd inevitably run into exceptions for blocks that want to be "special".

For this PR specifically, it also addresses technical issues that pattern editing doesn't solve, particularly around templateLock inheritance bugs and misleading UI affordances, though @danr can check my assumptions here.

Anyway, I'm just assuming a lot, curious to hear what others think.

@youknowriad

Copy link
Copy Markdown
Contributor

If I'm reading properly, you're saying that (correct me if I'm wrong)

  • composite mode is a "developer" way to build a block with a restricted content and only allow some areas to be "blocks" selectable/editable...
  • pattern editing (content only) is a "user" way to do the same: Build a block (the main goal of pattern editing / simple editing / content only is to treat the whole pattern as a unit/block) that is composed of other blocks (inner blocks) but flatten the tree (only certain areas and styles are editable).

For me that is very similar, and I wonder if this just indicates that we're lacking "tools/settings" on the pattern building UI to achieve the outcome that you're reaching for with this "composite mode".

At least that's how I see it conceptually.

I do acknowledge that a developer way to "compose" a block out of "multiple blocks" or "multiple block areas" separated by random content has been requested for some time and could be addressed API wise but I feel like a decision has been made a long time ago that "patterns" are the solution to that. Now, I may be wrong but I'll defer to @mtias here.

@ramonjd

ramonjd commented Dec 10, 2025

Copy link
Copy Markdown
Member

composite mode is a "developer"
pattern editing (content only) is a "user" way to do the same:

In a way, but not exactly. Yes, composite block is for developers to build blocks with the exact restrictions they require universally. For me it's a bit more than being about simplifying the editing experience. So a user would enter a block in the editor independent of any pattern, and that block's UX is constrained in the way the developer wants, not how pattern editing mode dictates.

That's just me. I know you have more context on these things so I trust your opinion!

For me that is very similar, and I wonder if this just indicates that we're lacking "tools/settings" on the pattern building UI to achieve the outcome that you're reaching for with this "composite mode".

Good question. I'm not sure, maybe it's even something we don't need to solve right now.

@andrewserong

Copy link
Copy Markdown
Contributor

Now, I may be wrong but I'll defer to @mtias here.

From memory I think Matías might have proposed the composite block idea originally. It does serve a similar goal of simplification (to the user) as pattern/content editing, but locked into how blocks are developed, rather than how they're composed in patterns. I'm aware I'm basically just paraphrasing how @ramonjd already put it above (#73510 (comment)) 😄

I agree to be cautious about introducing new APIs, but in this case, it does feel like a pretty common use case. Beyond the accordion blocks in core, I'm aware that there are plugins looking for a feature like this (e.g. in the Jetpack plugin, a composite blocks feature could help simplify the UI for form fields that are constructed as a controlled set of blocks out of a label and an input block, for example). In these kinds of cases, I believe there should be an API to handle this, rather than depending on templateLock, for the reasons this PR proposes.

@talldan

talldan commented Dec 11, 2025

Copy link
Copy Markdown
Contributor Author

It could use the pattern editing concept, but I think there's quite a few modifications that would be required to the regular experience:

  • When a block is identified as a section, the contentOnly treatment is usually applied to the entire block tree. For accordion, the Accordion Panel's children shouldn't have contentOnly applied. There would need to be a way to make this block's children freely editable (I guess this is a bit like the Post Content block when 'Show Template' is used in a post).
  • The 'Edit Section' button should never be shown for an Accordion Item.
  • I think the block developers want users to have full access to the design tools for Accordion Header and Panel. contentOnly usually doesn't allow this, so we need an alternative

There's currently no way to make a block a section from its config, so this may require a new API anyway (though we could also use that API on template parts / synced patterns).

I think it also depends on the priority of those bugs, whether they should be fixed sooner or we're happy to wait for these features to be built.

@talldan

talldan commented Jan 5, 2026

Copy link
Copy Markdown
Contributor Author

Closing the PR as there seems to be disagreement, and this problem area is not where my focus is right now.

@talldan talldan closed this Jan 5, 2026
@talldan
talldan deleted the experiment/accordion-composite-blocks branch January 5, 2026 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Block] Accordion Affects the Accordion Block [Type] Enhancement A suggestion for improvement.

5 participants