diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index 95f2e047dd0e31..1414d5c67818b7 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -193,6 +193,7 @@ Settings related to typography. | textColumns | Allow users to set the number of text columns. | `boolean` | `false` | | textDecoration | Allow users to set custom text decorations. | `boolean` | `true` | | writingMode | Allow users to set the writing mode. | `boolean` | `false` | +| textOrientation | Allow users to set the textOrientation. | `boolean` | `false` | | textTransform | Allow users to set custom text transforms. | `boolean` | `true` | | dropCap | Enable drop cap. | `boolean` | `true` | | fontSizes | Font size presets for the font size selector. | `[ { name, slug, size, fluid } ]` | | @@ -327,6 +328,7 @@ Typography styles. | textColumns | Sets the `column-count` CSS property. | `string`, `{ ref }` | | textDecoration | Sets the `text-decoration` CSS property. | `string`, `{ ref }` | | writingMode | Sets the `writing-mode` CSS property. | `string`, `{ ref }` | +| textOrientation | Sets the `text-orientation` CSS property. | `string`, `{ ref }` | | textTransform | Sets the `text-transform` CSS property. | `string`, `{ ref }` | --- diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index fa2a7b81e94e21..72491cf07ffb33 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -102,6 +102,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false; $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false; $has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false; + $has_text_orientation_support = $typography_supports['__experimentalTextOrientation'] ?? false; // Whether to skip individual block support features. $should_skip_font_size = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' ); @@ -115,6 +116,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { $should_skip_text_transform = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textTransform' ); $should_skip_letter_spacing = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'letterSpacing' ); $should_skip_writing_mode = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'writingMode' ); + $should_skip_text_orentation = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textOrientation' ); $typography_block_styles = array(); if ( $has_font_size_support && ! $should_skip_font_size ) { @@ -172,6 +174,10 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { if ( $has_writing_mode_support && ! $should_skip_writing_mode && isset( $block_attributes['style']['typography']['writingMode'] ) ) { $typography_block_styles['writingMode'] = $block_attributes['style']['typography']['writingMode'] ?? null; + // Text orientation requires writing mode to be set. + if ( $has_text_orientation_support && ! $should_skip_text_orentation && isset( $block_attributes['style']['typography']['textOrientation'] ) ) { + $typography_block_styles['textOrientation'] = _wp_array_get( $block_attributes, array( 'style', 'typography', 'textOrientation' ), null ); + } } $attributes = array(); diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 65a5e5fe4b9578..24b768aecb311b 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -373,9 +373,11 @@ class WP_Theme_JSON_Gutenberg { * @since 6.1.0 Added `layout.definitions` and `useRootPaddingAwareAlignments`. * @since 6.2.0 Added `dimensions.minHeight`, 'shadow.presets', 'shadow.defaultPresets', * `position.fixed` and `position.sticky`. - * @since 6.3.0 Removed `layout.definitions`. Added `typography.writingMode`. + * @since 6.3.0 Removed `layout.definitions`. * @since 6.4.0 Added `layout.allowEditing`. - * @since 6.4.0 Added `lightbox`. + * Added `lightbox`. + * Added `typography.writingMode`. + * @since 6.6.0 Added `typography.textOrientation`. * @var array */ const VALID_SETTINGS = array( @@ -459,6 +461,7 @@ class WP_Theme_JSON_Gutenberg { 'textDecoration' => null, 'textTransform' => null, 'writingMode' => null, + 'textOrientation' => null, ), ); @@ -498,8 +501,11 @@ class WP_Theme_JSON_Gutenberg { * added new property `shadow`, * updated `blockGap` to be allowed at any level. * @since 6.2.0 Added `outline`, and `minHeight` properties. + * @since 6.4.0 Added `writingMode` to `typography`. * @since 6.6.0 Added `background` sub properties to top-level only. * @since 6.6.0 Added `dimensions.aspectRatio`. + * @since 6.7.0 Added `textOrientation` to `typography`. + * * @var array */ const VALID_STYLES = array( @@ -556,6 +562,7 @@ class WP_Theme_JSON_Gutenberg { 'textDecoration' => null, 'textTransform' => null, 'writingMode' => null, + 'textOrientation' => null, ), 'css' => null, ); diff --git a/lib/compat/wordpress-6.6/kses.php b/lib/compat/wordpress-6.6/kses.php new file mode 100644 index 00000000000000..0baa6dfd924542 --- /dev/null +++ b/lib/compat/wordpress-6.6/kses.php @@ -0,0 +1,18 @@ + { @@ -304,6 +305,7 @@ export function useSettingsForBlockElement( 'textTransform', 'textDecoration', 'writingMode', + 'textOrientation', ].forEach( ( key ) => { if ( ! supportedStyles.includes( key ) ) { updatedSettings.typography = { 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 f6a389a5bc96d9..6d89ca094b390e 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -7,7 +7,7 @@ import { __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem, } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; +import { __, isRTL } from '@wordpress/i18n'; import { useCallback, useMemo, useEffect } from '@wordpress/element'; /** @@ -361,20 +361,75 @@ export default function TypographyPanel( { const hasTextDecoration = () => !! value?.typography?.textDecoration; const resetTextDecoration = () => setTextDecoration( undefined ); - // Text Orientation + // Writing Mode const hasWritingModeControl = useHasWritingModeControl( settings ); const writingMode = decodeValue( inheritedValue?.typography?.writingMode ); - const setWritingMode = ( newValue ) => { - onChange( - setImmutably( - value, - [ 'typography', 'writingMode' ], - newValue || undefined - ) - ); - }; const hasWritingMode = () => !! value?.typography?.writingMode; - const resetWritingMode = () => setWritingMode( undefined ); + const resetWritingMode = () => + setWritingModeAndTextOrientation( undefined ); + + // Text Orientation + const textOrientation = decodeValue( + inheritedValue?.typography?.textOrientation + ); + + // Returns the new text orientation and writing mode based on the value from the control. + const getTextOrientationAndWritingMode = ( valueFromControl ) => { + switch ( valueFromControl ) { + case 'top-to-bottom': + return { + newTextOrientation: 'mixed', + newWritingMode: isRTL() ? 'vertical-lr' : 'vertical-rl', + }; + + case 'upright': + return { + newTextOrientation: 'upright', + newWritingMode: isRTL() ? 'vertical-rl' : 'vertical-lr', + }; + + case 'horizontal': + return { + newTextOrientation: undefined, + newWritingMode: 'horizontal-tb', + }; + + default: + return { + newTextOrientation: undefined, + newWritingMode: undefined, + }; + } + }; + + function getValuefromWritingModeAndTextOrientation() { + if ( writingMode === 'horizontal-tb' ) { + return 'horizontal'; + } + if ( writingMode === 'vertical-lr' || writingMode === 'vertical-rl' ) { + if ( textOrientation === 'upright' ) { + return 'upright'; + } + return 'top-to-bottom'; + } + } + + const setWritingModeAndTextOrientation = useCallback( + ( newValue ) => { + const { newTextOrientation, newWritingMode } = + getTextOrientationAndWritingMode( newValue ); + + return onChange( { + ...value, + typography: { + ...value?.typography, + textOrientation: newTextOrientation, + writingMode: newWritingMode, + }, + } ); + }, + [ onChange, value ] + ); // Text Alignment const hasTextAlignmentControl = useHasTextAlignmentControl( settings ); @@ -537,23 +592,6 @@ export default function TypographyPanel( { /> ) } - { hasWritingModeControl && ( - - - - ) } { hasTextTransformControl && ( ) } + { hasWritingModeControl && ( + + + + ) } ); } diff --git a/packages/block-editor/src/components/writing-mode-control/index.js b/packages/block-editor/src/components/writing-mode-control/index.js index 7732f54b1569a7..aa2f27b97a681a 100644 --- a/packages/block-editor/src/components/writing-mode-control/index.js +++ b/packages/block-editor/src/components/writing-mode-control/index.js @@ -7,7 +7,13 @@ import clsx from 'clsx'; * WordPress dependencies */ import { __, isRTL } from '@wordpress/i18n'; -import { textHorizontal, textVertical } from '@wordpress/icons'; +import { + textHorizontal, + textHorizontalRTL, + textUpright, + textVertical, + textVerticalRTL, +} from '@wordpress/icons'; /** * Internal dependencies @@ -16,14 +22,19 @@ import SegmentedTextControl from '../segmented-text-control'; const WRITING_MODES = [ { - label: __( 'Horizontal' ), - value: 'horizontal-tb', - icon: textHorizontal, + name: __( 'Horizontal' ), + value: 'horizontal', + icon: isRTL() ? textHorizontalRTL : textHorizontal, }, { - label: __( 'Vertical' ), - value: isRTL() ? 'vertical-lr' : 'vertical-rl', - icon: textVertical, + name: __( 'Top to bottom' ), + value: 'top-to-bottom', + icon: isRTL() ? textVerticalRTL : textVertical, + }, + { + name: __( 'Upright' ), + value: 'upright', + icon: textUpright, }, ]; diff --git a/packages/block-editor/src/hooks/supports.js b/packages/block-editor/src/hooks/supports.js index 75f2bdf2dc219e..70948b4dff2aca 100644 --- a/packages/block-editor/src/hooks/supports.js +++ b/packages/block-editor/src/hooks/supports.js @@ -40,6 +40,11 @@ const TEXT_DECORATION_SUPPORT_KEY = 'typography.__experimentalTextDecoration'; * e.g. settings found in `block.json`. */ const WRITING_MODE_SUPPORT_KEY = 'typography.__experimentalWritingMode'; +/** + * Key within block settings' supports array indicating support for text orientation + * e.g. settings found in `block.json`. + */ +const TEXT_ORIENTATION_SUPPORT_KEY = 'typography.__experimentalTextOrientation'; /** * Key within block settings' supports array indicating support for text * transforms e.g. settings found in `block.json`. @@ -63,6 +68,7 @@ const TYPOGRAPHY_SUPPORT_KEYS = [ TEXT_DECORATION_SUPPORT_KEY, TEXT_TRANSFORM_SUPPORT_KEY, WRITING_MODE_SUPPORT_KEY, + TEXT_ORIENTATION_SUPPORT_KEY, LETTER_SPACING_SUPPORT_KEY, ]; const EFFECTS_SUPPORT_KEYS = [ 'shadow' ]; diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 26700ecf7b3fab..f3466505fe19cd 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -237,6 +237,7 @@ export function useBlockSettings( name, parentLayout ) { textColumns, textDecoration, writingMode, + textOrientation, textTransform, letterSpacing, padding, @@ -294,6 +295,7 @@ export function useBlockSettings( name, parentLayout ) { 'typography.textColumns', 'typography.textDecoration', 'typography.writingMode', + 'typography.textOrientation', 'typography.textTransform', 'typography.letterSpacing', 'spacing.padding', @@ -391,6 +393,7 @@ export function useBlockSettings( name, parentLayout ) { textTransform, letterSpacing, writingMode, + textOrientation, }, spacing: { spacingSizes: { @@ -439,6 +442,7 @@ export function useBlockSettings( name, parentLayout ) { textTransform, letterSpacing, writingMode, + textOrientation, padding, margin, blockGap, diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index e7e4b75d0a30f0..1c45c49638799e 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -43,6 +43,8 @@ @import "./components/segmented-text-control/style.scss"; @import "./components/skip-to-selected-block/style.scss"; @import "./components/tabbed-sidebar/style.scss"; +@import "./components/text-transform-control/style.scss"; +@import "./components/writing-mode-control/style.scss"; @import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index f16a7cf0411443..29e54df8f24757 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -65,6 +65,7 @@ "__experimentalLetterSpacing": true, "__experimentalTextTransform": true, "__experimentalWritingMode": true, + "__experimentalTextOrientation": true, "__experimentalDefaultControls": { "fontSize": true } diff --git a/packages/block-library/src/post-navigation-link/block.json b/packages/block-library/src/post-navigation-link/block.json index ce733759846fee..8a9ec3e4ef0246 100644 --- a/packages/block-library/src/post-navigation-link/block.json +++ b/packages/block-library/src/post-navigation-link/block.json @@ -51,6 +51,7 @@ "__experimentalTextDecoration": true, "__experimentalLetterSpacing": true, "__experimentalWritingMode": true, + "__experimentalTextOrientation": true, "__experimentalDefaultControls": { "fontSize": true } diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 620dfcbb8599c0..e6566e27e0d390 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -258,6 +258,11 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { support: [ 'typography', '__experimentalWritingMode' ], useEngine: true, }, + textOrientation: { + value: [ 'typography', 'textOrientation' ], + support: [ 'typography', '__experimentalTextOrientation' ], + useEngine: true, + }, '--wp--style--root--padding': { value: [ 'spacing', 'padding' ], support: [ 'spacing', 'padding' ], diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index c5d5976dd2d5f7..ecbcaa9694a81f 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -268,7 +268,10 @@ export { default as sidesTop } from './library/sides-top'; export { default as sidesVertical } from './library/sides-vertical'; export { default as textColor } from './library/text-color'; export { default as textHorizontal } from './library/text-horizontal'; +export { default as textHorizontalRTL } from './library/text-horizontal-rtl'; +export { default as textUpright } from './library/text-upright'; export { default as textVertical } from './library/text-vertical'; +export { default as textVerticalRTL } from './library/text-vertical-rtl'; export { default as tablet } from './library/tablet'; export { default as title } from './library/title'; export { default as tip } from './library/tip'; diff --git a/packages/icons/src/library/text-horizontal-rtl.js b/packages/icons/src/library/text-horizontal-rtl.js new file mode 100644 index 00000000000000..241e8245a22fef --- /dev/null +++ b/packages/icons/src/library/text-horizontal-rtl.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const textHorizontalRTL = ( + + + +); + +export default textHorizontalRTL; diff --git a/packages/icons/src/library/text-upright.js b/packages/icons/src/library/text-upright.js new file mode 100644 index 00000000000000..2f3498c8b1c53a --- /dev/null +++ b/packages/icons/src/library/text-upright.js @@ -0,0 +1,16 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const textUpright = ( + + + +); + +export default textUpright; diff --git a/packages/icons/src/library/text-vertical-rtl.js b/packages/icons/src/library/text-vertical-rtl.js new file mode 100644 index 00000000000000..9418118f637d6e --- /dev/null +++ b/packages/icons/src/library/text-vertical-rtl.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const textVerticalRTL = ( + + + +); + +export default textVerticalRTL; diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index 02186fecdcea26..03bff117d3d180 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -231,7 +231,7 @@ final class WP_Style_Engine { ), ), 'typography' => array( - 'fontSize' => array( + 'fontSize' => array( 'property_keys' => array( 'default' => 'font-size', ), @@ -243,7 +243,7 @@ final class WP_Style_Engine { 'has-$slug-font-size' => 'font-size', ), ), - 'fontFamily' => array( + 'fontFamily' => array( 'property_keys' => array( 'default' => 'font-family', ), @@ -255,54 +255,60 @@ final class WP_Style_Engine { 'has-$slug-font-family' => 'font-family', ), ), - 'fontStyle' => array( + 'fontStyle' => array( 'property_keys' => array( 'default' => 'font-style', ), 'path' => array( 'typography', 'fontStyle' ), ), - 'fontWeight' => array( + 'fontWeight' => array( 'property_keys' => array( 'default' => 'font-weight', ), 'path' => array( 'typography', 'fontWeight' ), ), - 'lineHeight' => array( + 'lineHeight' => array( 'property_keys' => array( 'default' => 'line-height', ), 'path' => array( 'typography', 'lineHeight' ), ), - 'textColumns' => array( + 'textColumns' => array( 'property_keys' => array( 'default' => 'column-count', ), 'path' => array( 'typography', 'textColumns' ), ), - 'textDecoration' => array( + 'textDecoration' => array( 'property_keys' => array( 'default' => 'text-decoration', ), 'path' => array( 'typography', 'textDecoration' ), ), - 'textTransform' => array( + 'textTransform' => array( 'property_keys' => array( 'default' => 'text-transform', ), 'path' => array( 'typography', 'textTransform' ), ), - 'letterSpacing' => array( + 'letterSpacing' => array( 'property_keys' => array( 'default' => 'letter-spacing', ), 'path' => array( 'typography', 'letterSpacing' ), ), - 'writingMode' => array( + 'writingMode' => array( 'property_keys' => array( 'default' => 'writing-mode', ), 'path' => array( 'typography', 'writingMode' ), ), + 'textOrientation' => array( + 'property_keys' => array( + 'default' => 'text-orientation', + ), + 'path' => array( 'typography', 'textOrientation' ), + ), ), ); diff --git a/packages/style-engine/src/styles/typography/index.ts b/packages/style-engine/src/styles/typography/index.ts index 92c40d2e156198..afc6ba52f339d8 100644 --- a/packages/style-engine/src/styles/typography/index.ts +++ b/packages/style-engine/src/styles/typography/index.ts @@ -124,6 +124,18 @@ const writingMode = { }, }; +const textOrientation = { + name: 'textOrientation', + generate: ( style: Style, options: StyleOptions ) => { + return generateRule( + style, + options, + [ 'typography', 'textOrientation' ], + 'textOrientation' + ); + }, +}; + export default [ fontFamily, fontSize, @@ -135,4 +147,5 @@ export default [ textDecoration, textTransform, writingMode, + textOrientation, ]; diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 5b361836a8e375..6640a3f9a4b3e6 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -65,6 +65,7 @@ export interface Style { textDecoration?: CSSProperties[ 'textDecoration' ]; textTransform?: CSSProperties[ 'textTransform' ]; writingMode?: CSSProperties[ 'writingMode' ]; + textOrientation?: CSSProperties[ 'textOrientation' ]; }; color?: { text?: CSSProperties[ 'color' ]; diff --git a/schemas/json/theme.json b/schemas/json/theme.json index a1f51ace920259..dc2c14cd9b9cd7 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -603,6 +603,11 @@ "type": "boolean", "default": false }, + "textOrientation": { + "description": "Allow users to set the textOrientation.", + "type": "boolean", + "default": false + }, "textTransform": { "description": "Allow users to set custom text transforms.", "type": "boolean", @@ -1662,6 +1667,17 @@ { "$ref": "#/definitions/refComplete" } ] }, + "textOrientation": { + "description": "Sets the `text-orientation` CSS property.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/refComplete" + } + ] + }, "textTransform": { "description": "Sets the `text-transform` CSS property.", "oneOf": [