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": [