Skip to content

Commit 36aceb3

Browse files
Add height dimensions block support
1 parent d75d953 commit 36aceb3

File tree

11 files changed

+252
-19
lines changed

11 files changed

+252
-19
lines changed

lib/block-supports/dimensions.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ function gutenberg_register_dimensions_support( $block_type ) {
2626
}
2727

2828
$has_dimensions_support = gutenberg_block_has_support( $block_type, array( '__experimentalDimensions' ), false );
29-
// Future block supports such as height & width will be added here.
3029

3130
if ( $has_dimensions_support ) {
3231
$block_type->attributes['style'] = array(
@@ -44,14 +43,24 @@ function gutenberg_register_dimensions_support( $block_type ) {
4443
*
4544
* @return array Block dimensions CSS classes and inline styles.
4645
*/
47-
function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
46+
function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) {
4847
if ( gutenberg_skip_dimensions_serialization( $block_type ) ) {
4948
return array();
5049
}
5150

5251
$styles = array();
5352

54-
// Height support to be added in near future.
53+
// Height.
54+
$has_height_support = gutenberg_block_has_support( $block_type, array( '__experimentalDimensions', 'height' ), false );
55+
56+
if ( $has_height_support ) {
57+
$height_value = _wp_array_get( $block_attributes, array( 'style', 'dimensions', 'height' ), null );
58+
59+
if ( null !== $height_value ) {
60+
$styles[] = sprintf( 'height: %s;', $height_value );
61+
}
62+
}
63+
5564
// Width support to be added in near future.
5665

5766
return empty( $styles ) ? array() : array( 'style' => implode( ' ', $styles ) );
@@ -63,10 +72,11 @@ function gutenberg_apply_dimensions_support( $block_type, $block_attributes ) {
6372
*
6473
* @param WP_Block_type $block_type Block type.
6574
*
66-
* @return boolean Whether to serialize spacing support styles & classes.
75+
* @return boolean Whether to serialize dimensions support styles & classes.
6776
*/
6877
function gutenberg_skip_dimensions_serialization( $block_type ) {
6978
$dimensions_support = _wp_array_get( $block_type->supports, array( '__experimentalDimensions' ), false );
79+
7080
return is_array( $dimensions_support ) &&
7181
array_key_exists( '__experimentalSkipSerialization', $dimensions_support ) &&
7282
$dimensions_support['__experimentalSkipSerialization'];

lib/class-wp-theme-json-gutenberg.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ class WP_Theme_JSON_Gutenberg {
6060
'gradient' => null,
6161
'text' => null,
6262
),
63+
'dimensions' => array(
64+
'height' => null,
65+
),
6366
'spacing' => array(
6467
'margin' => null,
6568
'padding' => null,
@@ -94,6 +97,9 @@ class WP_Theme_JSON_Gutenberg {
9497
'palette' => null,
9598
),
9699
'custom' => null,
100+
'dimensions' => array(
101+
'customHeight' => null,
102+
),
97103
'layout' => array(
98104
'contentSize' => null,
99105
'wideSize' => null,
@@ -222,6 +228,7 @@ class WP_Theme_JSON_Gutenberg {
222228
'font-size' => array( 'typography', 'fontSize' ),
223229
'font-style' => array( 'typography', 'fontStyle' ),
224230
'font-weight' => array( 'typography', 'fontWeight' ),
231+
'height' => array( 'dimensions', 'height' ),
225232
'letter-spacing' => array( 'typography', 'letterSpacing' ),
226233
'line-height' => array( 'typography', 'lineHeight' ),
227234
'margin' => array( 'spacing', 'margin' ),

lib/theme.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,9 @@
210210
}
211211
]
212212
},
213+
"dimensions": {
214+
"customHeight": false
215+
},
213216
"spacing": {
214217
"customMargin": false,
215218
"customPadding": false,

packages/block-editor/src/hooks/dimensions.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ import { getBlockSupport } from '@wordpress/blocks';
1313
* Internal dependencies
1414
*/
1515
import InspectorControls from '../components/inspector-controls';
16+
import {
17+
HeightEdit,
18+
hasHeightSupport,
19+
hasHeightValue,
20+
resetHeight,
21+
useIsHeightDisabled,
22+
} from './height';
1623
import {
1724
MarginEdit,
1825
hasMarginSupport,
@@ -29,6 +36,7 @@ import {
2936
} from './padding';
3037
import { cleanEmptyObject } from './utils';
3138

39+
export const DIMENSIONS_SUPPORT_KEY = '__experimentalDimensions';
3240
export const SPACING_SUPPORT_KEY = 'spacing';
3341
export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ];
3442
export const AXIAL_SIDES = [ 'vertical', 'horizontal' ];
@@ -37,19 +45,24 @@ export const AXIAL_SIDES = [ 'vertical', 'horizontal' ];
3745
* Inspector controls for dimensions support.
3846
*
3947
* @param {Object} props Block props.
40-
*
41-
* @return {WPElement} Inspector controls for spacing support features.
48+
* @return {WPElement} Inspector controls for dimensions support features.
4249
*/
4350
export function DimensionsPanel( props ) {
4451
const isPaddingDisabled = useIsPaddingDisabled( props );
4552
const isMarginDisabled = useIsMarginDisabled( props );
53+
const isHeightDisabled = useIsHeightDisabled( props );
4654
const isDisabled = useIsDimensionsDisabled( props );
4755
const isSupported = hasDimensionsSupport( props.name );
4856

4957
if ( isDisabled || ! isSupported ) {
5058
return null;
5159
}
5260

61+
const defaultDimensionsControls = getBlockSupport( props.name, [
62+
DIMENSIONS_SUPPORT_KEY,
63+
'__experimentalDefaultControls',
64+
] );
65+
5366
const defaultSpacingControls = getBlockSupport( props.name, [
5467
SPACING_SUPPORT_KEY,
5568
'__experimentalDefaultControls',
@@ -62,6 +75,10 @@ export function DimensionsPanel( props ) {
6275
props.setAttributes( {
6376
style: cleanEmptyObject( {
6477
...style,
78+
dimensions: {
79+
...style?.dimensions,
80+
height: undefined,
81+
},
6582
spacing: {
6683
...style?.spacing,
6784
margin: undefined,
@@ -78,6 +95,17 @@ export function DimensionsPanel( props ) {
7895
header={ __( 'Dimensions' ) }
7996
resetAll={ resetAll }
8097
>
98+
{ ! isHeightDisabled && (
99+
<ToolsPanelItem
100+
className="single-column"
101+
hasValue={ () => hasHeightValue( props ) }
102+
label={ __( 'Height' ) }
103+
onDeselect={ () => resetHeight( props ) }
104+
isShownByDefault={ defaultDimensionsControls?.height }
105+
>
106+
<HeightEdit { ...props } />
107+
</ToolsPanelItem>
108+
) }
81109
{ ! isPaddingDisabled && (
82110
<ToolsPanelItem
83111
hasValue={ () => hasPaddingValue( props ) }
@@ -115,21 +143,25 @@ export function hasDimensionsSupport( blockName ) {
115143
return false;
116144
}
117145

118-
return hasPaddingSupport( blockName ) || hasMarginSupport( blockName );
146+
return (
147+
hasHeightSupport( blockName ) ||
148+
hasPaddingSupport( blockName ) ||
149+
hasMarginSupport( blockName )
150+
);
119151
}
120152

121153
/**
122154
* Determines whether dimensions support has been disabled.
123155
*
124156
* @param {Object} props Block properties.
125-
*
126-
* @return {boolean} If spacing support is completely disabled.
157+
* @return {boolean} If dimensions support is completely disabled.
127158
*/
128159
const useIsDimensionsDisabled = ( props = {} ) => {
160+
const heightDisabled = useIsHeightDisabled( props );
129161
const paddingDisabled = useIsPaddingDisabled( props );
130162
const marginDisabled = useIsMarginDisabled( props );
131163

132-
return paddingDisabled && marginDisabled;
164+
return heightDisabled && paddingDisabled && marginDisabled;
133165
};
134166

135167
/**
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { getBlockSupport } from '@wordpress/blocks';
5+
import {
6+
__experimentalUseCustomUnits as useCustomUnits,
7+
__experimentalUnitControl as UnitControl,
8+
} from '@wordpress/components';
9+
import { __ } from '@wordpress/i18n';
10+
11+
/**
12+
* Internal dependencies
13+
*/
14+
import useSetting from '../components/use-setting';
15+
import { DIMENSIONS_SUPPORT_KEY } from './dimensions';
16+
import { cleanEmptyObject } from './utils';
17+
18+
/**
19+
* Determines if there is height support.
20+
*
21+
* @param {string|Object} blockType Block name or Block Type object.
22+
* @return {boolean} Whether there is support.
23+
*/
24+
export function hasHeightSupport( blockType ) {
25+
const support = getBlockSupport( blockType, DIMENSIONS_SUPPORT_KEY );
26+
return !! ( true === support || support?.height );
27+
}
28+
29+
/**
30+
* Checks if there is a current value in the height block support attributes.
31+
*
32+
* @param {Object} props Block props.
33+
* @return {boolean} Whether or not the block has a height value set.
34+
*/
35+
export function hasHeightValue( props ) {
36+
return props.attributes.style?.dimensions?.height !== undefined;
37+
}
38+
39+
/**
40+
* Resets the height block support attributes. This can be used when
41+
* disabling the height support controls for a block via a progressive
42+
* discovery panel.
43+
*
44+
* @param {Object} props Block props.
45+
* @param {Object} props.attributes Block's attributes.
46+
* @param {Object} props.setAttributes Function to set block's attributes.
47+
*/
48+
export function resetHeight( { attributes = {}, setAttributes } ) {
49+
const { style } = attributes;
50+
51+
setAttributes( {
52+
style: cleanEmptyObject( {
53+
...style,
54+
dimensions: {
55+
...style?.dimensions,
56+
height: undefined,
57+
},
58+
} ),
59+
} );
60+
}
61+
62+
/**
63+
* Custom hook that checks if height controls have been disabled.
64+
*
65+
* @param {string} name The name of the block.
66+
* @return {boolean} Whether height control is disabled.
67+
*/
68+
export function useIsHeightDisabled( { name: blockName } = {} ) {
69+
const isDisabled = ! useSetting( 'dimensions.customHeight' );
70+
return ! hasHeightSupport( blockName ) || isDisabled;
71+
}
72+
73+
/**
74+
* Inspector control panel containing the height related configuration.
75+
*
76+
* @param {Object} props Block props.
77+
* @return {WPElement} Edit component for height.
78+
*/
79+
export function HeightEdit( props ) {
80+
const {
81+
attributes: { style },
82+
setAttributes,
83+
} = props;
84+
85+
const units = useCustomUnits( {
86+
availableUnits: useSetting( 'dimensions.units' ) || [
87+
'%',
88+
'px',
89+
'em',
90+
'rem',
91+
'vh',
92+
'vw',
93+
],
94+
} );
95+
96+
if ( useIsHeightDisabled( props ) ) {
97+
return null;
98+
}
99+
100+
const onChange = ( next ) => {
101+
const newStyle = {
102+
...style,
103+
dimensions: {
104+
...style?.dimensions,
105+
height: next,
106+
},
107+
};
108+
109+
setAttributes( { style: cleanEmptyObject( newStyle ) } );
110+
};
111+
112+
return (
113+
<UnitControl
114+
label={ __( 'Height' ) }
115+
value={ style?.dimensions?.height }
116+
units={ units }
117+
onChange={ onChange }
118+
min={ 0 }
119+
/>
120+
);
121+
}

packages/block-editor/src/hooks/style.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@ import {
3737
TYPOGRAPHY_SUPPORT_KEY,
3838
TYPOGRAPHY_SUPPORT_KEYS,
3939
} from './typography';
40-
import { SPACING_SUPPORT_KEY, DimensionsPanel } from './dimensions';
40+
import {
41+
DIMENSIONS_SUPPORT_KEY,
42+
SPACING_SUPPORT_KEY,
43+
DimensionsPanel,
44+
} from './dimensions';
4145
import useDisplayBlockControls from '../components/use-display-block-controls';
4246

4347
const styleSupportKeys = [
4448
...TYPOGRAPHY_SUPPORT_KEYS,
4549
BORDER_SUPPORT_KEY,
4650
COLOR_SUPPORT_KEY,
51+
DIMENSIONS_SUPPORT_KEY,
4752
SPACING_SUPPORT_KEY,
4853
];
4954

@@ -152,8 +157,11 @@ const skipSerializationPaths = {
152157
[ `${ TYPOGRAPHY_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
153158
TYPOGRAPHY_SUPPORT_KEY,
154159
],
160+
[ `${ DIMENSIONS_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
161+
DIMENSIONS_SUPPORT_KEY,
162+
],
155163
[ `${ SPACING_SUPPORT_KEY }.__experimentalSkipSerialization` ]: [
156-
'spacing',
164+
SPACING_SUPPORT_KEY,
157165
],
158166
};
159167

packages/block-editor/src/hooks/test/style.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ describe( 'getInlineStyles', () => {
2323
style: 'dotted',
2424
color: '#21759b',
2525
},
26+
dimensions: {
27+
height: '500px',
28+
},
2629
spacing: {
2730
padding: { top: '10px' },
2831
margin: { bottom: '15px' },
@@ -37,6 +40,7 @@ describe( 'getInlineStyles', () => {
3740
color: 'red',
3841
lineHeight: 1.5,
3942
fontSize: 10,
43+
height: '500px',
4044
marginBottom: '15px',
4145
paddingTop: '10px',
4246
} );

packages/blocks/src/api/constants.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ export const __EXPERIMENTAL_STYLE_PROPERTY = {
7272
value: [ 'typography', 'fontWeight' ],
7373
support: [ 'typography', '__experimentalFontWeight' ],
7474
},
75+
height: {
76+
value: [ 'dimensions', 'height' ],
77+
support: [ '__experimentalDimensions', 'height' ],
78+
},
7579
lineHeight: {
7680
value: [ 'typography', 'lineHeight' ],
7781
support: [ 'typography', 'lineHeight' ],

packages/edit-site/src/components/editor/global-styles-renderer.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,13 @@ export const getNodesWithStyles = ( tree, blockSelectors ) => {
192192

193193
const pickStyleKeys = ( treeToPickFrom ) =>
194194
pickBy( treeToPickFrom, ( value, key ) =>
195-
[ 'border', 'color', 'spacing', 'typography' ].includes( key )
195+
[
196+
'border',
197+
'color',
198+
'dimensions',
199+
'spacing',
200+
'typography',
201+
].includes( key )
196202
);
197203

198204
// Top-level.

0 commit comments

Comments
 (0)