Skip to content

Commit

Permalink
Add "Image Title Attribute" as an editable attribute on the image blo…
Browse files Browse the repository at this point in the history
…ck (#11070)

* Add a title to the image block advanced settings
This is used to set the actual title attribute in the html
of the output, and is completely separate from the image's
title in the media library

* Update help text on image title attribute to link to w3.org title description

* Uopdate title attribute help text to not all be a link

* Remove line break in title attribute helper text
  • Loading branch information
brentswisher authored and mkaz committed Nov 1, 2019
1 parent 3b19415 commit 680a085
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 73 deletions.
6 changes: 6 additions & 0 deletions packages/block-library/src/image/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
"source": "html",
"selector": "figcaption"
},
"title": {
"type": "string",
"source": "attribute",
"selector": "img",
"attribute": "title"
},
"href": {
"type": "string",
"source": "attribute",
Expand Down
170 changes: 98 additions & 72 deletions packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ import {
BlockControls,
BlockIcon,
InspectorControls,
InspectorAdvancedControls,
MediaPlaceholder,
URLPopover,
RichText,
Expand Down Expand Up @@ -280,6 +281,7 @@ export class ImageEdit extends Component {
this.onSetLinkClass = this.onSetLinkClass.bind( this );
this.onSetLinkRel = this.onSetLinkRel.bind( this );
this.onSetNewTab = this.onSetNewTab.bind( this );
this.onSetTitle = this.onSetTitle.bind( this );
this.getFilename = this.getFilename.bind( this );
this.toggleIsEditing = this.toggleIsEditing.bind( this );
this.onUploadError = this.onUploadError.bind( this );
Expand Down Expand Up @@ -349,6 +351,7 @@ export class ImageEdit extends Component {
url: undefined,
alt: undefined,
id: undefined,
title: undefined,
caption: undefined,
} );
return;
Expand Down Expand Up @@ -443,6 +446,11 @@ export class ImageEdit extends Component {
this.props.setAttributes( { href: value } );
}

onSetTitle( value ) {
// This is the HTML title attribute, separate from the media object title
this.props.setAttributes( { title: value } );
}

onSetLinkClass( value ) {
this.props.setAttributes( { linkClass: value } );
}
Expand Down Expand Up @@ -578,6 +586,7 @@ export class ImageEdit extends Component {
rel,
linkClass,
linkDestination,
title,
width,
height,
linkTarget,
Expand Down Expand Up @@ -687,84 +696,101 @@ export class ImageEdit extends Component {
const imageSizeOptions = this.getImageSizeOptions();

const getInspectorControls = ( imageWidth, imageHeight ) => (
<InspectorControls>
<PanelBody title={ __( 'Image Settings' ) }>
<TextareaControl
label={ __( 'Alt Text (Alternative Text)' ) }
value={ alt }
onChange={ this.updateAlt }
<>
<InspectorControls>
<PanelBody title={ __( 'Image Settings' ) }>
<TextareaControl
label={ __( 'Alt Text (Alternative Text)' ) }
value={ alt }
onChange={ this.updateAlt }
help={
<>
<ExternalLink href="https://www.w3.org/WAI/tutorials/images/decision-tree">
{ __( 'Describe the purpose of the image' ) }
</ExternalLink>
{ __( 'Leave empty if the image is purely decorative.' ) }
</>
}
/>
{ ! isEmpty( imageSizeOptions ) && (
<SelectControl
label={ __( 'Image Size' ) }
value={ sizeSlug }
options={ imageSizeOptions }
onChange={ this.updateImage }
/>
) }
{ isResizable && (
<div className="block-library-image__dimensions">
<p className="block-library-image__dimensions__row">
{ __( 'Image Dimensions' ) }
</p>
<div className="block-library-image__dimensions__row">
<TextControl
type="number"
className="block-library-image__dimensions__width"
label={ __( 'Width' ) }
value={ width || imageWidth || '' }
min={ 1 }
onChange={ this.updateWidth }
/>
<TextControl
type="number"
className="block-library-image__dimensions__height"
label={ __( 'Height' ) }
value={ height || imageHeight || '' }
min={ 1 }
onChange={ this.updateHeight }
/>
</div>
<div className="block-library-image__dimensions__row">
<ButtonGroup aria-label={ __( 'Image Size' ) }>
{ [ 25, 50, 75, 100 ].map( ( scale ) => {
const scaledWidth = Math.round( imageWidth * ( scale / 100 ) );
const scaledHeight = Math.round( imageHeight * ( scale / 100 ) );

const isCurrent = width === scaledWidth && height === scaledHeight;

return (
<Button
key={ scale }
isSmall
isPrimary={ isCurrent }
aria-pressed={ isCurrent }
onClick={ this.updateDimensions( scaledWidth, scaledHeight ) }
>
{ scale }%
</Button>
);
} ) }
</ButtonGroup>
<Button
isSmall
onClick={ this.updateDimensions() }
>
{ __( 'Reset' ) }
</Button>
</div>
</div>
) }
</PanelBody>
</InspectorControls>
<InspectorAdvancedControls>
<TextControl
label={ __( 'Title Attribute' ) }
value={ title || '' }
onChange={ this.onSetTitle }
help={
<>
<ExternalLink href="https://www.w3.org/WAI/tutorials/images/decision-tree">
{ __( 'Describe the purpose of the image' ) }
{ __( 'Describe the role of this image on the page.' ) }
<ExternalLink href="https://www.w3.org/TR/html52/dom.html#the-title-attribute">
{ __( '(Note: many devices and browsers do not display this text.)' ) }
</ExternalLink>
{ __( 'Leave empty if the image is purely decorative.' ) }
</>
}
/>
{ ! isEmpty( imageSizeOptions ) && (
<SelectControl
label={ __( 'Image Size' ) }
value={ sizeSlug }
options={ imageSizeOptions }
onChange={ this.updateImage }
/>
) }
{ isResizable && (
<div className="block-library-image__dimensions">
<p className="block-library-image__dimensions__row">
{ __( 'Image Dimensions' ) }
</p>
<div className="block-library-image__dimensions__row">
<TextControl
type="number"
className="block-library-image__dimensions__width"
label={ __( 'Width' ) }
value={ width || imageWidth || '' }
min={ 1 }
onChange={ this.updateWidth }
/>
<TextControl
type="number"
className="block-library-image__dimensions__height"
label={ __( 'Height' ) }
value={ height || imageHeight || '' }
min={ 1 }
onChange={ this.updateHeight }
/>
</div>
<div className="block-library-image__dimensions__row">
<ButtonGroup aria-label={ __( 'Image Size' ) }>
{ [ 25, 50, 75, 100 ].map( ( scale ) => {
const scaledWidth = Math.round( imageWidth * ( scale / 100 ) );
const scaledHeight = Math.round( imageHeight * ( scale / 100 ) );

const isCurrent = width === scaledWidth && height === scaledHeight;

return (
<Button
key={ scale }
isSmall
isPrimary={ isCurrent }
aria-pressed={ isCurrent }
onClick={ this.updateDimensions( scaledWidth, scaledHeight ) }
>
{ scale }%
</Button>
);
} ) }
</ButtonGroup>
<Button
isSmall
onClick={ this.updateDimensions() }
>
{ __( 'Reset' ) }
</Button>
</div>
</div>
) }
</PanelBody>
</InspectorControls>
</InspectorAdvancedControls>
</>
);

// Disable reason: Each block can be selected by clicking on it
Expand Down
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 @@ -23,6 +23,7 @@ export default function save( { attributes } ) {
id,
linkTarget,
sizeSlug,
title,
} = attributes;

const newRel = isEmpty( rel ) ? undefined : rel;
Expand All @@ -40,6 +41,7 @@ export default function save( { attributes } ) {
className={ id ? `wp-image-${ id }` : null }
width={ width }
height={ height }
title={ title }
/>
);

Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/image/transforms.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function getFirstAnchorAttributeFormHTML( html, attributeName ) {

const imageSchema = {
img: {
attributes: [ 'src', 'alt' ],
attributes: [ 'src', 'alt', 'title' ],
classes: [ 'alignleft', 'aligncenter', 'alignright', 'alignnone', /^wp-image-\d+$/ ],
},
};
Expand Down

0 comments on commit 680a085

Please sign in to comment.