diff --git a/packages/block-library/src/tab-list/edit.js b/packages/block-library/src/tab-list/edit.js index 607150eb89fa8e..7122686537ebfe 100644 --- a/packages/block-library/src/tab-list/edit.js +++ b/packages/block-library/src/tab-list/edit.js @@ -14,6 +14,8 @@ import { useSelect } from '@wordpress/data'; import AddTabToolbarControl from '../tab-panel/add-tab-toolbar-control'; import RemoveTabToolbarControl from '../tab-panel/remove-tab-toolbar-control'; +const TAB_LIST_TEMPLATE = [ [ 'core/tab' ], [ 'core/tab' ] ]; + function Edit( { clientId } ) { const tabsClientId = useSelect( ( select ) => @@ -26,6 +28,7 @@ function Edit( { clientId } ) { const innerBlocksProps = useInnerBlocksProps( blockProps, { allowedBlocks: [ 'core/tab' ], orientation: 'horizontal', + template: TAB_LIST_TEMPLATE, templateLock: false, renderAppender: false, } ); diff --git a/packages/block-library/src/tab-panels/edit.js b/packages/block-library/src/tab-panels/edit.js index 01422a9cc38791..d191ed320becd8 100644 --- a/packages/block-library/src/tab-panels/edit.js +++ b/packages/block-library/src/tab-panels/edit.js @@ -7,6 +7,7 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; +import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -14,7 +15,15 @@ import { useSelect } from '@wordpress/data'; import AddTabToolbarControl from '../tab-panel/add-tab-toolbar-control'; import RemoveTabToolbarControl from '../tab-panel/remove-tab-toolbar-control'; -const TAB_PANELS_TEMPLATE = [ [ 'core/tab-panel', {} ] ]; +/** + * Initial template applied only when the block is first inserted (i.e. when + * inner blocks are empty). templateLock is false, so this is never applied to + * existing blocks that already have tab panels saved. + */ +const TAB_PANELS_TEMPLATE = [ + [ 'core/tab-panel', { label: __( 'Tab' ) } ], + [ 'core/tab-panel', { label: __( 'Tab' ) } ], +]; export default function Edit( { clientId } ) { const blockProps = useBlockProps(); diff --git a/packages/block-library/src/tabs/edit.js b/packages/block-library/src/tabs/edit.js index cfb3fd102a001e..2bf64eaa031477 100644 --- a/packages/block-library/src/tabs/edit.js +++ b/packages/block-library/src/tabs/edit.js @@ -9,7 +9,6 @@ import { } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; import { useMemo, useEffect } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -19,36 +18,19 @@ import useTabListSync from './use-tab-list-sync'; const EMPTY_ARRAY = []; -const TABS_TEMPLATE = [ - [ - 'core/tab-list', - {}, - [ - [ 'core/tab', {} ], - [ 'core/tab', {} ], - ], - ], - [ - 'core/tab-panels', - {}, - [ - [ - 'core/tab-panel', - { - label: __( 'Tab' ), - }, - [ [ 'core/paragraph' ] ], - ], - [ - 'core/tab-panel', - { - label: __( 'Tab' ), - }, - [ [ 'core/paragraph' ] ], - ], - ], - ], -]; +/** + * Only the two structural child blocks are specified here — without inner + * block entries for core/tab-list or core/tab-panels. + * + * If inner blocks were included in this template, `synchronizeBlocksWithTemplate` + * (called whenever templateLock === 'all') would recurse into the containers and + * truncate them to the template count, causing data loss when a saved block with + * more than two tabs is re-opened in the editor. + * + * Initial tab/panel creation is delegated to the tab-panels template in + * tab-panels/edit.js (templateLock: false, applied only when empty). + */ +const TABS_TEMPLATE = [ [ 'core/tab-list' ], [ 'core/tab-panels' ] ]; function Edit( { clientId, attributes, setAttributes } ) { const { anchor, activeTabIndex, editorActiveTabIndex } = attributes;