Skip to content
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a71f03c
Image block: Add 'Mark as decorative' toggle
SteveJonesDev Apr 23, 2026
57eadef
Image block: Update alt text handling for decorative images
SteveJonesDev May 7, 2026
aa70418
Image block: Set default value for 'isDecorative' attribute in ImageEdit
SteveJonesDev May 7, 2026
e1459cd
Image block: Add 'isDecorative' attribute to core/image block attributes
SteveJonesDev May 7, 2026
16a68da
Add: confirmation dialog for marking images as decorative
SteveJonesDev May 7, 2026
5aeb643
Merge branch 'trunk' into add/image-block-decorative-toggle
SteveJonesDev May 7, 2026
6e6978f
Merge branch 'trunk' into add/image-block-decorative-toggle
SteveJonesDev May 11, 2026
074c30b
Image block: Hide caption when in read-only mode and empty
SteveJonesDev May 11, 2026
e0848a9
Image block: Set default value for 'isDecorative' attribute to false
SteveJonesDev May 11, 2026
ede7a94
Image block: Set 'isDecorative' attribute to false when enabling ligh…
SteveJonesDev May 11, 2026
1d14bb3
Image block: Remove default 'isDecorative' attribute setting in Image…
SteveJonesDev May 11, 2026
4df01e2
Image block: Add 'isDecorative' attribute with default value false to…
SteveJonesDev May 11, 2026
b21abad
Image block: Conditionally render alternative text input based on 'is…
SteveJonesDev May 13, 2026
4521859
Image block: Remove 'isDecorative' parameter from getAltHelp function…
SteveJonesDev May 13, 2026
8d9d315
Image block: handle caption logic in the image block. Revert changes …
SteveJonesDev May 13, 2026
57343e0
Image block: Replace ToggleControl with CheckboxControl for decorativ…
SteveJonesDev May 13, 2026
264fb68
Image block: Add 'isDecorative' field to inspector controls and updat…
SteveJonesDev May 14, 2026
f6d7341
Image block: Simplify decorative image handling by removing confirmat…
SteveJonesDev May 14, 2026
feaf9a2
Image block: Remoded getAltHelp and inlined the ternary directly into…
SteveJonesDev May 18, 2026
283e469
Image block: Restored the fragment wrapper is back to match the origi…
SteveJonesDev May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ Insert an image to make a visual statement. ([Source](https://github.com/WordPre
- **Name:** core/image
- **Category:** media
- **Supports:** align (center, full, left, right, wide), anchor, color (~~background~~, ~~text~~), filter (duotone), interactivity, shadow, spacing (margin)
- **Attributes:** alt, aspectRatio, blob, caption, focalPoint, height, href, id, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width
- **Attributes:** alt, aspectRatio, blob, caption, focalPoint, height, href, id, isDecorative, lightbox, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width

## Latest Comments

Expand Down
4 changes: 4 additions & 0 deletions packages/block-library/src/image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@
"source": "attribute",
"selector": "figure > a",
"attribute": "target"
},
"isDecorative": {
"type": "boolean",
"default": false
}
},
"supports": {
Expand Down
194 changes: 142 additions & 52 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
Spinner,
TextareaControl,
TextControl,
CheckboxControl,
ToolbarButton,
ToolbarGroup,
__experimentalConfirmDialog as ConfirmDialog,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalUseCustomUnits as useCustomUnits,
Expand All @@ -29,6 +31,7 @@ import { useSelect, useDispatch } from '@wordpress/data';
import {
BlockControls,
InspectorControls,
RichText,
__experimentalImageURLInputUI as ImageURLInputUI,
MediaReplaceFlow,
store as blockEditorStore,
Expand Down Expand Up @@ -261,6 +264,26 @@ function ContentOnlyControls( {
);
}

function getAltHelp( { lockAltControls, lockAltControlsMessage } ) {
if ( lockAltControls ) {
return <>{ lockAltControlsMessage }</>;
}
return (
<>
<ExternalLink
href={
// translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.
__(
'https://www.w3.org/WAI/tutorials/images/decision-tree/'
)
}
>
{ __( 'Describe the purpose of the image.' ) }
</ExternalLink>
</>
);
}

export default function Image( {
temporaryURL,
isSideloading,
Expand Down Expand Up @@ -297,6 +320,8 @@ export default function Image( {
sizeSlug,
lightbox,
metadata,
isDecorative,
caption,
} = attributes;
const [ imageElement, setImageElement ] = useState();
const [ resizeDelta, setResizeDelta ] = useState( null );
Expand Down Expand Up @@ -525,6 +550,7 @@ export default function Image( {
if ( enable && ! lightboxSetting?.enabled ) {
setAttributes( {
lightbox: { enabled: true },
isDecorative: false,
} );
} else if ( ! enable && lightboxSetting?.enabled ) {
setAttributes( {
Expand Down Expand Up @@ -563,6 +589,34 @@ export default function Image( {
setAttributes( { alt: newAlt } );
}

const [ isDecorativeConfirmVisible, setIsDecorativeConfirmVisible ] =
useState( false );

function applyDecorative() {
setAttributes( {
isDecorative: true,
alt: '',
caption: undefined,
href: undefined,
linkDestination: undefined,
linkTarget: undefined,
rel: undefined,
} );
}

function updateIsDecorative( value ) {
if ( ! value ) {
setAttributes( { isDecorative: false } );
return;
}
const hasDataToLose = alt || ! RichText.isEmpty( caption ) || href;
if ( hasDataToLose ) {
setIsDecorativeConfirmVisible( true );
} else {
applyDecorative();
}
}

const imperativeFocalPointPreview = ( value ) => {
if ( imageElement ) {
imageElement.style.setProperty(
Expand Down Expand Up @@ -806,7 +860,8 @@ export default function Image( {
isSingleSelected &&
! isEditingImage &&
! lockHrefControls &&
! lockUrlControls;
! lockUrlControls &&
! isDecorative;

const showCoverControls =
isSingleSelected && canInsertCover && ! isContentOnlyMode;
Expand Down Expand Up @@ -914,7 +969,10 @@ export default function Image( {
<InspectorControls group="content">
<ToolsPanel
label={ __( 'Media' ) }
resetAll={ () => onSelectImage( undefined ) }
resetAll={ () => {
onSelectImage( undefined );
setAttributes( { isDecorative: false } );
} }
dropdownMenuProps={ dropdownMenuProps }
>
{ ! lockUrlControls && (
Expand Down Expand Up @@ -944,45 +1002,48 @@ export default function Image( {
/>
</ToolsPanelItem>
) }
<ToolsPanelItem
label={ __( 'Alternative text' ) }
isShownByDefault
hasValue={ () => !! alt }
onDeselect={ () =>
setAttributes( { alt: undefined } )
}
>
<TextareaControl
{ ! isDecorative && (
<ToolsPanelItem
label={ __( 'Alternative text' ) }
value={ alt || '' }
onChange={ updateAlt }
readOnly={ lockAltControls }
help={
lockAltControls ? (
<>{ lockAltControlsMessage }</>
) : (
<>
<ExternalLink
href={
// translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.
__(
'https://www.w3.org/WAI/tutorials/images/decision-tree/'
)
}
>
{ __(
'Describe the purpose of the image.'
) }
</ExternalLink>
<br />
{ __(
'Leave empty if decorative.'
) }
</>
)
isShownByDefault
hasValue={ () => !! alt }
onDeselect={ () =>
setAttributes( { alt: undefined } )
}
/>
</ToolsPanelItem>
>
<TextareaControl
label={ __( 'Alternative text' ) }
value={ alt || '' }
onChange={ updateAlt }
readOnly={ lockAltControls }
help={ getAltHelp( {
Comment thread
SteveJonesDev marked this conversation as resolved.
Resolved
lockAltControls,
lockAltControlsMessage,
} ) }
/>
</ToolsPanelItem>
) }

{ ! lockAltControls && ! lightboxChecked && (
<ToolsPanelItem
label={ __( 'Mark as decorative' ) }
isShownByDefault
hasValue={ () => !! isDecorative }
onDeselect={ () =>
setAttributes( { isDecorative: false } )
}
>
<CheckboxControl
__nextHasNoMarginBottom
label={ __( 'Mark as decorative' ) }
checked={ !! isDecorative }
onChange={ updateIsDecorative }
help={ __(
'Hidden from assistive technologies.'
) }
/>
</ToolsPanelItem>
) }
</ToolsPanel>
</InspectorControls>
) }
Expand Down Expand Up @@ -1072,7 +1133,17 @@ export default function Image( {
const filename = getFilename( url );
let defaultedAlt;

if ( alt ) {
if ( isDecorative ) {
defaultedAlt = filename
? sprintf(
/* translators: %s: file name */
__(
'This image has been marked as decorative; its file name is %s'
),
filename
)
: __( 'This image has been marked as decorative.' );
} else if ( alt ) {
defaultedAlt = alt;
} else if ( filename ) {
defaultedAlt = sprintf(
Expand Down Expand Up @@ -1327,18 +1398,37 @@ export default function Image( {
{ img }
{ resizableBox }

<Caption
attributes={ attributes }
setAttributes={ setAttributes }
isSelected={ isSingleSelected }
insertBlocksAfter={ insertBlocksAfter }
label={ __( 'Image caption text' ) }
showToolbarButton={
isSingleSelected &&
( hasNonContentControls || isContentOnlyMode ) &&
! hideCaptionControls
}
/>
{ ! isDecorative && (
<Caption
attributes={ attributes }
setAttributes={ setAttributes }
isSelected={ isSingleSelected }
insertBlocksAfter={ insertBlocksAfter }
label={ __( 'Image caption text' ) }
showToolbarButton={
isSingleSelected &&
( hasNonContentControls || isContentOnlyMode ) &&
! hideCaptionControls
}
/>
) }

{ isDecorativeConfirmVisible && (
<ConfirmDialog
isOpen
onConfirm={ () => {
setIsDecorativeConfirmVisible( false );
applyDecorative();
} }
onCancel={ () => setIsDecorativeConfirmVisible( false ) }
confirmButtonText={ __( 'Mark as decorative' ) }
size="medium"
>
{ __(
'Marking this image as decorative will remove any alt text, caption, and links. Continue?'
) }
</ConfirmDialog>
) }
</>
);
}
2 changes: 2 additions & 0 deletions packages/block-library/src/image/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default function save( { attributes } ) {
linkTarget,
sizeSlug,
title,
isDecorative,
metadata: { bindings = {} } = {},
} = attributes;

Expand Down Expand Up @@ -78,6 +79,7 @@ export default function save( { attributes } ) {
height,
} }
title={ title }
role={ isDecorative ? 'none' : undefined }
/>
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"caption": "",
"id": 1421,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
},
Expand All @@ -40,7 +41,8 @@
"caption": "",
"id": 1440,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
}
Expand Down
6 changes: 4 additions & 2 deletions test/integration/fixtures/blocks/core__gallery.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"caption": "",
"id": 1421,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
},
Expand All @@ -40,7 +41,8 @@
"caption": "",
"id": 1440,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
}
Expand Down
6 changes: 4 additions & 2 deletions test/integration/fixtures/blocks/core__gallery__columns.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"caption": "",
"id": 1421,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
},
Expand All @@ -40,7 +41,8 @@
"caption": "",
"id": 1440,
"sizeSlug": "large",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"url": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==",
"alt": "title",
"caption": "",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
},
Expand All @@ -28,7 +29,8 @@
"url": "data:image/jpeg;base64,/9j/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/yQALCAABAAEBAREA/8wABgAQEAX/2gAIAQEAAD8A0s8g/9k=",
"alt": "title",
"caption": "",
"linkDestination": "none"
"linkDestination": "none",
"isDecorative": false
},
"innerBlocks": []
}
Expand Down
Loading
Loading