diff --git a/packages/block-library/src/details/edit.js b/packages/block-library/src/details/edit.js index 693e0fb310add0..1205b8fa099c9c 100644 --- a/packages/block-library/src/details/edit.js +++ b/packages/block-library/src/details/edit.js @@ -6,20 +6,26 @@ import { useBlockProps, useInnerBlocksProps, InspectorControls, + store as blockEditorStore, } from '@wordpress/block-editor'; import { TextControl, ToggleControl, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, + privateApis as componentsPrivateApis, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { useState } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { useToolsPanelDropdownMenuProps } from '../utils/hooks'; +import { unlock } from '../lock-unlock'; + +const { withIgnoreIMEEvents } = unlock( componentsPrivateApis ); const TEMPLATE = [ [ @@ -30,7 +36,7 @@ const TEMPLATE = [ ], ]; -function DetailsEdit( { attributes, setAttributes } ) { +function DetailsEdit( { attributes, setAttributes, clientId } ) { const { name, showContent, summary, allowedBlocks, placeholder } = attributes; const blockProps = useBlockProps(); @@ -42,6 +48,27 @@ function DetailsEdit( { attributes, setAttributes } ) { const [ isOpen, setIsOpen ] = useState( showContent ); const dropdownMenuProps = useToolsPanelDropdownMenuProps(); + // Check if the inner blocks are selected. + const hasSelectedInnerBlock = useSelect( + ( select ) => + select( blockEditorStore ).hasSelectedInnerBlock( clientId, true ), + [ clientId ] + ); + + const handleSummaryKeyDown = ( event ) => { + if ( event.key === 'Enter' && ! event.shiftKey ) { + setIsOpen( ( prevIsOpen ) => ! prevIsOpen ); + event.preventDefault(); + } + }; + + // Prevent spacebar from toggling
while typing. + const handleSummaryKeyUp = ( event ) => { + if ( event.key === ' ' ) { + event.preventDefault(); + } + }; + return ( <> @@ -93,13 +120,18 @@ function DetailsEdit( { attributes, setAttributes } ) {
setIsOpen( event.target.open ) } > - + { + test.beforeEach( async ( { admin } ) => { + await admin.createNewPost(); + } ); + + test( 'can toggle hidden blocks by pressing enter', async ( { + editor, + page, + } ) => { + // Insert a details block with empty inner blocks. + await editor.insertBlock( { + name: 'core/details', + attributes: { + summary: 'Details summary', + }, + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + content: 'Details content', + }, + }, + ], + } ); + + // Open the details block. + await page.keyboard.press( 'Enter' ); + + // The inner block should be visible. + await expect( + editor.canvas.getByRole( 'document', { name: 'Block: Paragraph' } ) + ).toContainText( 'Details content' ); + + // Close the details block. + await page.keyboard.press( 'Enter' ); + + // The inner block should be hidden. + await expect( + editor.canvas.getByRole( 'document', { name: 'Block: Paragraph' } ) + ).toBeHidden(); + } ); + + test( 'can create a multiline summary with Shift+Enter', async ( { + editor, + page, + } ) => { + // Insert a details block. + await editor.insertBlock( { + name: 'core/details', + } ); + + const summary = editor.canvas.getByRole( 'textbox', { + name: 'Write summary', + } ); + + // Add a multiline summary. + await summary.type( 'First line' ); + await page.keyboard.press( 'Shift+Enter' ); + await summary.type( 'Second line' ); + + // Verify the summary is multiline. + await expect( summary ).toHaveText( 'First line\nSecond line', { + useInnerText: true, + } ); + } ); + + test( 'typing space in summary rich-text should not toggle details', async ( { + editor, + } ) => { + // Insert a details block. + await editor.insertBlock( { + name: 'core/details', + } ); + + const summary = editor.canvas.getByRole( 'textbox', { + name: 'Write summary', + } ); + + // Type space in the summary rich-text. + await summary.type( ' ' ); + + // Verify the details block is not toggled. + await expect( + editor.canvas.getByRole( 'document', { name: 'Empty block' } ) + ).toBeHidden(); + } ); + + test( 'selecting hidden blocks in list view expands details and focuses content', async ( { + editor, + page, + pageUtils, + } ) => { + // Insert a details block. + await editor.insertBlock( { + name: 'core/details', + attributes: { + summary: 'Details summary', + }, + innerBlocks: [ + { + name: 'core/paragraph', + attributes: { + content: 'Details content', + }, + }, + ], + } ); + + const listView = page.getByRole( 'treegrid', { + name: 'Block navigation structure', + } ); + + // Open the list view. + await pageUtils.pressKeys( 'access+o' ); + + // Verify inner blocks appear in the list view. + await page.keyboard.press( 'ArrowRight' ); + await expect( + listView.getByRole( 'link', { + name: 'Paragraph', + } ) + ).toBeVisible(); + + // Verify the first inner block in the list view is focused. + await page.keyboard.press( 'ArrowDown' ); + await expect( + listView.getByRole( 'link', { + name: 'Paragraph', + } ) + ).toBeFocused(); + + // Verify the first inner block in the editor canvas is focused. + await page.keyboard.press( 'Enter' ); + await expect( + editor.canvas.getByRole( 'document', { name: 'Block: Paragraph' } ) + ).toBeFocused(); + } ); +} );