diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js index e0de34cf2280e2..65b58ef91fd42c 100644 --- a/packages/block-editor/src/components/global-styles/hooks.js +++ b/packages/block-editor/src/components/global-styles/hooks.js @@ -76,6 +76,7 @@ const VALID_SETTINGS = [ 'typography.fontWeight', 'typography.letterSpacing', 'typography.lineHeight', + 'typography.textAlign', 'typography.textColumns', 'typography.textDecoration', 'typography.textTransform', @@ -372,8 +373,13 @@ export function useSettingsForBlockElement( ? updatedSettings.shadow : false; + // Text alignment is only available for blocks. + if ( element ) { + updatedSettings.typography.textAlign = false; + } + return updatedSettings; - }, [ parentSettings, supportedStyles, supports ] ); + }, [ parentSettings, supportedStyles, supports, element ] ); } export function useColorsPerOrigin( settings ) { diff --git a/packages/block-editor/src/components/global-styles/typography-panel.js b/packages/block-editor/src/components/global-styles/typography-panel.js index 76836c775bb807..98a4c92954b026 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -18,6 +18,7 @@ import FontFamilyControl from '../font-family'; import FontAppearanceControl from '../font-appearance-control'; import LineHeightControl from '../line-height-control'; import LetterSpacingControl from '../letter-spacing-control'; +import TextAlignmentControl from '../text-alignment-control'; import TextTransformControl from '../text-transform-control'; import TextDecorationControl from '../text-decoration-control'; import WritingModeControl from '../writing-mode-control'; @@ -32,6 +33,7 @@ export function useHasTypographyPanel( settings ) { const hasLineHeight = useHasLineHeightControl( settings ); const hasFontAppearance = useHasAppearanceControl( settings ); const hasLetterSpacing = useHasLetterSpacingControl( settings ); + const hasTextAlign = useHasTextAlignmentControl( settings ); const hasTextTransform = useHasTextTransformControl( settings ); const hasTextDecoration = useHasTextDecorationControl( settings ); const hasWritingMode = useHasWritingModeControl( settings ); @@ -43,6 +45,7 @@ export function useHasTypographyPanel( settings ) { hasLineHeight || hasFontAppearance || hasLetterSpacing || + hasTextAlign || hasTextTransform || hasFontSize || hasTextDecoration || @@ -91,6 +94,10 @@ function useHasTextTransformControl( settings ) { return settings?.typography?.textTransform; } +function useHasTextAlignmentControl( settings ) { + return settings?.typography?.textAlign; +} + function useHasTextDecorationControl( settings ) { return settings?.typography?.textDecoration; } @@ -150,6 +157,7 @@ const DEFAULT_CONTROLS = { fontAppearance: true, lineHeight: true, letterSpacing: true, + textAlign: true, textTransform: true, textDecoration: true, writingMode: true, @@ -165,6 +173,13 @@ export default function TypographyPanel( { panelId, defaultControls = DEFAULT_CONTROLS, } ) { + // If paneId has a value, it means this panel will be rendered inside + // the block sidebar. The text alignment UI for individual blocks is rendered + // in the block toolbar, so disable support if it's not a global style. + if ( panelId ) { + settings.typography.textAlign = false; + } + const decodeValue = ( rawValue ) => getValueFromVariable( { settings }, '', rawValue ); @@ -334,6 +349,22 @@ export default function TypographyPanel( { const hasWritingMode = () => !! value?.typography?.writingMode; const resetWritingMode = () => setWritingMode( undefined ); + // Text Alignment + const hasTextAlignmentControl = useHasTextAlignmentControl( settings ); + + const textAlign = decodeValue( inheritedValue?.typography?.textAlign ); + const setTextAlign = ( newValue ) => { + onChange( + setImmutably( + value, + [ 'typography', 'textAlign' ], + newValue || undefined + ) + ); + }; + const hasTextAlign = () => !! value?.typography?.textAlign; + const resetTextAlign = () => setTextAlign( undefined ); + const resetAllFilter = useCallback( ( previousValue ) => { return { ...previousValue, @@ -514,6 +545,22 @@ export default function TypographyPanel( { /> ) } + { hasTextAlignmentControl && ( + + + + ) } ); } diff --git a/phpunit/class-wp-theme-json-test.php b/phpunit/class-wp-theme-json-test.php index 00799b7ba0b478..22058a37d1affc 100644 --- a/phpunit/class-wp-theme-json-test.php +++ b/phpunit/class-wp-theme-json-test.php @@ -503,6 +503,11 @@ public function test_get_stylesheet() { ), ), ), + 'core/media-text' => array( + 'typography' => array( + 'textAlign' => 'center', + ), + ), 'core/post-date' => array( 'color' => array( 'text' => '#123456', @@ -547,7 +552,7 @@ public function test_get_stylesheet() { ); $variables = ':root{--wp--preset--color--grey: grey;--wp--preset--gradient--custom-gradient: linear-gradient(135deg,rgba(0,0,0) 0%,rgb(0,0,0) 100%);--wp--preset--font-size--small: 14px;--wp--preset--font-size--big: 41px;--wp--preset--font-family--arial: Arial, serif;}.wp-block-group{--wp--custom--base-font: 16;--wp--custom--line-height--small: 1.2;--wp--custom--line-height--medium: 1.4;--wp--custom--line-height--large: 1.8;}'; - $styles = static::$base_styles . ':where(body){color: var(--wp--preset--color--grey);}:where(a:where(:not(.wp-element-button))){background-color: #333;color: #111;}:where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:where(.wp-block-heading){color: #123456;}:where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:where(.wp-block-post-date){color: #123456;}:where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:where(.wp-block-post-excerpt){column-count: 2;}:where(.wp-block-image){margin-bottom: 30px;}:where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; + $styles = static::$base_styles . ':where(body){color: var(--wp--preset--color--grey);}:where(a:where(:not(.wp-element-button))){background-color: #333;color: #111;}:where(.wp-element-button, .wp-block-button__link){box-shadow: 10px 10px 5px 0px rgba(0,0,0,0.66);}:where(.wp-block-cover){min-height: unset;aspect-ratio: 16/9;}:where(.wp-block-group){background: var(--wp--preset--gradient--custom-gradient);border-radius: 10px;min-height: 50vh;padding: 24px;}:where(.wp-block-group a:where(:not(.wp-element-button))){color: #111;}:where(.wp-block-heading){color: #123456;}:where(.wp-block-heading a:where(:not(.wp-element-button))){background-color: #333;color: #111;font-size: 60px;}:where(.wp-block-media-text){text-align: center;}:where(.wp-block-post-date){color: #123456;}:where(.wp-block-post-date a:where(:not(.wp-element-button))){background-color: #777;color: #555;}:where(.wp-block-post-excerpt){column-count: 2;}:where(.wp-block-image){margin-bottom: 30px;}:where(.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder){border-top-left-radius: 10px;border-bottom-right-radius: 1em;}:where(.wp-block-image img, .wp-block-image .components-placeholder){filter: var(--wp--preset--duotone--custom-duotone);}'; $presets = '.has-grey-color{color: var(--wp--preset--color--grey) !important;}.has-grey-background-color{background-color: var(--wp--preset--color--grey) !important;}.has-grey-border-color{border-color: var(--wp--preset--color--grey) !important;}.has-custom-gradient-gradient-background{background: var(--wp--preset--gradient--custom-gradient) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-big-font-size{font-size: var(--wp--preset--font-size--big) !important;}.has-arial-font-family{font-family: var(--wp--preset--font-family--arial) !important;}'; $all = $variables . $styles . $presets;