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 3299739575430..a2e88320cf58b 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -158,6 +158,7 @@ Settings related to typography. | lineHeight | boolean | false | | | textColumns | boolean | false | | | textDecoration | boolean | true | | +| writingMode | boolean | false | | | textTransform | boolean | true | | | dropCap | boolean | true | | | fontSizes | array | | fluid, name, size, slug | @@ -239,6 +240,7 @@ Typography styles. | lineHeight | string, object | | | textColumns | string | | | textDecoration | string, object | | +| writingMode | string, object | | | textTransform | string, object | | --- diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 469b429f9b3dd..047231a6eed10 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -29,6 +29,7 @@ function gutenberg_register_typography_support( $block_type ) { $has_text_columns_support = _wp_array_get( $typography_supports, array( 'textColumns' ), false ); $has_text_decoration_support = _wp_array_get( $typography_supports, array( '__experimentalTextDecoration' ), false ); $has_text_transform_support = _wp_array_get( $typography_supports, array( '__experimentalTextTransform' ), false ); + $has_writing_mode_support = _wp_array_get( $typography_supports, array( '__experimentalWritingMode' ), false ); $has_typography_support = $has_font_family_support || $has_font_size_support @@ -38,7 +39,8 @@ function gutenberg_register_typography_support( $block_type ) { || $has_line_height_support || $has_text_columns_support || $has_text_decoration_support - || $has_text_transform_support; + || $has_text_transform_support + || $has_writing_mode_support; if ( ! $block_type->attributes ) { $block_type->attributes = array(); @@ -96,6 +98,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { $has_text_columns_support = _wp_array_get( $typography_supports, array( 'textColumns' ), false ); $has_text_decoration_support = _wp_array_get( $typography_supports, array( '__experimentalTextDecoration' ), false ); $has_text_transform_support = _wp_array_get( $typography_supports, array( '__experimentalTextTransform' ), false ); + $has_writing_mode_support = _wp_array_get( $typography_supports, array( '__experimentalWritingMode' ), false ); // Whether to skip individual block support features. $should_skip_font_size = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'fontSize' ); @@ -107,6 +110,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { $should_skip_text_decoration = wp_should_skip_block_supports_serialization( $block_type, 'typography', 'textDecoration' ); $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' ); $typography_block_styles = array(); if ( $has_font_size_support && ! $should_skip_font_size ) { @@ -158,6 +162,10 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { gutenberg_typography_get_preset_inline_style_value( $block_attributes['style']['typography']['letterSpacing'], 'letter-spacing' ); } + if ( $has_writing_mode_support && ! $should_skip_writing_mode && isset( $block_attributes['style']['typography']['writingMode'] ) ) { + $typography_block_styles['writingMode'] = _wp_array_get( $block_attributes, array( 'style', 'typography', 'writingMode' ), null ); + } + $attributes = array(); $styles = gutenberg_style_engine_get_styles( array( 'typography' => $typography_block_styles ), diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 7313afeba91bc..0745ee06b84a2 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -202,6 +202,7 @@ class WP_Theme_JSON_Gutenberg { * `--wp--style--root--padding-*`, and `box-shadow` properties, * removed the `--wp--style--block-gap` property. * @since 6.2.0 Added `outline-*`, and `min-height` properties. + * @since 6.3.0 Added `writing-mode` property. * * @var array */ @@ -260,6 +261,7 @@ class WP_Theme_JSON_Gutenberg { 'text-transform' => array( 'typography', 'textTransform' ), 'filter' => array( 'filter', 'duotone' ), 'box-shadow' => array( 'shadow' ), + 'writing-mode' => array( 'typography', 'writingMode' ), ); /** @@ -339,7 +341,7 @@ 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`. + * @since 6.3.0 Removed `layout.definitions`. Added `typography.writingMode`. * @var array */ const VALID_SETTINGS = array( @@ -406,6 +408,7 @@ class WP_Theme_JSON_Gutenberg { 'textColumns' => null, 'textDecoration' => null, 'textTransform' => null, + 'writingMode' => null, ), 'behaviors' => null, ); @@ -468,6 +471,7 @@ class WP_Theme_JSON_Gutenberg { 'textColumns' => null, 'textDecoration' => null, 'textTransform' => null, + 'writingMode' => null, ), 'css' => null, ); diff --git a/lib/theme.json b/lib/theme.json index 2786c281822d6..5c64526b1a253 100644 --- a/lib/theme.json +++ b/lib/theme.json @@ -274,7 +274,8 @@ "lineHeight": false, "textColumns": false, "textDecoration": true, - "textTransform": true + "textTransform": true, + "writingMode": false }, "blocks": { "core/button": { diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js index d5ad137503169..2efdc187f8f6b 100644 --- a/packages/block-editor/src/components/global-styles/hooks.js +++ b/packages/block-editor/src/components/global-styles/hooks.js @@ -71,6 +71,7 @@ const VALID_SETTINGS = [ 'typography.textColumns', 'typography.textDecoration', 'typography.textTransform', + 'typography.writingMode', ]; export const useGlobalStylesReset = () => { @@ -292,6 +293,7 @@ export function useSettingsForBlockElement( 'letterSpacing', 'textTransform', 'textDecoration', + 'writingMode', ].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 37ed048172e88..371855ab0ae23 100644 --- a/packages/block-editor/src/components/global-styles/typography-panel.js +++ b/packages/block-editor/src/components/global-styles/typography-panel.js @@ -19,6 +19,7 @@ import LineHeightControl from '../line-height-control'; import LetterSpacingControl from '../letter-spacing-control'; import TextTransformControl from '../text-transform-control'; import TextDecorationControl from '../text-decoration-control'; +import WritingModeControl from '../writing-mode-control'; import { getValueFromVariable } from './utils'; import { setImmutably } from '../../utils/object'; @@ -32,6 +33,7 @@ export function useHasTypographyPanel( settings ) { const hasLetterSpacing = useHasLetterSpacingControl( settings ); const hasTextTransform = useHasTextTransformControl( settings ); const hasTextDecoration = useHasTextDecorationControl( settings ); + const hasWritingMode = useHasWritingModeControl( settings ); const hasTextColumns = useHasTextColumnsControl( settings ); const hasFontSize = useHasFontSizeControl( settings ); @@ -43,6 +45,7 @@ export function useHasTypographyPanel( settings ) { hasTextTransform || hasFontSize || hasTextDecoration || + hasWritingMode || hasTextColumns ); } @@ -103,6 +106,10 @@ function useHasTextDecorationControl( settings ) { return settings?.typography?.textDecoration; } +function useHasWritingModeControl( settings ) { + return settings?.typography?.writingMode; +} + function useHasTextColumnsControl( settings ) { return settings?.typography?.textColumns; } @@ -138,6 +145,7 @@ const DEFAULT_CONTROLS = { letterSpacing: true, textTransform: true, textDecoration: true, + writingMode: true, textColumns: true, }; @@ -310,6 +318,21 @@ export default function TypographyPanel( { const hasTextDecoration = () => !! value?.typography?.textDecoration; const resetTextDecoration = () => setTextDecoration( undefined ); + // Text Orientation + 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 resetAllFilter = useCallback( ( previousValue ) => { return { ...previousValue, @@ -456,6 +479,23 @@ export default function TypographyPanel( { /> ) } + { hasWritingModeControl && ( + + + + ) } { hasTextTransformControl && ( + + { __( 'Orientation' ) } + +
+ { WRITING_MODES.map( ( writingMode ) => { + return ( +
+ + ); +} diff --git a/packages/block-editor/src/components/writing-mode-control/style.scss b/packages/block-editor/src/components/writing-mode-control/style.scss new file mode 100644 index 0000000000000..4b865dc0282c0 --- /dev/null +++ b/packages/block-editor/src/components/writing-mode-control/style.scss @@ -0,0 +1,18 @@ +.block-editor-writing-mode-control { + border: 0; + margin: 0; + padding: 0; + + .block-editor-writing-mode-control__buttons { + // 4px of padding makes the row 40px high, same as an input. + padding: $grid-unit-05 0; + display: flex; + } + + .components-button.has-icon { + height: $grid-unit-40; + margin-right: $grid-unit-05; + min-width: $grid-unit-40; + padding: 0; + } +} diff --git a/packages/block-editor/src/hooks/supports.js b/packages/block-editor/src/hooks/supports.js index ead8ca89aa47d..2cf08d46fa8fe 100644 --- a/packages/block-editor/src/hooks/supports.js +++ b/packages/block-editor/src/hooks/supports.js @@ -30,11 +30,17 @@ const TEXT_COLUMNS_SUPPORT_KEY = 'typography.textColumns'; * decorations e.g. settings found in `block.json`. */ const TEXT_DECORATION_SUPPORT_KEY = 'typography.__experimentalTextDecoration'; +/** + * Key within block settings' supports array indicating support for writing mode + * e.g. settings found in `block.json`. + */ +const WRITING_MODE_SUPPORT_KEY = 'typography.__experimentalWritingMode'; /** * Key within block settings' supports array indicating support for text * transforms e.g. settings found in `block.json`. */ const TEXT_TRANSFORM_SUPPORT_KEY = 'typography.__experimentalTextTransform'; + /** * Key within block settings' supports array indicating support for letter-spacing * e.g. settings found in `block.json`. @@ -50,6 +56,7 @@ const TYPOGRAPHY_SUPPORT_KEYS = [ TEXT_COLUMNS_SUPPORT_KEY, TEXT_DECORATION_SUPPORT_KEY, TEXT_TRANSFORM_SUPPORT_KEY, + WRITING_MODE_SUPPORT_KEY, LETTER_SPACING_SUPPORT_KEY, ]; const SPACING_SUPPORT_KEY = 'spacing'; diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index cb98c4098c477..c7d1a6ba3b144 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -30,6 +30,7 @@ const TEXT_DECORATION_SUPPORT_KEY = 'typography.__experimentalTextDecoration'; const TEXT_COLUMNS_SUPPORT_KEY = 'typography.textColumns'; const FONT_STYLE_SUPPORT_KEY = 'typography.__experimentalFontStyle'; const FONT_WEIGHT_SUPPORT_KEY = 'typography.__experimentalFontWeight'; +const WRITING_MODE_SUPPORT_KEY = 'typography.__experimentalWritingMode'; export const TYPOGRAPHY_SUPPORT_KEY = 'typography'; export const TYPOGRAPHY_SUPPORT_KEYS = [ LINE_HEIGHT_SUPPORT_KEY, @@ -39,6 +40,7 @@ export const TYPOGRAPHY_SUPPORT_KEYS = [ FONT_FAMILY_SUPPORT_KEY, TEXT_COLUMNS_SUPPORT_KEY, TEXT_DECORATION_SUPPORT_KEY, + WRITING_MODE_SUPPORT_KEY, TEXT_TRANSFORM_SUPPORT_KEY, LETTER_SPACING_SUPPORT_KEY, ]; diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 8c525e78e4c6e..ccc5dcd9ff2e2 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -136,6 +136,7 @@ export function useBlockSettings( name, parentLayout ) { const lineHeight = useSetting( 'typography.lineHeight' ); const textColumns = useSetting( 'typography.textColumns' ); const textDecoration = useSetting( 'typography.textDecoration' ); + const writingMode = useSetting( 'typography.writingMode' ); const textTransform = useSetting( 'typography.textTransform' ); const letterSpacing = useSetting( 'typography.letterSpacing' ); const padding = useSetting( 'spacing.padding' ); @@ -211,6 +212,7 @@ export function useBlockSettings( name, parentLayout ) { textDecoration, textTransform, letterSpacing, + writingMode, }, spacing: { spacingSizes: { @@ -244,6 +246,7 @@ export function useBlockSettings( name, parentLayout ) { textDecoration, textTransform, letterSpacing, + writingMode, padding, margin, blockGap, diff --git a/packages/block-library/src/paragraph/block.json b/packages/block-library/src/paragraph/block.json index cbabc108eca31..7e13b13dc4feb 100644 --- a/packages/block-library/src/paragraph/block.json +++ b/packages/block-library/src/paragraph/block.json @@ -58,6 +58,7 @@ "__experimentalFontWeight": true, "__experimentalLetterSpacing": true, "__experimentalTextTransform": true, + "__experimentalWritingMode": 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 4e7df560c69b3..e1b6d4fa90a40 100644 --- a/packages/block-library/src/post-navigation-link/block.json +++ b/packages/block-library/src/post-navigation-link/block.json @@ -45,6 +45,7 @@ "__experimentalTextTransform": true, "__experimentalTextDecoration": true, "__experimentalLetterSpacing": true, + "__experimentalWritingMode": true, "__experimentalDefaultControls": { "fontSize": true } diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 6fe04c07de1bf..fb4e4efa4e083 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -215,6 +215,11 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { support: [ 'typography', '__experimentalLetterSpacing' ], useEngine: true, }, + writingMode: { + value: [ 'typography', 'writingMode' ], + support: [ 'typography', '__experimentalWritingMode' ], + useEngine: true, + }, '--wp--style--root--padding': { value: [ 'spacing', 'padding' ], support: [ 'spacing', 'padding' ], diff --git a/packages/edit-site/src/components/global-styles/stories/index.js b/packages/edit-site/src/components/global-styles/stories/index.js index f5e31cc142c0f..f04387295c458 100644 --- a/packages/edit-site/src/components/global-styles/stories/index.js +++ b/packages/edit-site/src/components/global-styles/stories/index.js @@ -367,6 +367,7 @@ const BASE_SETTINGS = { textColumns: false, textDecoration: true, textTransform: true, + writingMode: false, fluid: true, fontFamilies: { theme: [ diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js index 903d6f9455a87..1f15620ff6b22 100644 --- a/packages/icons/src/index.js +++ b/packages/icons/src/index.js @@ -255,6 +255,8 @@ export { default as sidesRight } from './library/sides-right'; 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 textVertical } from './library/text-vertical'; 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.js b/packages/icons/src/library/text-horizontal.js new file mode 100644 index 0000000000000..3f82ee1fba4cb --- /dev/null +++ b/packages/icons/src/library/text-horizontal.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const textHorizontal = ( + + + +); + +export default textHorizontal; diff --git a/packages/icons/src/library/text-vertical.js b/packages/icons/src/library/text-vertical.js new file mode 100644 index 0000000000000..406561bee97cc --- /dev/null +++ b/packages/icons/src/library/text-vertical.js @@ -0,0 +1,12 @@ +/** + * WordPress dependencies + */ +import { SVG, Path } from '@wordpress/primitives'; + +const textVertical = ( + + + +); + +export default textVertical; diff --git a/packages/style-engine/class-wp-style-engine.php b/packages/style-engine/class-wp-style-engine.php index d62f245364103..ec66168bc1a9a 100644 --- a/packages/style-engine/class-wp-style-engine.php +++ b/packages/style-engine/class-wp-style-engine.php @@ -241,6 +241,12 @@ final class WP_Style_Engine { ), 'path' => array( 'typography', 'letterSpacing' ), ), + 'writingMode' => array( + 'property_keys' => array( + 'default' => 'writing-mode', + ), + 'path' => array( 'typography', 'writingMode' ), + ), ), ); diff --git a/packages/style-engine/src/styles/typography/index.ts b/packages/style-engine/src/styles/typography/index.ts index 66e89d0e56209..92c40d2e15619 100644 --- a/packages/style-engine/src/styles/typography/index.ts +++ b/packages/style-engine/src/styles/typography/index.ts @@ -112,6 +112,18 @@ const textTransform = { }, }; +const writingMode = { + name: 'writingMode', + generate: ( style: Style, options: StyleOptions ) => { + return generateRule( + style, + options, + [ 'typography', 'writingMode' ], + 'writingMode' + ); + }, +}; + export default [ fontFamily, fontSize, @@ -122,4 +134,5 @@ export default [ textColumns, textDecoration, textTransform, + writingMode, ]; diff --git a/packages/style-engine/src/types.ts b/packages/style-engine/src/types.ts index 23d3e38cc43c2..4b6a9aa72257e 100644 --- a/packages/style-engine/src/types.ts +++ b/packages/style-engine/src/types.ts @@ -55,6 +55,7 @@ export interface Style { textColumns?: CSSProperties[ 'columnCount' ]; textDecoration?: CSSProperties[ 'textDecoration' ]; textTransform?: CSSProperties[ 'textTransform' ]; + writingMode?: CSSProperties[ 'writingMode' ]; }; color?: { text?: CSSProperties[ 'color' ]; diff --git a/schemas/json/theme.json b/schemas/json/theme.json index 03a966f7f3eee..7f0e712283b60 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -458,6 +458,11 @@ "type": "boolean", "default": true }, + "writingMode": { + "description": "Allow users to set the writing mode.", + "type": "boolean", + "default": false + }, "textTransform": { "description": "Allow users to set custom text transforms.", "type": "boolean", @@ -1508,6 +1513,17 @@ } ] }, + "writingMode": { + "description": "Sets the `writing-mode` CSS property.", + "oneOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/refComplete" + } + ] + }, "textTransform": { "description": "Sets the `text-transform` CSS property.", "oneOf": [