Skip to content

Commit 2843130

Browse files
Create new DimensionControl for existing supports
1 parent 595c150 commit 2843130

File tree

10 files changed

+346
-12
lines changed

10 files changed

+346
-12
lines changed

.eslintrc.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,6 @@ module.exports = {
280280
'BaseControl',
281281
'CheckboxControl',
282282
'ComboboxControl',
283-
'DimensionControl',
284283
'FocalPointPicker',
285284
'RangeControl',
286285
'SearchControl',
@@ -304,7 +303,7 @@ module.exports = {
304303
'Button',
305304
'ComboboxControl',
306305
'CustomSelectControl',
307-
'DimensionControl',
306+
308307
'FontAppearanceControl',
309308
'FontFamilyControl',
310309
'FontSizePicker',

packages/block-editor/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,25 @@ _Returns_
392392

393393
Undocumented declaration.
394394

395+
### DimensionControl
396+
397+
DimensionControl renders a linked unit control and range control for adjusting dimensions of a block.
398+
399+
_Related_
400+
401+
- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/dimension-control/README.md>
402+
403+
_Parameters_
404+
405+
- _props_ `Object`:
406+
- _props.label_ `?string`: A label for the control.
407+
- _props.onChange_ `( value: string ) => void`: Called when the dimension value changes.
408+
- _props.value_ `string`: The current dimension value.
409+
410+
_Returns_
411+
412+
- `Component`: The component to be rendered.
413+
395414
### FontSizePicker
396415

397416
_Related_
@@ -600,6 +619,8 @@ _Returns_
600619

601620
### HeightControl
602621

622+
> **Deprecated** Use DimensionControl instead.
623+
603624
HeightControl renders a linked unit control and range control for adjusting the height of a block.
604625

605626
_Related_
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Dimension Control
2+
3+
The `DimensionControl` component provides a comprehensive control for managing dimensions of a block within the block editor. It supports both preset values from theme settings and custom values with unit controls and sliders. It can be used for controlling various dimension-related block supports like height, width, min-height, etc.
4+
5+
_Note:_ It is worth noting that dimension options are opt-in features. Themes need to declare support for them before they'll be available, and a convenient way to do that is via opting in to the [appearanceTools](/docs/how-to-guides/themes/global-settings-and-styles.md#opt-in-into-ui-controls) UI controls.
6+
7+
## Features
8+
9+
- **Preset Support**: Automatically detects and displays dimension presets from `dimensions.dimensionSizes` theme settings
10+
- **Custom Values**: Allows entering custom dimension values with unit selection
11+
- **Unit Conversion**: Intelligently converts between compatible units (px ↔ em/rem, viewport units)
12+
- **Flexible UI**: Shows either a slider (≤8 presets) or dropdown (>8 presets) for preset selection
13+
- **Toggle Between Modes**: Users can switch between preset and custom value modes
14+
15+
## Development guidelines
16+
17+
### Usage
18+
19+
Renders the markup for dimension control component, to be used in the block inspector.
20+
21+
```jsx
22+
import { useState } from 'react';
23+
import { DimensionControl } from '@wordpress/block-editor';
24+
25+
const MyDimensionControl = () => (
26+
const [ value, setValue ] = useState();
27+
<DimensionControl
28+
label={ 'My Dimension Control' }
29+
onChange={ setValue }
30+
value={ value }
31+
/>
32+
);
33+
```
34+
35+
### Props
36+
37+
#### `value`
38+
39+
- **Type:** `String` or `Number` or `Undefined`
40+
41+
The value of the current dimension.
42+
43+
#### `onChange`
44+
45+
- **Type:** `Function`
46+
47+
A callback function that handles the application of the dimension value.
48+
49+
#### `label`
50+
51+
- **Type:** `String`
52+
- **Default:** `'Dimension'`
53+
54+
A label for the dimension control. This is useful when using the dimension control for different dimension properties. For example, "Height", "Width", "Minimum height", etc.
55+
56+
## Preset Integration
57+
58+
The component automatically integrates with the theme's dimension size presets defined in `dimensions.dimensionSizes`. These presets are merged from:
59+
60+
- **Default presets**: System-defined dimension sizes
61+
- **Theme presets**: Dimension sizes defined by the active theme
62+
- **Custom presets**: User-defined dimension sizes
63+
64+
### Preset Value Format
65+
66+
When a preset is selected, the component returns values in the format:
67+
```
68+
var:preset|dimension-sizes|{slug}
69+
```
70+
71+
For example: `var:preset|dimension-sizes|medium`
72+
73+
### Theme Configuration
74+
75+
To provide dimension presets, add them to your theme's `theme.json`:
76+
77+
```json
78+
{
79+
"version": 2,
80+
"settings": {
81+
"dimensions": {
82+
"dimensionSizes": [
83+
{
84+
"name": "Small",
85+
"slug": "small",
86+
"size": "16px"
87+
},
88+
{
89+
"name": "Medium",
90+
"slug": "medium",
91+
"size": "32px"
92+
},
93+
{
94+
"name": "Large",
95+
"slug": "large",
96+
"size": "64px"
97+
}
98+
]
99+
}
100+
}
101+
}
102+
```
103+
104+
## Related components
105+
106+
Block Editor components are components that can be used to compose the UI of your block editor. Thus, they can only be used under a [`BlockEditorProvider`](https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/provider/README.md) in the components tree.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { useMemo, useState } from '@wordpress/element';
5+
import {
6+
BaseControl,
7+
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
8+
__experimentalUseCustomUnits as useCustomUnits,
9+
} from '@wordpress/components';
10+
import { __ } from '@wordpress/i18n';
11+
12+
/**
13+
* Internal dependencies
14+
*/
15+
import { useSettings } from '../use-settings';
16+
import PresetInputControl from '../preset-input-control';
17+
import { CUSTOM_VALUE_SETTINGS } from '../preset-input-control/constants';
18+
19+
const EMPTY_ARRAY = [];
20+
21+
// Dimension-specific custom value settings - override defaults for larger dimension values
22+
const DIMENSION_CUSTOM_VALUE_SETTINGS = {
23+
...CUSTOM_VALUE_SETTINGS,
24+
px: { max: 1000, steps: 1 },
25+
em: { max: 50, steps: 0.1 },
26+
rem: { max: 50, steps: 0.1 },
27+
};
28+
29+
/**
30+
* Hook to retrieve dimension sizes from theme settings.
31+
*
32+
* @param {Object} presets Dimension presets object containing default, theme, and custom sizes.
33+
* @return {Array} Array of dimension size options.
34+
*/
35+
function useDimensionSizes( presets ) {
36+
const defaultSizes = presets?.default ?? EMPTY_ARRAY;
37+
const customSizes = presets?.custom ?? EMPTY_ARRAY;
38+
const themeSizes = presets?.theme ?? EMPTY_ARRAY;
39+
40+
return useMemo( () => {
41+
const sizes = [
42+
{ name: __( 'None' ), slug: '0', size: 0 },
43+
...customSizes,
44+
...themeSizes,
45+
...defaultSizes,
46+
];
47+
48+
return sizes;
49+
}, [ customSizes, themeSizes, defaultSizes ] );
50+
}
51+
52+
/**
53+
* DimensionControl renders a linked unit control and range control for adjusting dimensions of a block.
54+
*
55+
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/dimension-control/README.md
56+
*
57+
* @param {Object} props
58+
* @param {?string} props.label A label for the control.
59+
* @param {( value: string ) => void } props.onChange Called when the dimension value changes.
60+
* @param {string} props.value The current dimension value.
61+
*
62+
* @return {Component} The component to be rendered.
63+
*/
64+
export default function DimensionControl( {
65+
label = __( 'Dimension' ),
66+
onChange,
67+
value,
68+
} ) {
69+
const [ dimensionSizes, availableUnits ] = useSettings(
70+
'dimensions.dimensionSizes',
71+
'spacing.units'
72+
);
73+
74+
const units = useCustomUnits( {
75+
availableUnits: availableUnits || [
76+
'%',
77+
'px',
78+
'em',
79+
'rem',
80+
'vh',
81+
'vw',
82+
],
83+
} );
84+
85+
const options = useDimensionSizes( dimensionSizes );
86+
87+
// Track selected unit for PresetInputControl
88+
const [ selectedUnit, setSelectedUnit ] = useState( () => {
89+
const [ , unit ] = parseQuantityAndUnitFromRawValue( value );
90+
return unit || units[ 0 ]?.value || 'px';
91+
} );
92+
93+
return (
94+
<fieldset className="block-editor-dimension-control">
95+
<BaseControl.VisualLabel as="legend">
96+
{ label }
97+
</BaseControl.VisualLabel>
98+
<PresetInputControl
99+
ariaLabel={ label }
100+
className="block-editor-dimension-control"
101+
customValueSettings={ DIMENSION_CUSTOM_VALUE_SETTINGS }
102+
minimumCustomValue={ 0 }
103+
onChange={ onChange }
104+
onUnitChange={ setSelectedUnit }
105+
presets={ options }
106+
presetType="dimension"
107+
selectedUnit={ selectedUnit }
108+
showTooltip
109+
smoothUnitConversions
110+
units={ units }
111+
value={ value }
112+
/>
113+
</fieldset>
114+
);
115+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* WordPress dependencies
3+
*/
4+
import { useState } from '@wordpress/element';
5+
6+
/**
7+
* Internal dependencies
8+
*/
9+
import DimensionControl from '../';
10+
11+
export default {
12+
component: DimensionControl,
13+
title: 'BlockEditor/DimensionControl',
14+
};
15+
16+
const Template = ( props ) => {
17+
const [ value, setValue ] = useState();
18+
return (
19+
<DimensionControl onChange={ setValue } value={ value } { ...props } />
20+
);
21+
};
22+
23+
export const Default = Template.bind( {} );
24+
25+
export const WithCustomLabel = Template.bind( {} );
26+
WithCustomLabel.args = {
27+
label: 'Height',
28+
};
29+
30+
export const WithWidthLabel = Template.bind( {} );
31+
WithWidthLabel.args = {
32+
label: 'Width',
33+
};
34+
35+
export const WithMinHeightLabel = Template.bind( {} );
36+
WithMinHeightLabel.args = {
37+
label: 'Minimum height',
38+
};
39+
40+
export const WithPresets = Template.bind( {} );
41+
WithPresets.args = {
42+
label: 'Height with presets',
43+
};
44+
45+
export const WithInitialValue = Template.bind( {} );
46+
WithInitialValue.args = {
47+
label: 'Height',
48+
value: '24px',
49+
};
50+
51+
const TemplateWithPresetValue = ( props ) => {
52+
const [ value, setValue ] = useState( 'var:preset|dimension|medium' );
53+
return (
54+
<DimensionControl onChange={ setValue } value={ value } { ...props } />
55+
);
56+
};
57+
58+
export const WithPresetValue = TemplateWithPresetValue.bind( {} );
59+
WithPresetValue.args = {
60+
label: 'Height (preset value)',
61+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.block-editor-dimension-control {
2+
border: 0;
3+
margin: 0;
4+
padding: 0;
5+
}

packages/block-editor/src/components/global-styles/dimensions-panel.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import { getValueFromVariable } from '@wordpress/global-styles-engine';
2424
*/
2525
import { useToolsPanelDropdownMenuProps } from './utils';
2626
import SpacingSizesControl from '../spacing-sizes-control';
27-
import HeightControl from '../height-control';
27+
import DimensionControl from '../dimension-control';
2828
import ChildLayoutControl from '../child-layout-control';
2929
import AspectRatioTool from '../dimensions-tool/aspect-ratio-tool';
3030
import { cleanEmptyObject } from '../../hooks/utils';
@@ -700,7 +700,7 @@ export default function DimensionsPanel( {
700700
}
701701
panelId={ panelId }
702702
>
703-
<HeightControl
703+
<DimensionControl
704704
label={ __( 'Minimum height' ) }
705705
value={ minHeightValue }
706706
onChange={ setMinHeightValue }
@@ -717,7 +717,7 @@ export default function DimensionsPanel( {
717717
}
718718
panelId={ panelId }
719719
>
720-
<HeightControl
720+
<DimensionControl
721721
label={ __( 'Width' ) }
722722
value={ widthValue }
723723
onChange={ setWidthValue }

0 commit comments

Comments
 (0)