From 75605bc54049463d89f94a9236a9d132a22385ca Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Tue, 13 Oct 2020 21:34:31 +1000 Subject: [PATCH 1/8] Add text transform block support --- lib/block-supports/typography.php | 7 +- lib/experimental-default-theme.json | 14 +++ lib/global-styles.php | 15 ++- .../text-transform-control/index.js | 67 +++++++++++++ .../block-editor/src/hooks/text-transform.js | 98 +++++++++++++++++++ packages/block-editor/src/hooks/typography.js | 8 ++ packages/block-library/src/heading/block.json | 1 + packages/blocks/src/api/constants.js | 1 + .../edit-site/src/components/editor/utils.js | 1 + 9 files changed, 208 insertions(+), 4 deletions(-) create mode 100644 packages/block-editor/src/components/text-transform-control/index.js create mode 100644 packages/block-editor/src/hooks/text-transform.js diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php index 3f7ebb7c28d21e..0aaa1459edcf04 100644 --- a/lib/block-supports/typography.php +++ b/lib/block-supports/typography.php @@ -21,11 +21,16 @@ function gutenberg_register_typography_support( $block_type ) { $has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( 'lineHeight' ), false ); } + $has_text_transform_support = false; + if ( property_exists( $block_type, 'supports' ) ) { + $has_text_transform_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextTransform' ), false ); + } + if ( ! $block_type->attributes ) { $block_type->attributes = array(); } - if ( ( $has_font_size_support || $has_line_height_support ) && ! array_key_exists( 'style', $block_type->attributes ) ) { + if ( ( $has_font_size_support || $has_line_height_support || $has_text_transform_support ) && ! array_key_exists( 'style', $block_type->attributes ) ) { $block_type->attributes['style'] = array( 'type' => 'object', ); diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index 28a20292ff3f88..9775224079f919 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -160,6 +160,20 @@ "slug": "huge", "size": 42 } + ], + "textTransforms": [ + { + "name": "Capitalize", + "slug": "capitalize" + }, + { + "name": "Lowercase", + "slug": "lowercase" + }, + { + "name": "Uppercase", + "slug": "uppercase" + } ] }, "spacing": { diff --git a/lib/global-styles.php b/lib/global-styles.php index 46bbf2c86c964b..0e32cce3355f71 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -395,6 +395,8 @@ function gutenberg_experimental_global_styles_get_css_property( $style_property return 'font-size'; case 'lineHeight': return 'line-height'; + case 'textTransform': + return 'text-transform'; default: return $style_property; } @@ -413,6 +415,7 @@ function gutenberg_experimental_global_styles_get_style_property() { 'color' => array( 'color', 'text' ), 'fontSize' => array( 'typography', 'fontSize' ), 'lineHeight' => array( 'typography', 'lineHeight' ), + 'textTransform' => array( 'typography', 'textTransform' ), ); } @@ -429,6 +432,7 @@ function gutenberg_experimental_global_styles_get_support_keys() { 'color' => array( 'color' ), 'fontSize' => array( 'fontSize' ), 'lineHeight' => array( 'lineHeight' ), + 'textTransform' => array( '__experimentalTextTransform' ), ); } @@ -451,6 +455,10 @@ function gutenberg_experimental_global_styles_get_presets_structure() { 'path' => array( 'typography', 'fontSizes' ), 'key' => 'size', ), + 'textTransform' => array( + 'path' => array( 'typography', 'textTransforms' ), + 'key' => 'slug', + ), ); } @@ -489,9 +497,10 @@ function gutenberg_experimental_global_styles_get_block_data() { 'global', array( 'supports' => array( - '__experimentalSelector' => ':root', - 'fontSize' => true, - 'color' => array( + '__experimentalSelector' => ':root', + 'fontSize' => true, + '__experimentalTextTransform' => true, + 'color' => array( 'linkColor' => true, 'gradients' => true, ), diff --git a/packages/block-editor/src/components/text-transform-control/index.js b/packages/block-editor/src/components/text-transform-control/index.js new file mode 100644 index 00000000000000..e66e6d6cdbd009 --- /dev/null +++ b/packages/block-editor/src/components/text-transform-control/index.js @@ -0,0 +1,67 @@ +/** + * WordPress dependencies + */ +import { Button, ButtonGroup } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Control to facilitate text transform selections. + * + * @param {Object} props Component props. + * @param {string} props.value Currently selected text transform. + * @param {Array} props.textTransforms Text transforms available for selection. + * @param {Function} props.onChange Handles change in text transform selection. + * @return {WPElement} Text transform control. + */ +export default function TextTransformControl( { + value: textTransform, + textTransforms, + onChange, +} ) { + /** + * Determines what the new text transform is as a result of a user + * interaction with the control. Then passes this on to the supplied + * onChange handler. + * + * @param {string} newTransform Slug for selected text transform. + */ + const handleOnChange = ( newTransform ) => { + // Check if we are toggling a transform off. + const transform = + textTransform === newTransform ? undefined : newTransform; + + // Ensure only defined text transforms are allowed. + const presetTransform = textTransforms.find( + ( { slug } ) => slug === transform + ); + + // Create string that will be turned into CSS custom property + const newTextTransform = presetTransform + ? `var:preset|text-transform|${ presetTransform.slug }` + : undefined; + + onChange( newTextTransform ); + }; + + return ( + <> +

{ __( 'Text Transform' ) }

+ + { textTransforms.map( ( presetTransform ) => { + return ( + + ); + } ) } + + + ); +} diff --git a/packages/block-editor/src/hooks/text-transform.js b/packages/block-editor/src/hooks/text-transform.js new file mode 100644 index 00000000000000..8d7e807584cb09 --- /dev/null +++ b/packages/block-editor/src/hooks/text-transform.js @@ -0,0 +1,98 @@ +/** + * WordPress dependencies + */ +import { hasBlockSupport } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import TextTransformControl from '../components/text-transform-control'; +import useEditorFeature from '../components/use-editor-feature'; +import { cleanEmptyObject } from './utils'; + +/** + * Key within block settings' supports array indicating support for text + * transforms e.g. settings found in `block.json`. + */ +export const TEXT_TRANSFORM_SUPPORT_KEY = '__experimentalTextTransform'; + +/** + * Inspector control panel containing the text transform options. + * + * @param {Object} props Block properties. + * @return {WPElement} Text transform edit element. + */ +export function TextTransformEdit( props ) { + const { + attributes: { style }, + setAttributes, + } = props; + const textTransforms = useEditorFeature( 'typography.textTransforms' ); + const isDisabled = useIsTextTransformDisabled( props ); + + if ( isDisabled ) { + return null; + } + + const textTransform = getTextTransformFromAttributeValue( + textTransforms, + style?.typography?.textTransform + ); + + function onChange( newTransform ) { + setAttributes( { + style: cleanEmptyObject( { + ...style, + typography: { + ...style?.typography, + textTransform: newTransform, + }, + } ), + } ); + } + + return ( + + ); +} + +/** + * Checks if text-transform settings have been disabled. + * + * @param {string} name Name of the block. + * @return {boolean} Whether or not the setting is disabled. + */ +export function useIsTextTransformDisabled( { name: blockName } = {} ) { + const notSupported = ! hasBlockSupport( + blockName, + TEXT_TRANSFORM_SUPPORT_KEY + ); + const textTransforms = useEditorFeature( 'typography.textTransforms' ); + const hasTextTransforms = !! textTransforms?.length; + + return notSupported || ! hasTextTransforms; +} + +/** + * Extracts the current text transform selection, if available, from the CSS + * variable set as the `styles.typography.textTransform` attribute. + * + * @param {Array} textTransforms Available text transforms as defined in theme.json. + * @param {string} value Attribute value in `styles.typography.textTransform` + * @return {string} Actual text transform value + */ +const getTextTransformFromAttributeValue = ( textTransforms, value ) => { + const attributeParsed = /var:preset\|text-transform\|(.+)/.exec( value ); + + if ( attributeParsed && attributeParsed[ 1 ] ) { + return textTransforms.find( + ( { slug } ) => slug === attributeParsed[ 1 ] + )?.slug; + } + + return value; +}; diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index 49a281cb219eaf..4aa3e9ee85963f 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -21,10 +21,16 @@ import { FontSizeEdit, useIsFontSizeDisabled, } from './font-size'; +import { + TEXT_TRANSFORM_SUPPORT_KEY, + TextTransformEdit, + useIsTextTransformDisabled, +} from './text-transform'; export const TYPOGRAPHY_SUPPORT_KEYS = [ LINE_HEIGHT_SUPPORT_KEY, FONT_SIZE_SUPPORT_KEY, + TEXT_TRANSFORM_SUPPORT_KEY, ]; export function TypographyPanel( props ) { @@ -37,6 +43,7 @@ export function TypographyPanel( props ) { + @@ -56,6 +63,7 @@ function useIsTypographyDisabled( props = {} ) { const configs = [ useIsFontSizeDisabled( props ), useIsLineHeightDisabled( props ), + useIsTextTransformDisabled( props ), ]; return configs.filter( Boolean ).length === configs.length; diff --git a/packages/block-library/src/heading/block.json b/packages/block-library/src/heading/block.json index 50bf37cdaefa5d..c88f30200ac139 100644 --- a/packages/block-library/src/heading/block.json +++ b/packages/block-library/src/heading/block.json @@ -29,6 +29,7 @@ }, "fontSize": true, "lineHeight": true, + "__experimentalTextTransform": true, "__experimentalSelector": { "core/heading/h1": "h1", "core/heading/h2": "h2", diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js index 18488d1db55f79..7b6df1970ef639 100644 --- a/packages/blocks/src/api/constants.js +++ b/packages/blocks/src/api/constants.js @@ -18,6 +18,7 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = { backgroundColor: [ 'color', 'background' ], color: [ 'color', 'text' ], fontSize: [ 'typography', 'fontSize' ], + textTransform: [ 'typography', 'textTransform' ], lineHeight: [ 'typography', 'lineHeight' ], paddingBottom: [ 'spacing', 'padding', 'bottom' ], paddingLeft: [ 'spacing', 'padding', 'left' ], diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js index 3e4044be2f0253..b1a9492bbf420f 100644 --- a/packages/edit-site/src/components/editor/utils.js +++ b/packages/edit-site/src/components/editor/utils.js @@ -13,6 +13,7 @@ export const PRESET_CATEGORIES = { color: { path: [ 'color', 'palette' ], key: 'color' }, gradient: { path: [ 'color', 'gradients' ], key: 'gradient' }, fontSize: { path: [ 'typography', 'fontSizes' ], key: 'size' }, + textTransform: { path: [ 'typography', 'textTransforms' ], key: 'slug' }, }; export const LINK_COLOR = '--wp--style--color--link'; export const LINK_COLOR_DECLARATION = `a { color: var(${ LINK_COLOR }, #00e); }`; From 2c2b141bf6174c599823d7e3ab8126226ccf8ee8 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 14 Oct 2020 13:15:33 +1000 Subject: [PATCH 2/8] Add config for block preset classes --- lib/global-styles.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/global-styles.php b/lib/global-styles.php index 0e32cce3355f71..931c219ec168d0 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -626,6 +626,11 @@ function gutenberg_experimental_global_styles_get_preset_classes( $selector, $se 'key' => 'size', 'property' => 'font-size', ), + 'text-transform' => array( + 'path' => array( 'typography', 'textTransforms' ), + 'key' => 'slug', + 'property' => 'text-transform', + ), ); foreach ( $classes_structure as $class_suffix => $preset_structure ) { From a20ff2f39d5742c16099be84945c5673adfa3578 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 16 Oct 2020 14:22:48 +1000 Subject: [PATCH 3/8] Update text transform controls --- .../components/text-transform-control/index.js | 18 ++++++++++++++---- .../text-transform-control/style.scss | 10 ++++++++++ packages/block-editor/src/style.scss | 1 + 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 packages/block-editor/src/components/text-transform-control/style.scss diff --git a/packages/block-editor/src/components/text-transform-control/index.js b/packages/block-editor/src/components/text-transform-control/index.js index e66e6d6cdbd009..04ca0b2d5f6478 100644 --- a/packages/block-editor/src/components/text-transform-control/index.js +++ b/packages/block-editor/src/components/text-transform-control/index.js @@ -43,25 +43,35 @@ export default function TextTransformControl( { onChange( newTextTransform ); }; + // Text transform icons to use. + // Icons still to be created/designed. + const icons = { + capitalize: undefined, + lowercase: undefined, + uppercase: undefined, + }; + return ( - <> -

{ __( 'Text Transform' ) }

+
+ { __( 'Text Transform' ) } { textTransforms.map( ( presetTransform ) => { return ( ); } ) } - +
); } diff --git a/packages/block-editor/src/components/text-transform-control/style.scss b/packages/block-editor/src/components/text-transform-control/style.scss new file mode 100644 index 00000000000000..fa45d4ff297bd3 --- /dev/null +++ b/packages/block-editor/src/components/text-transform-control/style.scss @@ -0,0 +1,10 @@ +.block-editor-text-transform-control { + legend { + margin-bottom: 8px; + } + + .components-button-group { + display: inline-flex; + margin-bottom: 24px; + } +} diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 096eb3bacb7969..f437e862d456a2 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -43,6 +43,7 @@ @import "./components/rich-text/format-toolbar/style.scss"; @import "./components/rich-text/style.scss"; @import "./components/skip-to-selected-block/style.scss"; +@import "./components/text-transform-control/style.scss"; @import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; @import "./components/url-popover/style.scss"; From fe63bfd3fa07dc3e6deda0775db62e10531fc753 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Fri, 16 Oct 2020 14:38:37 +1000 Subject: [PATCH 4/8] Fix PHPCS errors --- lib/global-styles.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/global-styles.php b/lib/global-styles.php index 931c219ec168d0..650d21c703dd51 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -443,15 +443,15 @@ function gutenberg_experimental_global_styles_get_support_keys() { */ function gutenberg_experimental_global_styles_get_presets_structure() { return array( - 'color' => array( + 'color' => array( 'path' => array( 'color', 'palette' ), 'key' => 'color', ), - 'gradient' => array( + 'gradient' => array( 'path' => array( 'color', 'gradients' ), 'key' => 'gradient', ), - 'fontSize' => array( + 'fontSize' => array( 'path' => array( 'typography', 'fontSizes' ), 'key' => 'size', ), From 0b6fd63e5ba7e233b9f012b102d94e344dfc59a7 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Wed, 21 Oct 2020 17:51:27 +1000 Subject: [PATCH 5/8] Allow for text transform controls alongside decoration The direction the design is headed it to display text decoration and text transform controls side-by-side. This commit provides a new component to handle grouping these together and arranging them within a flex container. It also makes minor tweaks like labelling the controls "Letter case" instead of "Text Transform" and using plain text to provide something like the icons will be. --- lib/experimental-default-theme.json | 10 +++--- .../text-decoration-and-transform/index.js | 35 +++++++++++++++++++ .../text-decoration-and-transform/style.scss | 3 ++ .../text-transform-control/index.js | 9 ++--- .../text-transform-control/style.scss | 10 +++++- packages/block-editor/src/hooks/typography.js | 4 +-- packages/block-editor/src/style.scss | 1 + 7 files changed, 60 insertions(+), 12 deletions(-) create mode 100644 packages/block-editor/src/components/text-decoration-and-transform/index.js create mode 100644 packages/block-editor/src/components/text-decoration-and-transform/style.scss diff --git a/lib/experimental-default-theme.json b/lib/experimental-default-theme.json index 9775224079f919..2e49877e50e136 100644 --- a/lib/experimental-default-theme.json +++ b/lib/experimental-default-theme.json @@ -163,16 +163,16 @@ ], "textTransforms": [ { - "name": "Capitalize", - "slug": "capitalize" + "name": "AB", + "slug": "uppercase" }, { - "name": "Lowercase", + "name": "ab", "slug": "lowercase" }, { - "name": "Uppercase", - "slug": "uppercase" + "name": "Ab", + "slug": "capitalize" } ] }, diff --git a/packages/block-editor/src/components/text-decoration-and-transform/index.js b/packages/block-editor/src/components/text-decoration-and-transform/index.js new file mode 100644 index 00000000000000..38f589949627a7 --- /dev/null +++ b/packages/block-editor/src/components/text-decoration-and-transform/index.js @@ -0,0 +1,35 @@ +/** + * Internal dependencies + */ +import { + TextTransformEdit, + useIsTextTransformDisabled, +} from '../../hooks/text-transform'; + +/** + * Handles grouping related text decoration and text transform edit components + * so they can be laid out in a more flexible manner within the Typography + * InspectorControls panel. + * + * @param {Object} props Block props to be passed on to individual controls. + * @return {WPElement} Component containing text decoration or transform controls. + */ +export default function TextDecorationAndTransformEdit( props ) { + // Once text decorations block support is added additional checks will + // need to be added below and it's edit component included. + const transformAvailable = ! useIsTextTransformDisabled( props ); + + if ( ! transformAvailable ) { + return null; + } + + return ( + <> + { transformAvailable && ( +
+ { transformAvailable && } +
+ ) } + + ); +} diff --git a/packages/block-editor/src/components/text-decoration-and-transform/style.scss b/packages/block-editor/src/components/text-decoration-and-transform/style.scss new file mode 100644 index 00000000000000..3f62e923036a4b --- /dev/null +++ b/packages/block-editor/src/components/text-decoration-and-transform/style.scss @@ -0,0 +1,3 @@ +.block-editor-text-decoration-and-transform { + display: flex; +} diff --git a/packages/block-editor/src/components/text-transform-control/index.js b/packages/block-editor/src/components/text-transform-control/index.js index 04ca0b2d5f6478..901cb87df845b2 100644 --- a/packages/block-editor/src/components/text-transform-control/index.js +++ b/packages/block-editor/src/components/text-transform-control/index.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { Button, ButtonGroup } from '@wordpress/components'; +import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; /** @@ -53,13 +53,14 @@ export default function TextTransformControl( { return (
- { __( 'Text Transform' ) } - + { __( 'Letter case' ) } +
{ textTransforms.map( ( presetTransform ) => { return ( ); } ) } - +
); } diff --git a/packages/block-editor/src/components/text-transform-control/style.scss b/packages/block-editor/src/components/text-transform-control/style.scss index fa45d4ff297bd3..09280029a971aa 100644 --- a/packages/block-editor/src/components/text-transform-control/style.scss +++ b/packages/block-editor/src/components/text-transform-control/style.scss @@ -1,10 +1,18 @@ .block-editor-text-transform-control { + flex: 0 0 50%; + legend { margin-bottom: 8px; } - .components-button-group { + .block-editor-text-transform-control__buttons { display: inline-flex; margin-bottom: 24px; + + .components-button.has-icon { + min-width: 24px; + padding: 0; + margin-right: 4px; + } } } diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js index 4aa3e9ee85963f..3ddf6b011eca87 100644 --- a/packages/block-editor/src/hooks/typography.js +++ b/packages/block-editor/src/hooks/typography.js @@ -10,6 +10,7 @@ import { __ } from '@wordpress/i18n'; * Internal dependencies */ import InspectorControls from '../components/inspector-controls'; +import TextDecorationAndTransformEdit from '../components/text-decoration-and-transform'; import { LINE_HEIGHT_SUPPORT_KEY, @@ -23,7 +24,6 @@ import { } from './font-size'; import { TEXT_TRANSFORM_SUPPORT_KEY, - TextTransformEdit, useIsTextTransformDisabled, } from './text-transform'; @@ -43,8 +43,8 @@ export function TypographyPanel( props ) { - + ); diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index f437e862d456a2..318c5b349b551f 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -43,6 +43,7 @@ @import "./components/rich-text/format-toolbar/style.scss"; @import "./components/rich-text/style.scss"; @import "./components/skip-to-selected-block/style.scss"; +@import "./components/text-decoration-and-transform/style.scss"; @import "./components/text-transform-control/style.scss"; @import "./components/tool-selector/style.scss"; @import "./components/url-input/style.scss"; From 23967b1227a0bf00144dd6ef941f0405ed572266 Mon Sep 17 00:00:00 2001 From: Aaron Robertshaw <60436221+aaronrobertshaw@users.noreply.github.com> Date: Thu, 22 Oct 2020 15:12:42 +1000 Subject: [PATCH 6/8] Add new icons for text transforms --- .../src/components/text-transform-control/index.js | 12 ++++++++---- packages/icons/src/index.js | 3 +++ packages/icons/src/library/format-capitalize.js | 12 ++++++++++++ packages/icons/src/library/format-lowercase.js | 12 ++++++++++++ packages/icons/src/library/format-uppercase.js | 12 ++++++++++++ 5 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 packages/icons/src/library/format-capitalize.js create mode 100644 packages/icons/src/library/format-lowercase.js create mode 100644 packages/icons/src/library/format-uppercase.js diff --git a/packages/block-editor/src/components/text-transform-control/index.js b/packages/block-editor/src/components/text-transform-control/index.js index 901cb87df845b2..545fed8407f398 100644 --- a/packages/block-editor/src/components/text-transform-control/index.js +++ b/packages/block-editor/src/components/text-transform-control/index.js @@ -3,6 +3,11 @@ */ import { Button } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; +import { + formatCapitalize, + formatLowercase, + formatUppercase, +} from '@wordpress/icons'; /** * Control to facilitate text transform selections. @@ -46,9 +51,9 @@ export default function TextTransformControl( { // Text transform icons to use. // Icons still to be created/designed. const icons = { - capitalize: undefined, - lowercase: undefined, - uppercase: undefined, + capitalize: formatCapitalize, + lowercase: formatLowercase, + uppercase: formatUppercase, }; return ( @@ -60,7 +65,6 @@ export default function TextTransformControl( {