Skip to content
Closed
29 changes: 20 additions & 9 deletions packages/block-editor/src/components/block-controls/fill.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
__experimentalStyleProvider as StyleProvider,
ToolbarGroup,
} from '@wordpress/components';
import { Children } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -21,29 +22,39 @@ export default function BlockControlsFill( {
group,
__experimentalShareWithChildBlocks
);

if ( ! Fill ) {
return null;
}

const innerMarkup = (
<>
{ group === 'default' && <ToolbarGroup controls={ controls } /> }
{ children }
</>
);

return (
<StyleProvider document={ document }>
<Fill>
{ ( fillProps ) => {
// `fillProps.forwardedContext` is an array of context provider entries, provided by slot,
// that should wrap the fill markup.
const { forwardedContext = [] } = fillProps;
const { forwardedContext = [], shouldRender = () => true } =
fillProps;

// Filter children based on shouldRender callback
const childrenArray = Children.toArray( children );
const filteredChildren =
childrenArray.filter( shouldRender );

const filteredMarkup = (
<>
{ group === 'default' && (
<ToolbarGroup controls={ controls } />
) }
{ filteredChildren }
</>
);

return forwardedContext.reduce(
( inner, [ Provider, props ] ) => (
<Provider { ...props }>{ inner }</Provider>
),
innerMarkup
filteredMarkup
);
} }
</Fill>
Expand Down
15 changes: 14 additions & 1 deletion packages/block-editor/src/components/block-controls/slot.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,33 @@ import warning from '@wordpress/warning';
*/
import groups from './groups';
import { unlock } from '../../lock-unlock';
import { useBlockEditingMode } from '../block-editing-mode';

const { ComponentsContext } = unlock( privateApis );

export default function BlockControlsSlot( { group = 'default', ...props } ) {
const toolbarState = useContext( ToolbarContext );
const contextState = useContext( ComponentsContext );

// Get the block editing mode for the current block
const blockEditingMode = useBlockEditingMode();

const fillProps = useMemo(
() => ( {
forwardedContext: [
[ ToolbarContext.Provider, { value: toolbarState } ],
[ ComponentsContext.Provider, { value: contextState } ],
],
shouldRender: ( element ) => {
// In content-only mode, only render elements with category="content"
if ( blockEditingMode === 'contentOnly' ) {
return element?.props?.category === 'content';
}
// In other modes, render all elements
return true;
},
} ),
[ toolbarState, contextState ]
[ toolbarState, contextState, blockEditingMode ]
);

const slotFill = groups[ group ];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const FormatToolbarContainer = ( { inline, editableContentElement } ) => {
// Render regular toolbar.
return (
<BlockControls group="inline">
<FormatToolbar />
<FormatToolbar category="content" />
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.

Note the approach in #71058 for restricting formatting controls. If your approach is better and we can have one unified mechanism then we'd need to revert that.

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.

I think they work alongside each other. This category="content" says "we want this component to show when in contentOnly mode" and yours is filtering which format controls should be shown within it.

</BlockControls>
);
};
Expand Down
31 changes: 14 additions & 17 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,8 +714,7 @@ export default function Image( {
const mediaReplaceFlow = isSingleSelected &&
! isEditingImage &&
! lockUrlControls && (
// For contentOnly mode, put this button in its own area so it has borders around it.
<BlockControls group={ isContentOnlyMode ? 'inline' : 'other' }>
<BlockControls group="other">
<MediaReplaceFlow
mediaId={ id }
mediaURL={ url }
Expand All @@ -726,6 +725,7 @@ export default function Image( {
onError={ onUploadError }
name={ ! url ? __( 'Add image' ) : __( 'Replace' ) }
onReset={ () => onSelectImage( undefined ) }
category="content"
Copy link
Copy Markdown
Contributor

@getdave getdave Sep 3, 2025

Choose a reason for hiding this comment

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

Obviously we can make this a private API for now via Symbols, but don't bother until we've got more feedback.

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.

Yeah, I'm not worried about that specific quite yet. I want to see about the overall approach first and then get into the details.

/>
</BlockControls>
);
Expand Down Expand Up @@ -777,21 +777,18 @@ export default function Image( {
</ToolbarGroup>
</BlockControls>
) }
{ isContentOnlyMode && (
// Add some extra controls for content attributes when content only mode is active.
// With content only mode active, the inspector is hidden, so users need another way
// to edit these attributes.
<BlockControls group="block">
<ContentOnlyControls
attributes={ attributes }
setAttributes={ setAttributes }
lockAltControls={ lockAltControls }
lockAltControlsMessage={ lockAltControlsMessage }
lockTitleControls={ lockTitleControls }
lockTitleControlsMessage={ lockTitleControlsMessage }
/>
</BlockControls>
) }
{ /* Content-only controls - automatically filtered by category="content" */ }
<BlockControls group="block">
<ContentOnlyControls
category="content"
attributes={ attributes }
setAttributes={ setAttributes }
lockAltControls={ lockAltControls }
lockAltControlsMessage={ lockAltControlsMessage }
lockTitleControls={ lockTitleControls }
lockTitleControlsMessage={ lockTitleControlsMessage }
/>
</BlockControls>
<InspectorControls>
<ToolsPanel
label={ __( 'Settings' ) }
Expand Down
42 changes: 19 additions & 23 deletions packages/block-library/src/paragraph/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
RichText,
useBlockProps,
useSettings,
useBlockEditingMode,
} from '@wordpress/block-editor';
import { getBlockSupport } from '@wordpress/blocks';
import { formatLtr } from '@wordpress/icons';
Expand Down Expand Up @@ -117,31 +116,28 @@ function ParagraphBlock( {
} ),
style: { direction },
} );
const blockEditingMode = useBlockEditingMode();

return (
<>
{ blockEditingMode === 'default' && (
<BlockControls group="block">
<AlignmentControl
value={ align }
onChange={ ( newAlign ) =>
setAttributes( {
align: newAlign,
dropCap: hasDropCapDisabled( newAlign )
? false
: dropCap,
} )
}
/>
<ParagraphRTLControl
direction={ direction }
setDirection={ ( newDirection ) =>
setAttributes( { direction: newDirection } )
}
/>
</BlockControls>
) }
<BlockControls group="block">
<AlignmentControl
value={ align }
onChange={ ( newAlign ) =>
setAttributes( {
align: newAlign,
dropCap: hasDropCapDisabled( newAlign )
? false
: dropCap,
} )
}
/>
<ParagraphRTLControl
direction={ direction }
setDirection={ ( newDirection ) =>
setAttributes( { direction: newDirection } )
}
/>
</BlockControls>
{ isSingleSelected && (
<DropCapControl
name={ name }
Expand Down
Loading