Skip to content

Commit

Permalink
Block Support: Add text transform block support using CSS variables (#…
Browse files Browse the repository at this point in the history
…26060)

* Add text transform block support

* Add config for block preset classes

* Update text transform controls

* Fix PHPCS errors

* 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.

* Add new icons for text transforms

* Switch to only opting in for navigation block

* Fix return value regression after resolving merge conflict
  • Loading branch information
aaronrobertshaw authored Nov 3, 2020
1 parent fb1cc0e commit 4474833
Show file tree
Hide file tree
Showing 17 changed files with 375 additions and 16 deletions.
63 changes: 53 additions & 10 deletions lib/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
);
Expand All @@ -48,17 +53,16 @@ function gutenberg_register_typography_support( $block_type ) {
* @return array Font size CSS classes and inline styles.
*/
function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
$has_font_size_support = false;
$classes = array();
$styles = array();
if ( property_exists( $block_type, 'supports' ) ) {
$has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( 'fontSize' ), false );
if ( ! property_exists( $block_type, 'supports' ) ) {
return array();
}

$has_line_height_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( 'lineHeight' ), false );
}
$classes = array();
$styles = array();

$has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( 'fontSize' ), false );
$has_line_height_support = gutenberg_experimental_get( $block_type->supports, array( 'lineHeight' ), false );
$has_text_transform_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextTransform' ), false );

// Font Size.
if ( $has_font_size_support ) {
Expand All @@ -82,6 +86,14 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
}
}

// Text Transform.
if ( $has_text_transform_support ) {
$text_transform_style = gutenberg_typography_get_css_variable_inline_style( $block_attributes, 'textTransform', 'text-transform' );
if ( $text_transform_style ) {
$styles[] = $text_transform_style;
}
}

$attributes = array();
if ( ! empty( $classes ) ) {
$attributes['class'] = implode( ' ', $classes );
Expand All @@ -101,3 +113,34 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
'apply' => 'gutenberg_apply_typography_support',
)
);

/**
* Generates an inline style for a typography feature e.g. text decoration,
* text transform, and font style.
*
* @param array $attributes Block's attributes.
* @param string $feature Key for the feature within the typography styles.
* @param string $css_property Slug for the CSS property the inline style sets.
*
* @return string CSS inline style.
*/
function gutenberg_typography_get_css_variable_inline_style( $attributes, $feature, $css_property ) {
// Retrieve current attribute value or skip if not found.
$style_value = gutenberg_experimental_get( $attributes, array( 'style', 'typography', $feature ), false );
if ( ! $style_value ) {
return;
}

// If we don't have a preset CSS variable, we'll assume it's a regular CSS value.
if ( strpos( $style_value, "var:preset|{$css_property}|" ) === false ) {
return sprintf( '%s:%s;', $css_property, $style_value );
}

// We have a preset CSS variable as the style.
// Get the style value from the string and return CSS style.
$index_to_splice = strrpos( $style_value, '|' ) + 1;
$slug = substr( $style_value, $index_to_splice );

// Return the actual CSS inline style e.g. `text-decoration:var(--wp--preset--text-decoration--underline);`.
return sprintf( '%s:var(--wp--preset--%s--%s);', $css_property, $css_property, $slug );
}
14 changes: 14 additions & 0 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,20 @@
"slug": "huge",
"size": 42
}
],
"textTransforms": [
{
"name": "AB",
"slug": "uppercase"
},
{
"name": "ab",
"slug": "lowercase"
},
{
"name": "Ab",
"slug": "capitalize"
}
]
},
"spacing": {
Expand Down
26 changes: 20 additions & 6 deletions lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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' ),
);
}

Expand All @@ -429,6 +432,7 @@ function gutenberg_experimental_global_styles_get_support_keys() {
'color' => array( 'color' ),
'fontSize' => array( 'fontSize' ),
'lineHeight' => array( 'lineHeight' ),
'textTransform' => array( '__experimentalTextTransform' ),
);
}

Expand All @@ -439,18 +443,22 @@ 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',
),
'textTransform' => array(
'path' => array( 'typography', 'textTransforms' ),
'key' => 'slug',
),
);
}

Expand Down Expand Up @@ -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,
),
Expand Down Expand Up @@ -626,6 +635,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 ) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 && (
<div className="block-editor-text-decoration-and-transform">
{ transformAvailable && <TextTransformEdit { ...props } /> }
</div>
) }
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.block-editor-text-decoration-and-transform {
display: flex;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/**
* WordPress dependencies
*/
import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import {
formatCapitalize,
formatLowercase,
formatUppercase,
} from '@wordpress/icons';

/**
* 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 );
};

// Text transform icons to use.
// Icons still to be created/designed.
const icons = {
capitalize: formatCapitalize,
lowercase: formatLowercase,
uppercase: formatUppercase,
};

return (
<fieldset className="block-editor-text-transform-control">
<legend>{ __( 'Letter case' ) }</legend>
<div className="block-editor-text-transform-control__buttons">
{ textTransforms.map( ( presetTransform ) => {
return (
<Button
key={ presetTransform.slug }
icon={ icons[ presetTransform.slug ] }
isSmall
isPressed={ textTransform === presetTransform.slug }
onClick={ () =>
handleOnChange( presetTransform.slug )
}
>
{ ! icons[ presetTransform.slug ] &&
presetTransform.name }
</Button>
);
} ) }
</div>
</fieldset>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.block-editor-text-transform-control {
flex: 0 0 50%;

legend {
margin-bottom: 8px;
}

.block-editor-text-transform-control__buttons {
display: inline-flex;
margin-bottom: 24px;

.components-button.has-icon {
min-width: 24px;
padding: 0;
margin-right: 4px;
}
}
}
Loading

0 comments on commit 4474833

Please sign in to comment.