Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions docs/reference-guides/core-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ Prompt visitors to take action with a button-style link. ([Source](https://githu
- **Name:** core/button
- **Category:** design
- **Parent:** core/buttons
- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), shadow (), spacing (padding), splitting, typography (fontSize, lineHeight), ~~alignWide~~, ~~align~~, ~~reusable~~
- **Attributes:** backgroundColor, gradient, linkTarget, placeholder, rel, tagName, text, textAlign, textColor, title, type, url, width
- **Supports:** anchor, color (background, gradients, text), interactivity (clientNavigation), shadow (), spacing (padding), splitting, typography (fontSize, lineHeight, textAlign), ~~alignWide~~, ~~align~~, ~~reusable~~
- **Attributes:** backgroundColor, gradient, linkTarget, placeholder, rel, tagName, text, textColor, title, type, url, width

## Buttons

Expand Down
5 changes: 2 additions & 3 deletions packages/block-library/src/button/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
"type": "string",
"default": "button"
},
"textAlign": {
"type": "string"
},
"url": {
"type": "string",
"source": "attribute",
Expand Down Expand Up @@ -88,6 +85,7 @@
"__experimentalSkipSerialization": [
"fontSize",
"lineHeight",
"textAlign",
"fontFamily",
"fontWeight",
"fontStyle",
Expand All @@ -97,6 +95,7 @@
],
"fontSize": true,
"lineHeight": true,
"textAlign": true,
"__experimentalFontFamily": true,
"__experimentalFontWeight": true,
"__experimentalFontStyle": true,
Expand Down
214 changes: 214 additions & 0 deletions packages/block-library/src/button/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import {
__experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
__experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
__experimentalGetElementClassName,
getTypographyClassesAndStyles,
} from '@wordpress/block-editor';
import { compose } from '@wordpress/compose';

/**
* Internal dependencies
*/
import migrateFontFamily from '../utils/migrate-font-family';
import migrateTextAlign from '../utils/migrate-text-align';

const migrateBorderRadius = ( attributes ) => {
const { borderRadius, ...newAttributes } = attributes;
Expand Down Expand Up @@ -134,6 +136,217 @@ const blockAttributes = {
},
};

const v13 = {
attributes: {
tagName: {
type: 'string',
enum: [ 'a', 'button' ],
default: 'a',
},
type: {
type: 'string',
default: 'button',
},
textAlign: {
type: 'string',
},
url: {
type: 'string',
source: 'attribute',
selector: 'a',
attribute: 'href',
role: 'content',
},
title: {
type: 'string',
source: 'attribute',
selector: 'a,button',
attribute: 'title',
role: 'content',
},
text: {
type: 'rich-text',
source: 'rich-text',
selector: 'a,button',
role: 'content',
},
linkTarget: {
type: 'string',
source: 'attribute',
selector: 'a',
attribute: 'target',
role: 'content',
},
rel: {
type: 'string',
source: 'attribute',
selector: 'a',
attribute: 'rel',
role: 'content',
},
placeholder: {
type: 'string',
},
backgroundColor: {
type: 'string',
},
textColor: {
type: 'string',
},
gradient: {
type: 'string',
},
width: {
type: 'number',
},
},
supports: {
anchor: true,
align: true,
alignWide: false,
color: {
__experimentalSkipSerialization: true,
gradients: true,
__experimentalDefaultControls: {
background: true,
text: true,
},
},
typography: {
__experimentalSkipSerialization: [
'fontSize',
'lineHeight',
'fontFamily',
'fontWeight',
'fontStyle',
'textTransform',
'textDecoration',
'letterSpacing',
],
fontSize: true,
lineHeight: true,
__experimentalFontFamily: true,
__experimentalFontWeight: true,
__experimentalFontStyle: true,
__experimentalTextTransform: true,
__experimentalTextDecoration: true,
__experimentalLetterSpacing: true,
__experimentalWritingMode: true,
__experimentalDefaultControls: {
fontSize: true,
},
},
reusable: false,
shadow: {
__experimentalSkipSerialization: true,
},
spacing: {
__experimentalSkipSerialization: true,
padding: [ 'horizontal', 'vertical' ],
__experimentalDefaultControls: {
padding: true,
},
},
__experimentalBorder: {
color: true,
radius: true,
style: true,
width: true,
__experimentalSkipSerialization: true,
__experimentalDefaultControls: {
color: true,
radius: true,
style: true,
width: true,
},
},
interactivity: {
clientNavigation: true,
},
},
selectors: {
root: '.wp-block-button .wp-block-button__link',
typography: {
writingMode: '.wp-block-button',
},
},
save( { attributes, className } ) {
const {
tagName,
type,
textAlign,
fontSize,
linkTarget,
rel,
style,
text,
title,
url,
width,
} = attributes;

const TagName = tagName || 'a';
const isButtonTag = 'button' === TagName;
const buttonType = type || 'button';
const borderProps = getBorderClassesAndStyles( attributes );
const colorProps = getColorClassesAndStyles( attributes );
const spacingProps = getSpacingClassesAndStyles( attributes );
const shadowProps = getShadowClassesAndStyles( attributes );
const typographyProps = getTypographyClassesAndStyles( attributes );
const buttonClasses = clsx(
'wp-block-button__link',
colorProps.className,
borderProps.className,
typographyProps.className,
{
[ `has-text-align-${ textAlign }` ]: textAlign,
// For backwards compatibility add style that isn't provided via
// block support.
'no-border-radius': style?.border?.radius === 0,
[ `has-custom-font-size` ]:
fontSize || style?.typography?.fontSize,
},
__experimentalGetElementClassName( 'button' )
);
const buttonStyle = {
...borderProps.style,
...colorProps.style,
...spacingProps.style,
...shadowProps.style,
...typographyProps.style,
writingMode: undefined,
};

// The use of a `title` attribute here is soft-deprecated, but still applied
// if it had already been assigned, for the sake of backward-compatibility.
// A title will no longer be assigned for new or updated button block links.

const wrapperClasses = clsx( className, {
[ `has-custom-width wp-block-button__width-${ width }` ]: width,
} );

return (
<div { ...useBlockProps.save( { className: wrapperClasses } ) }>
<RichText.Content
tagName={ TagName }
type={ isButtonTag ? buttonType : null }
className={ buttonClasses }
href={ isButtonTag ? null : url }
title={ title }
style={ buttonStyle }
value={ text }
target={ isButtonTag ? null : linkTarget }
rel={ isButtonTag ? null : rel }
/>
</div>
);
},
isEligible( attributes ) {
return !! attributes.textAlign;
},
migrate: migrateTextAlign,
};

Copy link
Contributor

@youknowriad youknowriad Dec 8, 2025

Choose a reason for hiding this comment

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

A lot of these deprecated versions will become unnecessary after #73116 so I think this is ok for now. and I do think there's a lot of benefits to this unification. (Global Styles support being the important one)

const v12 = {
attributes: {
tagName: {
Expand Down Expand Up @@ -587,6 +800,7 @@ const v10 = {
};

const deprecated = [
v13,
v12,
v11,
v10,
Expand Down
13 changes: 2 additions & 11 deletions packages/block-library/src/button/edit.js
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we need to add a "migration hook" to the edit function (like we did in the paragraph block) for folks that toggle the old attributes dynamically use updateBlockAttributes action.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you.
I added attribute migration based on #73578.
1567bad

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getUpdatedLinkAttributes } from './get-updated-link-attributes';
import removeAnchorTag from '../utils/remove-anchor-tag';
import { useToolsPanelDropdownMenuProps } from '../utils/hooks';
import { unlock } from '../lock-unlock';
import useDeprecatedTextAlign from '../utils/deprecated-text-align-attributes';

/**
* WordPress dependencies
Expand All @@ -34,7 +35,6 @@ import {
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
} from '@wordpress/components';
import {
AlignmentControl,
BlockControls,
InspectorControls,
RichText,
Expand Down Expand Up @@ -186,7 +186,6 @@ function ButtonEdit( props ) {
} = props;
const {
tagName,
textAlign,
linkTarget,
placeholder,
rel,
Expand All @@ -196,6 +195,7 @@ function ButtonEdit( props ) {
width,
metadata,
} = attributes;
useDeprecatedTextAlign( props );

const TagName = tagName || 'a';

Expand Down Expand Up @@ -361,7 +361,6 @@ function ButtonEdit( props ) {
borderProps.className,
typographyProps.className,
{
[ `has-text-align-${ textAlign }` ]: textAlign,
// For backwards compatibility add style that isn't
// provided via block support.
'no-border-radius': style?.border?.radius === 0,
Expand All @@ -385,14 +384,6 @@ function ButtonEdit( props ) {
</div>
{ hasBlockControls && (
<BlockControls group="block">
{ hasNonContentControls && (
<AlignmentControl
value={ textAlign }
onChange={ ( nextAlign ) => {
setAttributes( { textAlign: nextAlign } );
} }
/>
) }
{ isLinkTag && ! lockUrlControls && (
<ToolbarButton
name="link"
Expand Down
2 changes: 0 additions & 2 deletions packages/block-library/src/button/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export default function save( { attributes, className } ) {
const {
tagName,
type,
textAlign,
fontSize,
linkTarget,
rel,
Expand All @@ -46,7 +45,6 @@ export default function save( { attributes, className } ) {
borderProps.className,
typographyProps.className,
{
[ `has-text-align-${ textAlign }` ]: textAlign,
Copy link
Member

Choose a reason for hiding this comment

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

This could be considered a breaking change if themes or extenders rely on this class.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The has-text-align-${ textAlign } class is provided by getTypographyClassesAndStyles, so your markup should remain unchanged.

const textAlignClassName = !! attributes?.style?.typography?.textAlign
? `has-text-align-${ attributes?.style?.typography?.textAlign }`
: '';

// For backwards compatibility add style that isn't provided via
// block support.
'no-border-radius': style?.border?.radius === 0,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* WordPress dependencies
*/
import { useEvent } from '@wordpress/compose';
import { useEffect, useRef } from '@wordpress/element';
import deprecated from '@wordpress/deprecated';
import { useDispatch } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';

/**
* If a plugin is still using the old textAlign attribute, we need to migrate its value
* to the new style.typography.textAlign attribute.
*
* @param {Object} props Block props.
*/
export default function useDeprecatedTextAlign( props ) {
const { name, attributes, setAttributes } = props;
const { textAlign } = attributes;
const { __unstableMarkNextChangeAsNotPersistent } =
useDispatch( blockEditorStore );
const updateStyleWithAlign = useEvent( () => {
deprecated( `textAlign attribute in ${ name }`, {
alternative: 'style.typography.textAlign',
since: '7.0',
} );
__unstableMarkNextChangeAsNotPersistent();
setAttributes( ( currentAttr ) => ( {
style: {
...currentAttr.style,
typography: {
...currentAttr.style?.typography,
textAlign,
},
},
} ) );
} );
const lastUpdatedAlignRef = useRef();
useEffect( () => {
if ( textAlign === lastUpdatedAlignRef.current ) {
return;
}
lastUpdatedAlignRef.current = textAlign;
updateStyleWithAlign();
Copy link
Member

Choose a reason for hiding this comment

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

You could use a new setter method for setAttributes that removes the need for the useEvent hook and for passing style as an effect dependency.

Ref: https://make.wordpress.org/core/2025/11/25/miscellaneous-editor-changes-in-wordpress-6-9/#block-editor-support-passing-updater-function-to-setattributes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you! I tried to adjust it, how does this look? 8a32ace

Copy link
Member

Choose a reason for hiding this comment

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

This is what I had in mind, though it's not a blocker; I just wanted to share.

Example patch

diff --git a/packages/block-library/src/utils/deprecated-text-align-attributes.js b/packages/block-library/src/utils/deprecated-text-align-attributes.js
index 0daa1405bd..4dd591f987 100644
--- a/packages/block-library/src/utils/deprecated-text-align-attributes.js
+++ b/packages/block-library/src/utils/deprecated-text-align-attributes.js
@@ -1,7 +1,6 @@
 /**
  * WordPress dependencies
  */
-import { useEvent } from '@wordpress/compose';
 import { useEffect, useRef } from '@wordpress/element';
 import deprecated from '@wordpress/deprecated';
 import { useDispatch } from '@wordpress/data';
@@ -18,7 +17,12 @@ export default function useDeprecatedTextAlign( props ) {
 	const { textAlign } = attributes;
 	const { __unstableMarkNextChangeAsNotPersistent } =
 		useDispatch( blockEditorStore );
-	const updateStyleWithAlign = useEvent( () => {
+	const lastUpdatedAlignRef = useRef();
+	useEffect( () => {
+		if ( textAlign === lastUpdatedAlignRef.current ) {
+			return;
+		}
+		lastUpdatedAlignRef.current = textAlign;
 		deprecated( `textAlign attribute in ${ name }`, {
 			alternative: 'style.typography.textAlign',
 			since: '7.0',
@@ -33,13 +37,10 @@ export default function useDeprecatedTextAlign( props ) {
 				},
 			},
 		} ) );
-	} );
-	const lastUpdatedAlignRef = useRef();
-	useEffect( () => {
-		if ( textAlign === lastUpdatedAlignRef.current ) {
-			return;
-		}
-		lastUpdatedAlignRef.current = textAlign;
-		updateStyleWithAlign();
-	}, [ textAlign, updateStyleWithAlign ] );
+	}, [
+		__unstableMarkNextChangeAsNotPersistent,
+		name,
+		setAttributes,
+		textAlign,
+	] );
 }

}, [ textAlign, updateStyleWithAlign ] );
}
Loading
Loading