From 2a0736ff7e9eda0dfc476ced555c818f03430b45 Mon Sep 17 00:00:00 2001 From: Carolina Nymark Date: Thu, 27 May 2021 11:06:49 +0200 Subject: [PATCH] Add Letter-spacing and enable this for site title and site tagline (#31118) * Add Letter-spacing and enable this for site title and site tagline --- lib/block-supports/typography.php | 12 +++- lib/class-wp-theme-json-gutenberg.php | 5 ++ lib/experimental-default-theme.json | 1 + packages/block-editor/src/components/index.js | 1 + .../letter-spacing-control/index.js | 46 ++++++++++++ .../block-editor/src/hooks/letter-spacing.js | 71 +++++++++++++++++++ packages/block-editor/src/hooks/typography.js | 8 +++ .../block-library/src/site-tagline/block.json | 3 +- .../block-library/src/site-title/block.json | 3 +- packages/blocks/src/api/constants.js | 4 ++ .../components/sidebar/typography-panel.js | 26 ++++++- 11 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 packages/block-editor/src/components/letter-spacing-control/index.js create mode 100644 packages/block-editor/src/hooks/letter-spacing.js diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index fed915d600507..ed63b56b6a00a 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -21,13 +21,15 @@ function gutenberg_register_typography_support( $block_type ) { $has_line_height_support = _wp_array_get( $block_type->supports, array( 'lineHeight' ), false ); $has_text_decoration_support = _wp_array_get( $block_type->supports, array( '__experimentalTextDecoration' ), false ); $has_text_transform_support = _wp_array_get( $block_type->supports, array( '__experimentalTextTransform' ), false ); + $has_letter_spacing_support = _wp_array_get( $block_type->supports, array( '__experimentalLetterSpacing' ), false ); $has_typography_support = $has_font_size_support || $has_font_weight_support || $has_font_style_support || $has_line_height_support || $has_text_transform_support - || $has_text_decoration_support; + || $has_text_decoration_support + || $has_letter_spacing_support; if ( ! $block_type->attributes ) { $block_type->attributes = array(); @@ -72,6 +74,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { $has_line_height_support = _wp_array_get( $block_type->supports, array( 'lineHeight' ), false ); $has_text_decoration_support = _wp_array_get( $block_type->supports, array( '__experimentalTextDecoration' ), false ); $has_text_transform_support = _wp_array_get( $block_type->supports, array( '__experimentalTextTransform' ), false ); + $has_letter_spacing_support = _wp_array_get( $block_type->supports, array( '__experimentalLetterSpacing' ), false ); $skip_font_size_support_serialization = _wp_array_get( $block_type->supports, array( '__experimentalSkipFontSizeSerialization' ), false ); @@ -151,6 +154,13 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) { } } + if ( $has_letter_spacing_support ) { + $letter_spacing_style = gutenberg_typography_get_css_variable_inline_style( $block_attributes, 'letterSpacing', 'letter-spacing' ); + if ( $letter_spacing_style ) { + $styles[] = $letter_spacing_style; + } + } + if ( ! empty( $classes ) ) { $attributes['class'] = implode( ' ', $classes ); } diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index f883bbe2e128e..f0544ed03dba1 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -73,6 +73,7 @@ class WP_Theme_JSON_Gutenberg { 'fontSize' => null, 'fontStyle' => null, 'fontWeight' => null, + 'letterSpacing' => null, 'lineHeight' => null, 'textDecoration' => null, 'textTransform' => null, @@ -105,6 +106,7 @@ class WP_Theme_JSON_Gutenberg { 'customFontSize' => null, 'customFontStyle' => null, 'customFontWeight' => null, + 'customLetterSpacing' => null, 'customLineHeight' => null, 'customTextDecorations' => null, 'customTextTransforms' => null, @@ -238,6 +240,9 @@ class WP_Theme_JSON_Gutenberg { 'font-weight' => array( 'value' => array( 'typography', 'fontWeight' ), ), + 'letter-spacing' => array( + 'value' => array( 'typography', 'letterSpacing' ), + ), 'line-height' => array( 'value' => array( 'typography', 'lineHeight' ), ), diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index dc4dbbaf05852..7297493491c99 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -204,6 +204,7 @@ "customFontWeight": true, "customTextTransforms": true, "customTextDecorations": true, + "customLetterSpacing": true, "fontSizes": [ { "name": "Small", diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 51d9ba8c1a0db..7f1316dceeec0 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -44,6 +44,7 @@ export { default as __experimentalGradientPickerControl } from './gradient-picke export { default as __experimentalGradientPickerPanel } from './gradient-picker/panel'; export { default as __experimentalFontAppearanceControl } from './font-appearance-control'; export { default as __experimentalFontFamilyControl } from './font-family'; +export { default as __experimentalLetterSpacingControl } from './letter-spacing-control'; export { default as __experimentalColorGradientControl } from './colors-gradients/control'; export { default as __experimentalPanelColorGradientSettings } from './colors-gradients/panel-color-gradient-settings'; export { default as __experimentalImageSizeControl } from './image-size-control'; diff --git a/packages/block-editor/src/components/letter-spacing-control/index.js b/packages/block-editor/src/components/letter-spacing-control/index.js new file mode 100644 index 0000000000000..4aba5958c9f4a --- /dev/null +++ b/packages/block-editor/src/components/letter-spacing-control/index.js @@ -0,0 +1,46 @@ +/** + * WordPress dependencies + */ +import { __experimentalUnitControl as UnitControl } from '@wordpress/components'; +import { Platform } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; + +const isWeb = Platform.OS === 'web'; + +const CSS_UNITS = [ + { + value: 'px', + label: isWeb ? 'px' : __( 'Pixels (px)' ), + default: '2', + }, + { + value: 'em', + label: isWeb ? 'em' : __( 'Relative to parent font size (em)' ), + default: '.2', + }, + { + value: 'rem', + label: isWeb ? 'rem' : __( 'Relative to root font size (rem)' ), + default: '.2', + }, +]; + +/** + * Control for letter-spacing. + * + * @param {Object} props Component props. + * @param {string} props.value Currently selected letter-spacing. + * @param {Function} props.onChange Handles change in letter-spacing selection. + * @return {WPElement} Letter-spacing control. + */ +export default function LetterSpacingControl( { value, onChange } ) { + return ( + + ); +} diff --git a/packages/block-editor/src/hooks/letter-spacing.js b/packages/block-editor/src/hooks/letter-spacing.js new file mode 100644 index 0000000000000..0a70474c47803 --- /dev/null +++ b/packages/block-editor/src/hooks/letter-spacing.js @@ -0,0 +1,71 @@ +/** + * WordPress dependencies + */ +import { hasBlockSupport } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import LetterSpacingControl from '../components/letter-spacing-control'; +import useSetting from '../components/use-setting'; +import { cleanEmptyObject } from './utils'; + +/** + * Key within block settings' supports array indicating support for letter-spacing + * e.g. settings found in `block.json`. + */ +export const LETTER_SPACING_SUPPORT_KEY = '__experimentalLetterSpacing'; + +/** + * Inspector control panel containing the letter-spacing options. + * + * @param {Object} props Block properties. + * @return {WPElement} Letter-spacing edit element. + */ +export function LetterSpacingEdit( props ) { + const { + attributes: { style }, + setAttributes, + } = props; + + const isDisabled = useIsLetterSpacingDisabled( props ); + + if ( isDisabled ) { + return null; + } + + function onChange( newSpacing ) { + setAttributes( { + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + letterSpacing: newSpacing, + }, + } ), + } ); + } + + return ( + + ); +} + +/** + * Checks if letter-spacing settings have been disabled. + * + * @param {string} name Name of the block. + * @return {boolean} Whether or not the setting is disabled. + */ +export function useIsLetterSpacingDisabled( { name: blockName } = {} ) { + const notSupported = ! hasBlockSupport( + blockName, + LETTER_SPACING_SUPPORT_KEY + ); + const hasLetterSpacing = useSetting( 'typography.customLetterSpacing' ); + + return notSupported || ! hasLetterSpacing; +} diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index 5edc061a0220f..92186f5e87621 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -47,6 +47,11 @@ import { TEXT_TRANSFORM_SUPPORT_KEY, useIsTextTransformDisabled, } from './text-transform'; +import { + LETTER_SPACING_SUPPORT_KEY, + LetterSpacingEdit, + useIsLetterSpacingDisabled, +} from './letter-spacing'; export const TYPOGRAPHY_SUPPORT_KEYS = [ LINE_HEIGHT_SUPPORT_KEY, @@ -56,6 +61,7 @@ export const TYPOGRAPHY_SUPPORT_KEYS = [ FONT_FAMILY_SUPPORT_KEY, TEXT_DECORATION_SUPPORT_KEY, TEXT_TRANSFORM_SUPPORT_KEY, + LETTER_SPACING_SUPPORT_KEY, ]; export function TypographyPanel( props ) { @@ -75,6 +81,7 @@ export function TypographyPanel( props ) { + @@ -98,6 +105,7 @@ function useIsTypographyDisabled( props = {} ) { useIsFontFamilyDisabled( props ), useIsTextDecorationDisabled( props ), useIsTextTransformDisabled( props ), + useIsLetterSpacingDisabled( props ), ]; return configs.filter( Boolean ).length === configs.length; diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json index d85e68f3e1d0b..2e5689f5994b3 100644 --- a/packages/block-library/src/site-tagline/block.json +++ b/packages/block-library/src/site-tagline/block.json @@ -23,6 +23,7 @@ "fontSize": true, "lineHeight": true, "__experimentalFontFamily": true, - "__experimentalTextTransform": true + "__experimentalTextTransform": true, + "__experimentalLetterSpacing": true } } diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json index 26ee7c601f107..e84e348cbe919 100644 --- a/packages/block-library/src/site-title/block.json +++ b/packages/block-library/src/site-title/block.json @@ -31,6 +31,7 @@ "__experimentalFontFamily": true, "__experimentalTextTransform": true, "__experimentalFontStyle": true, - "__experimentalFontWeight": true + "__experimentalFontWeight": true, + "__experimentalLetterSpacing": true } } diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 33c017933ad76..b07aa5a174565 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -88,6 +88,10 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { value: [ 'typography', 'textTransform' ], support: [ '__experimentalTextTransform' ], }, + letterSpacing: { + value: [ 'typography', 'letterSpacing' ], + support: [ '__experimentalLetterSpacing' ], + }, }; export const __EXPERIMENTAL_ELEMENTS = { diff --git a/packages/edit-site/src/components/sidebar/typography-panel.js b/packages/edit-site/src/components/sidebar/typography-panel.js index 9752af7d2a90c..8e14eb08e0b4d 100644 --- a/packages/edit-site/src/components/sidebar/typography-panel.js +++ b/packages/edit-site/src/components/sidebar/typography-panel.js @@ -5,6 +5,7 @@ import { LineHeightControl, __experimentalFontFamilyControl as FontFamilyControl, __experimentalFontAppearanceControl as FontAppearanceControl, + __experimentalLetterSpacingControl as LetterSpacingControl, } from '@wordpress/block-editor'; import { PanelBody, FontSizePicker } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -17,8 +18,12 @@ import { useSetting } from '../editor/utils'; export function useHasTypographyPanel( { supports, name } ) { const hasLineHeight = useHasLineHeightControl( { supports, name } ); const hasFontAppearance = useHasAppearanceControl( { supports, name } ); + const hasLetterSpacing = useHasLetterSpacingControl( { supports, name } ); return ( - hasLineHeight || hasFontAppearance || supports.includes( 'fontSize' ) + hasLineHeight || + hasFontAppearance || + hasLetterSpacing || + supports.includes( 'fontSize' ) ); } @@ -39,6 +44,13 @@ function useHasAppearanceControl( { supports, name } ) { return hasFontStyles || hasFontWeights; } +function useHasLetterSpacingControl( { supports, name } ) { + return ( + useSetting( 'typography.customLetterSpacing', name ) && + supports.includes( 'letterSpacing' ) + ); +} + export default function TypographyPanel( { context: { supports, name }, getStyle, @@ -58,6 +70,10 @@ export default function TypographyPanel( { supports.includes( 'fontWeight' ); const hasLineHeightEnabled = useHasLineHeightControl( { supports, name } ); const hasAppearanceControl = useHasAppearanceControl( { supports, name } ); + const hasLetterSpacingControl = useHasLetterSpacingControl( { + supports, + name, + } ); return ( @@ -102,6 +118,14 @@ export default function TypographyPanel( { hasFontWeights={ hasFontWeights } /> ) } + { hasLetterSpacingControl && ( + + setStyle( name, 'letterSpacing', value ) + } + /> + ) } ); }