Skip to content

Commit

Permalink
Block Support: Add font style and weight options with combined UI (#2…
Browse files Browse the repository at this point in the history
…6444)

* Add combined font style and weight block support

Adds both font style and font weight block support options. The UI for both are combined into a single dropdown. The inline styles generated via this feature leverage CSS variables.

* Update styling of font appearance list items
  • Loading branch information
aaronrobertshaw authored Nov 6, 2020
1 parent 120fc88 commit 1d9c07a
Show file tree
Hide file tree
Showing 12 changed files with 329 additions and 28 deletions.
61 changes: 34 additions & 27 deletions lib/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,22 @@
* @param WP_Block_Type $block_type Block Type.
*/
function gutenberg_register_typography_support( $block_type ) {
$has_font_size_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_font_size_support = gutenberg_experimental_get( $block_type->supports, array( 'fontSize' ), false );
}

$has_line_height_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$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 ( ! property_exists( $block_type, 'supports' ) ) {
return;
}

$has_text_decoration_support = false;
if ( property_exists( $block_type, 'supports' ) ) {
$has_text_decoration_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextDecoration' ), false );
}
$has_font_appearance_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontAppearance' ), false );
$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_decoration_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextDecoration' ), false );
$has_text_transform_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextTransform' ), false );
$has_typography_support = $has_font_appearance_support || $has_font_size_support || $has_line_height_support || $has_text_transform_support || $has_text_decoration_support;

if ( ! $block_type->attributes ) {
$block_type->attributes = array();
}

if ( ( $has_font_size_support || $has_line_height_support || $has_text_transform_support || $has_text_decoration_support ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
if ( $has_typography_support && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
Expand Down Expand Up @@ -65,6 +56,7 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
$classes = array();
$styles = array();

$has_font_appearance_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontAppearance' ), false );
$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_decoration_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalTextDecoration' ), false );
Expand Down Expand Up @@ -105,6 +97,21 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
}
}

// Font appearance - style and weight.
if ( $has_font_appearance_support ) {
// Apply font style.
$font_style = gutenberg_typography_get_css_variable_inline_style( $block_attributes, 'fontStyle', 'font-style' );
if ( $font_style ) {
$styles[] = $font_style;
}

// Apply font weight.
$font_weight = gutenberg_typography_get_css_variable_inline_style( $block_attributes, 'fontWeight', 'font-weight' );
if ( $font_weight ) {
$styles[] = $font_weight;
}
}

// Line Height.
if ( $has_line_height_support ) {
$has_line_height = isset( $block_attributes['style']['typography']['lineHeight'] );
Expand Down Expand Up @@ -141,15 +148,6 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
return $attributes;
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'typography',
array(
'register_attribute' => 'gutenberg_register_typography_support',
'apply' => 'gutenberg_apply_typography_support',
)
);

/**
* Generates an inline style for a typography feature e.g. text decoration,
* text transform, and font style.
Expand Down Expand Up @@ -180,3 +178,12 @@ function gutenberg_typography_get_css_variable_inline_style( $attributes, $featu
// 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 );
}

// Register the block support.
WP_Block_Supports::get_instance()->register(
'typography',
array(
'register_attribute' => 'gutenberg_register_typography_support',
'apply' => 'gutenberg_apply_typography_support',
)
);
48 changes: 48 additions & 0 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,54 @@
"size": 42
}
],
"fontStyles": [
{
"name": "Regular",
"slug": "normal"
},
{
"name": "Italic",
"slug": "italic"
}
],
"fontWeights": [
{
"name": "Ultralight",
"slug": "100"
},
{
"name": "Thin",
"slug": "200"
},
{
"name": "Light",
"slug": "300"
},
{
"name": "Regular",
"slug": "400"
},
{
"name": "Medium",
"slug": "500"
},
{
"name": "Semibold",
"slug": "600"
},
{
"name": "Bold",
"slug": "700"
},
{
"name": "Heavy",
"slug": "800"
},
{
"name": "Black",
"slug": "900"
}
],
"textTransforms": [
{
"name": "AB",
Expand Down
61 changes: 61 additions & 0 deletions lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,40 @@ function gutenberg_experimental_global_styles_get_core() {
$font_size['name'] = $default_font_sizes_i18n[ $font_size['slug'] ];
}
}

$default_font_styles_i18n = array(
'normal' => __( 'Regular', 'gutenberg' ),
'italic' => __( 'Italic', 'gutenberg' ),
'initial' => __( 'Initial', 'gutenberg' ),
'inherit' => __( 'Inherit', 'gutenberg' ),
);

if ( ! empty( $config['global']['settings']['typography']['fontStyles'] ) ) {
foreach ( $config['global']['settings']['typography']['fontStyles'] as &$font_style ) {
$font_style['name'] = $default_font_styles_i18n[ $font_style['slug'] ];
}
}

$default_font_weights_i18n = array(
'100' => __( 'Ultralight', 'gutenberg' ),
'200' => __( 'Thin', 'gutenberg' ),
'300' => __( 'Light', 'gutenberg' ),
'400' => __( 'Regular', 'gutenberg' ),
'500' => __( 'Medium', 'gutenberg' ),
'600' => __( 'Semibold', 'gutenberg' ),
'700' => __( 'Bold', 'gutenberg' ),
'800' => __( 'Heavy', 'gutenberg' ),
'900' => __( 'Black', 'gutenberg' ),
'initial' => __( 'Initial', 'gutenberg' ),
'inherit' => __( 'Inherit', 'gutenberg' ),
);

if ( ! empty( $config['global']['settings']['typography']['fontWeights'] ) ) {
foreach ( $config['global']['settings']['typography']['fontWeights'] as &$font_weight ) {
$font_weight['name'] = $default_font_weights_i18n[ $font_weight['slug'] ];
}
}

// End i18n logic to remove when JSON i18 strings are extracted.
return $config;
}
Expand Down Expand Up @@ -393,6 +427,10 @@ function gutenberg_experimental_global_styles_get_css_property( $style_property
return 'background-color';
case 'fontSize':
return 'font-size';
case 'fontStyle':
return 'font-style';
case 'fontWeight':
return 'font-weight';
case 'lineHeight':
return 'line-height';
case 'fontFamily':
Expand All @@ -419,6 +457,8 @@ function gutenberg_experimental_global_styles_get_style_property() {
'color' => array( 'color', 'text' ),
'fontSize' => array( 'typography', 'fontSize' ),
'fontFamily' => array( 'typography', 'fontFamily' ),
'fontStyle' => array( 'typography', 'fontStyle' ),
'fontWeight' => array( 'typography', 'fontWeight' ),
'lineHeight' => array( 'typography', 'lineHeight' ),
'textDecoration' => array( 'typography', 'textDecoration' ),
'textTransform' => array( 'typography', 'textTransform' ),
Expand All @@ -437,6 +477,8 @@ function gutenberg_experimental_global_styles_get_support_keys() {
'backgroundColor' => array( 'color' ),
'color' => array( 'color' ),
'fontSize' => array( 'fontSize' ),
'fontStyle' => array( '__experimentalFontAppearance' ),
'fontWeight' => array( '__experimentalFontAppearance' ),
'lineHeight' => array( 'lineHeight' ),
'fontFamily' => array( '__experimentalFontFamily' ),
'textDecoration' => array( '__experimentalTextDecoration' ),
Expand Down Expand Up @@ -467,6 +509,14 @@ function gutenberg_experimental_global_styles_get_presets_structure() {
'path' => array( 'typography', 'fontFamilies' ),
'key' => 'fontFamily',
),
'fontStyle' => array(
'path' => array( 'typography', 'fontStyles' ),
'key' => 'slug',
),
'fontWeight' => array(
'path' => array( 'typography', 'fontWeights' ),
'key' => 'slug',
),
'textDecoration' => array(
'path' => array( 'typography', 'textDecorations' ),
'key' => 'value',
Expand Down Expand Up @@ -514,6 +564,7 @@ function gutenberg_experimental_global_styles_get_block_data() {
array(
'supports' => array(
'__experimentalSelector' => ':root',
'__experimentalFontAppearance' => false,
'__experimentalFontFamily' => true,
'fontSize' => true,
'__experimentalTextDecoration' => true,
Expand Down Expand Up @@ -653,6 +704,16 @@ function gutenberg_experimental_global_styles_get_preset_classes( $selector, $se
'key' => 'size',
'property' => 'font-size',
),
'font-style' => array(
'path' => array( 'typography', 'fontStyles' ),
'key' => 'slug',
'property' => 'font-style',
),
'font-weight' => array(
'path' => array( 'typography', 'fontWeights' ),
'key' => 'slug',
'property' => 'font-weight',
),
'text-decoration' => array(
'path' => array( 'typography', 'textDecorations' ),
'key' => 'value',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* WordPress dependencies
*/
import { CustomSelectControl } from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';

/**
* Control to display unified font style and weight options.
*
* @param {Object} props Component props.
* @param {Object} props.value Currently selected combination of font style and weight.
* @param {Object} props.options Object containing weight and style options.
* @param {Function} props.onChange Handles selection change.
* @return {WPElement} Font appearance control.
*/
export default function FontAppearanceControl( { value, options, onChange } ) {
const { fontStyle, fontWeight } = value;
const { fontStyles = [], fontWeights = [] } = options;
const hasStylesOrWeights = fontStyles.length > 0 || fontWeights.length > 0;

// Map font styles and weights to select options.
const selectOptions = useMemo( () => {
const defaultCombo = { fontStyle: undefined, fontWeight: undefined };
const combinedOptions = [
{
key: 'default',
name: __( 'Default' ),
style: defaultCombo,
presetStyle: defaultCombo,
},
];

fontStyles.forEach( ( { name: styleName, slug: styleSlug } ) => {
fontWeights.forEach( ( { name: weightName, slug: weightSlug } ) => {
combinedOptions.push( {
key: `${ weightSlug }-${ styleSlug }`,
name:
styleSlug === 'normal'
? weightName
: `${ weightName } ${ styleName }`,
// style applies font appearance to the individual select option.
style: { fontStyle: styleSlug, fontWeight: weightSlug },
// presetStyle are the actual typography styles that should be given to onChange.
presetStyle: {
fontStyle: `var:preset|font-style|${ styleSlug }`,
fontWeight: `var:preset|font-weight|${ weightSlug }`,
},
} );
} );
} );

return combinedOptions;
}, [ options ] );

const currentSelection = selectOptions.find(
( option ) =>
option.presetStyle.fontStyle === fontStyle &&
option.presetStyle.fontWeight === fontWeight
);

return (
<fieldset className="components-font-appearance-control">
{ hasStylesOrWeights && (
<CustomSelectControl
className="components-font-appearance-control__select"
label={ __( 'Appearance' ) }
options={ selectOptions }
value={ currentSelection }
onChange={ ( { selectedItem } ) =>
onChange( selectedItem.presetStyle )
}
/>
) }
</fieldset>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.components-font-appearance-control__select {
margin-bottom: 24px;

ul {
li {
color: $gray-900;
text-transform: capitalize;
}
}
}
Loading

0 comments on commit 1d9c07a

Please sign in to comment.