diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php
index 0f4d7dbce1939..f08a059897e32 100644
--- a/lib/block-supports/typography.php
+++ b/lib/block-supports/typography.php
@@ -64,6 +64,11 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
$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 );
+ $has_font_family_support = false;
+ if ( property_exists( $block_type, 'supports' ) ) {
+ $has_font_family_support = gutenberg_experimental_get( $block_type->supports, array( '__experimentalFontFamily' ), false );
+ }
+
// Font Size.
if ( $has_font_size_support ) {
$has_named_font_size = array_key_exists( 'fontSize', $block_attributes );
@@ -77,6 +82,23 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
}
}
+ // Font Family.
+ if ( $has_font_family_support ) {
+ $has_font_family = isset( $block_attributes['style']['typography']['fontFamily'] );
+ // Apply required class and style.
+ if ( $has_font_family ) {
+ $font_family = $block_attributes['style']['typography']['fontFamily'];
+ if ( strpos( $font_family, 'var:preset|font-family' ) !== false ) {
+ // Get the name from the string and add proper styles.
+ $index_to_splice = strrpos( $font_family, '|' ) + 1;
+ $font_family_name = substr( $font_family, $index_to_splice );
+ $styles[] = sprintf( 'font-family: var(--wp--preset--font-family--%s);', $font_family_name );
+ } else {
+ $styles[] = sprintf( 'font-family: %s;', $block_attributes['style']['color']['fontFamily'] );
+ }
+ }
+ }
+
// Line Height.
if ( $has_line_height_support ) {
$has_line_height = isset( $block_attributes['style']['typography']['lineHeight'] );
diff --git a/lib/global-styles.php b/lib/global-styles.php
index 24f0d2e168352..e83dc5bdc1ce1 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 'fontFamily':
+ return 'font-family';
case 'textTransform':
return 'text-transform';
default:
@@ -414,6 +416,7 @@ function gutenberg_experimental_global_styles_get_style_property() {
'backgroundColor' => array( 'color', 'background' ),
'color' => array( 'color', 'text' ),
'fontSize' => array( 'typography', 'fontSize' ),
+ 'fontFamily' => array( 'typography', 'fontFamily' ),
'lineHeight' => array( 'typography', 'lineHeight' ),
'textTransform' => array( 'typography', 'textTransform' ),
);
@@ -432,6 +435,7 @@ function gutenberg_experimental_global_styles_get_support_keys() {
'color' => array( 'color' ),
'fontSize' => array( 'fontSize' ),
'lineHeight' => array( 'lineHeight' ),
+ 'fontFamily' => array( '__experimentalFontFamily' ),
'textTransform' => array( '__experimentalTextTransform' ),
);
}
@@ -455,6 +459,10 @@ function gutenberg_experimental_global_styles_get_presets_structure() {
'path' => array( 'typography', 'fontSizes' ),
'key' => 'size',
),
+ 'fontFamily' => array(
+ 'path' => array( 'typography', 'fontFamilies' ),
+ 'key' => 'fontFamily',
+ ),
'textTransform' => array(
'path' => array( 'typography', 'textTransforms' ),
'key' => 'slug',
@@ -498,6 +506,7 @@ function gutenberg_experimental_global_styles_get_block_data() {
array(
'supports' => array(
'__experimentalSelector' => ':root',
+ '__experimentalFontFamily' => true,
'fontSize' => true,
'__experimentalTextTransform' => true,
'color' => array(
diff --git a/packages/block-editor/src/components/font-family/index.js b/packages/block-editor/src/components/font-family/index.js
new file mode 100644
index 0000000000000..0f15033ee55a8
--- /dev/null
+++ b/packages/block-editor/src/components/font-family/index.js
@@ -0,0 +1,53 @@
+/**
+ * External dependencies
+ */
+import { isEmpty } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { SelectControl } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import useEditorFeature from '../use-editor-feature';
+
+export default function FontFamilyControl( {
+ value = '',
+ onChange,
+ fontFamilies,
+ ...props
+} ) {
+ const blockLevelFontFamilies = useEditorFeature(
+ 'typography.fontFamilies'
+ );
+ if ( ! fontFamilies ) {
+ fontFamilies = blockLevelFontFamilies;
+ }
+
+ if ( isEmpty( fontFamilies ) ) {
+ return null;
+ }
+
+ const options = [
+ { value: '', label: __( 'Default' ) },
+ ...fontFamilies.map( ( { fontFamily, name } ) => {
+ return {
+ value: fontFamily,
+ label: name || fontFamily,
+ };
+ } ),
+ ];
+ return (
+
+ );
+}
diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js
index 021b511fe51aa..c6506c5c58f7a 100644
--- a/packages/block-editor/src/components/index.js
+++ b/packages/block-editor/src/components/index.js
@@ -29,6 +29,7 @@ export { default as ContrastChecker } from './contrast-checker';
export { default as __experimentalGradientPicker } from './gradient-picker';
export { default as __experimentalGradientPickerControl } from './gradient-picker/control';
export { default as __experimentalGradientPickerPanel } from './gradient-picker/panel';
+export { default as __experimentalFontFamilyControl } from './font-family';
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/hooks/font-family.js b/packages/block-editor/src/hooks/font-family.js
new file mode 100644
index 0000000000000..89fa784abf6e1
--- /dev/null
+++ b/packages/block-editor/src/hooks/font-family.js
@@ -0,0 +1,88 @@
+/**
+ * External dependencies
+ */
+import { find } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { hasBlockSupport } from '@wordpress/blocks';
+
+/**
+ * Internal dependencies
+ */
+import { cleanEmptyObject } from './utils';
+import useEditorFeature from '../components/use-editor-feature';
+import FontFamilyControl from '../components/font-family';
+
+export const FONT_FAMILY_SUPPORT_KEY = '__experimentalFontFamily';
+
+const getFontFamilyFromAttributeValue = ( fontFamilies, value ) => {
+ const attributeParsed = /var:preset\|font-family\|(.+)/.exec( value );
+ if ( attributeParsed && attributeParsed[ 1 ] ) {
+ return find( fontFamilies, ( { slug } ) => {
+ return slug === attributeParsed[ 1 ];
+ } ).fontFamily;
+ }
+ return value;
+};
+
+export function FontFamilyEdit( {
+ name,
+ setAttributes,
+ attributes: { style = {} },
+} ) {
+ const fontFamilies = useEditorFeature( 'typography.fontFamilies' );
+ const isDisable = useIsFontFamilyDisabled( { name } );
+
+ if ( isDisable ) {
+ return null;
+ }
+
+ const value = getFontFamilyFromAttributeValue(
+ fontFamilies,
+ style.typography?.fontFamily
+ );
+
+ function onChange( newValue ) {
+ const predefinedFontFamily = find(
+ fontFamilies,
+ ( { fontFamily } ) => fontFamily === newValue
+ );
+ setAttributes( {
+ style: cleanEmptyObject( {
+ ...style,
+ typography: {
+ ...( style.typography || {} ),
+ fontFamily: predefinedFontFamily
+ ? `var:preset|font-family|${ predefinedFontFamily.slug }`
+ : newValue || undefined,
+ },
+ } ),
+ } );
+ }
+
+ return (
+
+ );
+}
+
+/**
+ * Custom hook that checks if font-family functionality is disabled.
+ *
+ * @param {string} name The name of the block.
+ * @return {boolean} Whether setting is disabled.
+ */
+export function useIsFontFamilyDisabled( { name } ) {
+ const fontFamilies = useEditorFeature( 'typography.fontFamilies' );
+ return (
+ ! fontFamilies ||
+ fontFamilies.length === 0 ||
+ ! hasBlockSupport( name, FONT_FAMILY_SUPPORT_KEY )
+ );
+}
diff --git a/packages/block-editor/src/hooks/typography.js b/packages/block-editor/src/hooks/typography.js
index 3ddf6b011eca8..3ac9481ab1d0d 100644
--- a/packages/block-editor/src/hooks/typography.js
+++ b/packages/block-editor/src/hooks/typography.js
@@ -17,6 +17,11 @@ import {
LineHeightEdit,
useIsLineHeightDisabled,
} from './line-height';
+import {
+ FONT_FAMILY_SUPPORT_KEY,
+ FontFamilyEdit,
+ useIsFontFamilyDisabled,
+} from './font-family';
import {
FONT_SIZE_SUPPORT_KEY,
FontSizeEdit,
@@ -30,6 +35,7 @@ import {
export const TYPOGRAPHY_SUPPORT_KEYS = [
LINE_HEIGHT_SUPPORT_KEY,
FONT_SIZE_SUPPORT_KEY,
+ FONT_FAMILY_SUPPORT_KEY,
TEXT_TRANSFORM_SUPPORT_KEY,
];
@@ -42,6 +48,7 @@ export function TypographyPanel( props ) {
return (
+
@@ -63,6 +70,7 @@ function useIsTypographyDisabled( props = {} ) {
const configs = [
useIsFontSizeDisabled( props ),
useIsLineHeightDisabled( props ),
+ useIsFontFamilyDisabled( props ),
useIsTextTransformDisabled( props ),
];
diff --git a/packages/block-library/src/navigation/block.json b/packages/block-library/src/navigation/block.json
index 50e16a5a04c3b..ed05f159721f0 100644
--- a/packages/block-library/src/navigation/block.json
+++ b/packages/block-library/src/navigation/block.json
@@ -54,6 +54,7 @@
"color": {
"textColor": true,
"backgroundColor": true
- }
+ },
+ "__experimentalFontFamily": true
}
}
diff --git a/packages/block-library/src/post-title/block.json b/packages/block-library/src/post-title/block.json
index 3c8c63031bcb2..3339d39cf74df 100644
--- a/packages/block-library/src/post-title/block.json
+++ b/packages/block-library/src/post-title/block.json
@@ -35,6 +35,7 @@
},
"fontSize": true,
"lineHeight": true,
+ "__experimentalFontFamily": true,
"__experimentalSelector": {
"core/post-title/h1": "h1",
"core/post-title/h2": "h2",
diff --git a/packages/block-library/src/site-tagline/block.json b/packages/block-library/src/site-tagline/block.json
index 17220173c408e..cf7ae739576b9 100644
--- a/packages/block-library/src/site-tagline/block.json
+++ b/packages/block-library/src/site-tagline/block.json
@@ -13,6 +13,7 @@
"gradients": true
},
"fontSize": true,
- "lineHeight": true
+ "lineHeight": true,
+ "__experimentalFontFamily": true
}
}
diff --git a/packages/block-library/src/site-title/block.json b/packages/block-library/src/site-title/block.json
index bd10511fd1b3b..6e51654c1d807 100644
--- a/packages/block-library/src/site-title/block.json
+++ b/packages/block-library/src/site-title/block.json
@@ -17,6 +17,7 @@
"gradients": true
},
"fontSize": true,
- "lineHeight": true
+ "lineHeight": true,
+ "__experimentalFontFamily": true
}
}
diff --git a/packages/blocks/src/api/constants.js b/packages/blocks/src/api/constants.js
index 7b6df1970ef63..d4764dee10eda 100644
--- a/packages/blocks/src/api/constants.js
+++ b/packages/blocks/src/api/constants.js
@@ -24,4 +24,5 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
paddingLeft: [ 'spacing', 'padding', 'left' ],
paddingRight: [ 'spacing', 'padding', 'right' ],
paddingTop: [ 'spacing', 'padding', 'top' ],
+ fontFamily: [ 'typography', 'fontFamily' ],
};
diff --git a/packages/edit-site/src/components/editor/utils.js b/packages/edit-site/src/components/editor/utils.js
index ae02c64567ac4..820f1fc4363df 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' },
+ fontFamily: { path: [ 'typography', 'fontFamilies' ], key: 'fontFamily' },
textTransform: { path: [ 'typography', 'textTransforms' ], key: 'slug' },
};
export const LINK_COLOR = '--wp--style--color--link';
diff --git a/packages/edit-site/src/components/sidebar/typography-panel.js b/packages/edit-site/src/components/sidebar/typography-panel.js
index 20855fd998d10..73d8a13f6c28e 100644
--- a/packages/edit-site/src/components/sidebar/typography-panel.js
+++ b/packages/edit-site/src/components/sidebar/typography-panel.js
@@ -1,7 +1,10 @@
/**
* WordPress dependencies
*/
-import { LineHeightControl } from '@wordpress/block-editor';
+import {
+ LineHeightControl,
+ __experimentalFontFamilyControl as FontFamilyControl,
+} from '@wordpress/block-editor';
import { PanelBody, FontSizePicker } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
@@ -24,9 +27,18 @@ export default function TypographyPanel( {
'typography.customFontSize',
name
);
+ const fontFamilies = useEditorFeature( 'typography.fontFamilies', name );
return (
+ { supports.includes( 'fontFamily' ) && (
+
+ setStyleProperty( name, 'fontFamily', value )
+ }
+ />
+ ) }
{ supports.includes( 'fontSize' ) && (
setStyleProperty( name, 'lineHeight', value )