Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Support: Separate opt in for font style and weight options #26844

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/designers-developers/developers/themes/theme-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ The settings section has the following structure and default values:
"dropCap": true, /* false to opt-out */
"fontFamilies": [ ... ], /* font family presets */
"fontSizes": [ ... ], /* font size presets, as in add_theme_support('editor-font-sizes', ... ) */
"fontStyles": [ ... ], /* font style presets */
"fontWeights": [ ... ], /* font weight presets */
"textDecorations": [ ... ], /* text decoration presets */
"textTransforms": [ ... ] /* text transform presets */
Expand Down
21 changes: 16 additions & 5 deletions lib/block-supports/typography.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ function gutenberg_register_typography_support( $block_type ) {
return;
}

$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_font_style_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontStyle' ), false );
$has_font_weight_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontWeight' ), 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;

$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;

if ( ! $block_type->attributes ) {
$block_type->attributes = array();
Expand Down Expand Up @@ -57,8 +64,9 @@ 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_family_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontFamily' ), false );
$has_font_style_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontStyle' ), false );
$has_font_weight_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontWeight' ), 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 @@ -94,14 +102,17 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
}
}

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

// Font weight.
if ( $has_font_weight_support ) {
// Apply font weight.
$font_weight = gutenberg_typography_get_css_variable_inline_style( $block_attributes, 'fontWeight', 'font-weight' );
if ( $font_weight ) {
Expand Down
8 changes: 4 additions & 4 deletions lib/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class WP_Theme_JSON {
),
array(
'path' => array( 'settings', 'typography', 'fontStyles' ),
'value_key' => 'slug',
'value_key' => 'value',
'css_var_infix' => 'font-style',
'classes' => array(
array(
Expand All @@ -232,7 +232,7 @@ class WP_Theme_JSON {
),
array(
'path' => array( 'settings', 'typography', 'fontWeights' ),
'value_key' => 'slug',
'value_key' => 'value',
'css_var_infix' => 'font-weight',
'classes' => array(
array(
Expand Down Expand Up @@ -300,11 +300,11 @@ class WP_Theme_JSON {
),
'fontStyle' => array(
'value' => array( 'typography', 'fontStyle' ),
'support' => array( '__experimentalFontAppearance' ),
'support' => array( '__experimentalFontStyle' ),
),
'fontWeight' => array(
'value' => array( 'typography', 'fontWeight' ),
'support' => array( '__experimentalFontAppearance' ),
'support' => array( '__experimentalFontWeight' ),
),
'lineHeight' => array(
'value' => array( 'typography', 'lineHeight' ),
Expand Down
33 changes: 22 additions & 11 deletions lib/experimental-default-theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,49 +164,60 @@
"fontStyles": [
{
"name": "Regular",
"slug": "normal"
"slug": "normal",
"value": "normal"
},
{
"name": "Italic",
"slug": "italic"
"slug": "italic",
"value": "italic"
}
],
"fontWeights": [
{
"name": "Ultralight",
"slug": "100"
"slug": "100",
"value": "100"
},
{
"name": "Thin",
"slug": "200"
"slug": "200",
"value": "200"
},
{
"name": "Light",
"slug": "300"
"slug": "300",
"value": "300"
},
{
"name": "Regular",
"slug": "400"
"slug": "400",
"value": "400"
},
{
"name": "Medium",
"slug": "500"
"slug": "500",
"value": "500"
},
{
"name": "Semibold",
"slug": "600"
"slug": "600",
"value": "600"
},
{
"name": "Bold",
"slug": "700"
"slug": "700",
"value": "700"
},
{
"name": "Heavy",
"slug": "800"
"slug": "800",
"value": "800"
},
{
"name": "Black",
"slug": "900"
"slug": "900",
"value": "900"
}
],
"textTransforms": [
Expand Down
2 changes: 1 addition & 1 deletion lib/global-styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ function gutenberg_experimental_global_styles_get_stylesheet( $tree ) {

if ( $can_use_cached ) {
// Cache for a minute.
// This cache doesn't need to be any longer, we only want to avoid spikes on high-trafic sites.
// This cache doesn't need to be any longer, we only want to avoid spikes on high-traffic sites.
set_transient( 'global_styles', $stylesheet, MINUTE_IN_SECONDS );
}

Expand Down
121 changes: 85 additions & 36 deletions packages/block-editor/src/components/font-appearance-control/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,72 +3,121 @@
*/
import { CustomSelectControl } from '@wordpress/components';
import { useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { __, sprintf } 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.
* @param {Object} props Component props.
* @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;
export default function FontAppearanceControl( props ) {
const {
onChange,
options: { fontStyles = [], fontWeights = [] },
value: { fontStyle, fontWeight },
} = props;
const hasStyles = !! fontStyles.length;
const hasWeights = !! fontWeights.length;
const hasStylesOrWeights = hasStyles || hasWeights;
const defaultOption = {
key: 'default',
name: __( 'Default' ),
style: { fontStyle: undefined, fontWeight: undefined },
};

// 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,
},
];
// Combines both font style and weight options into a single dropdown.
const combineOptions = () => {
const combinedOptions = [ defaultOption ];

fontStyles.forEach( ( { name: styleName, slug: styleSlug } ) => {
fontWeights.forEach( ( { name: weightName, slug: weightSlug } ) => {
const optionName =
styleSlug === 'normal'
? weightName
: sprintf(
/* translators: 1: Font weight name. 2: Font style name. */
__( '%1$s %2$s' ),
weightName,
styleName
);

combinedOptions.push( {
key: `${ weightSlug }-${ styleSlug }`,
name:
styleSlug === 'normal'
? weightName
: `${ weightName } ${ styleName }`,
// style applies font appearance to the individual select option.
name: optionName,
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 ] );
};

// Generates select options for font styles only.
const styleOptions = () => {
const combinedOptions = [ defaultOption ];
fontStyles.forEach( ( { name, slug } ) => {
combinedOptions.push( {
key: slug,
name,
style: { fontStyle: slug, fontWeight: undefined },
} );
} );
return combinedOptions;
};

// Generates select options for font weights only.
const weightOptions = () => {
const combinedOptions = [ defaultOption ];
fontWeights.forEach( ( { name, slug } ) => {
combinedOptions.push( {
key: slug,
name,
style: { fontStyle: undefined, fontWeight: slug },
} );
} );
return combinedOptions;
};

// Map font styles and weights to select options.
const selectOptions = useMemo( () => {
if ( hasStyles && hasWeights ) {
return combineOptions();
}

return hasStyles ? styleOptions() : weightOptions();
}, [ props.options ] );

// Find current selection by comparing font style & weight against options.
const currentSelection = selectOptions.find(
( option ) =>
option.presetStyle.fontStyle === fontStyle &&
option.presetStyle.fontWeight === fontWeight
option.style.fontStyle === fontStyle &&
option.style.fontWeight === fontWeight
);

// Adjusts field label in case either styles or weights are disabled.
const getLabel = () => {
if ( ! hasStyles ) {
return __( 'Font weight' );
}

if ( ! hasWeights ) {
return __( 'Font style' );
}

return __( 'Appearance' );
};

return (
<fieldset className="components-font-appearance-control">
{ hasStylesOrWeights && (
<CustomSelectControl
className="components-font-appearance-control__select"
label={ __( 'Appearance' ) }
label={ getLabel() }
options={ selectOptions }
value={ currentSelection }
onChange={ ( { selectedItem } ) =>
onChange( selectedItem.presetStyle )
onChange( selectedItem.style )
}
/>
) }
Expand Down
Loading