Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Create new DimensionControl for existing supports
  • Loading branch information
aaronrobertshaw committed Dec 15, 2025
commit 743c7c459bb0a496ee4e091606a714a27dba827c
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ module.exports = {
'Button',
'ComboboxControl',
'CustomSelectControl',
'DimensionControl',

'FontAppearanceControl',
'FontFamilyControl',
'FontSizePicker',
Expand Down
21 changes: 21 additions & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,25 @@ _Returns_

Undocumented declaration.

### DimensionControl

DimensionControl renders a linked unit control and range control for adjusting dimensions of a block.

_Related_

- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/dimension-control/README.md>

_Parameters_

- _props_ `Object`:
- _props.label_ `?string`: A label for the control.
- _props.onChange_ `( value: string ) => void`: Called when the dimension value changes.
- _props.value_ `string`: The current dimension value.

_Returns_

- `Component`: The component to be rendered.

### FontSizePicker

_Related_
Expand Down Expand Up @@ -600,6 +619,8 @@ _Returns_

### HeightControl

> **Deprecated** Use DimensionControl instead.

HeightControl renders a linked unit control and range control for adjusting the height of a block.

_Related_
Expand Down
106 changes: 106 additions & 0 deletions packages/block-editor/src/components/dimension-control/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Dimension Control

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.

_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.

## Features

- **Preset Support**: Automatically detects and displays dimension presets from `dimensions.dimensionSizes` theme settings
- **Custom Values**: Allows entering custom dimension values with unit selection
- **Unit Conversion**: Intelligently converts between compatible units (px ↔ em/rem, viewport units)
- **Flexible UI**: Shows either a slider (≤8 presets) or dropdown (>8 presets) for preset selection
- **Toggle Between Modes**: Users can switch between preset and custom value modes

## Development guidelines

### Usage

Renders the markup for dimension control component, to be used in the block inspector.

```jsx
import { useState } from 'react';
import { DimensionControl } from '@wordpress/block-editor';

const MyDimensionControl = () => (
const [ value, setValue ] = useState();
<DimensionControl
label={ 'My Dimension Control' }
onChange={ setValue }
value={ value }
/>
);
```

### Props

#### `value`

- **Type:** `String` or `Number` or `Undefined`

The value of the current dimension.

#### `onChange`

- **Type:** `Function`

A callback function that handles the application of the dimension value.

#### `label`

- **Type:** `String`
- **Default:** `'Dimension'`

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.

## Preset Integration

The component automatically integrates with the theme's dimension size presets defined in `dimensions.dimensionSizes`. These presets are merged from:

- **Default presets**: System-defined dimension sizes
- **Theme presets**: Dimension sizes defined by the active theme
- **Custom presets**: User-defined dimension sizes

### Preset Value Format

When a preset is selected, the component returns values in the format:
```
var:preset|dimension-sizes|{slug}
```

For example: `var:preset|dimension-sizes|medium`

### Theme Configuration

To provide dimension presets, add them to your theme's `theme.json`:

```json
{
"version": 2,
"settings": {
"dimensions": {
"dimensionSizes": [
{
"name": "Small",
"slug": "small",
"size": "16px"
},
{
"name": "Medium",
"slug": "medium",
"size": "32px"
},
{
"name": "Large",
"slug": "large",
"size": "64px"
}
]
}
}
}
```

## Related components

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.
115 changes: 115 additions & 0 deletions packages/block-editor/src/components/dimension-control/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* WordPress dependencies
*/
import { useMemo, useState } from '@wordpress/element';
import {
BaseControl,
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
__experimentalUseCustomUnits as useCustomUnits,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { useSettings } from '../use-settings';
import PresetInputControl from '../preset-input-control';
import { CUSTOM_VALUE_SETTINGS } from '../preset-input-control/constants';

const EMPTY_ARRAY = [];

// Dimension-specific custom value settings - override defaults for larger dimension values
const DIMENSION_CUSTOM_VALUE_SETTINGS = {
...CUSTOM_VALUE_SETTINGS,
px: { max: 1000, steps: 1 },
em: { max: 50, steps: 0.1 },
rem: { max: 50, steps: 0.1 },
};

/**
* Hook to retrieve dimension sizes from theme settings.
*
* @param {Object} presets Dimension presets object containing default, theme, and custom sizes.
* @return {Array} Array of dimension size options.
*/
function useDimensionSizes( presets ) {
const defaultSizes = presets?.default ?? EMPTY_ARRAY;
const customSizes = presets?.custom ?? EMPTY_ARRAY;
const themeSizes = presets?.theme ?? EMPTY_ARRAY;

return useMemo( () => {
const sizes = [
{ name: __( 'None' ), slug: '0', size: 0 },
...customSizes,
...themeSizes,
...defaultSizes,
];

return sizes;
}, [ customSizes, themeSizes, defaultSizes ] );
}

/**
* DimensionControl renders a linked unit control and range control for adjusting dimensions of a block.
*
* @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/dimension-control/README.md
*
* @param {Object} props
* @param {?string} props.label A label for the control.
* @param {( value: string ) => void } props.onChange Called when the dimension value changes.
* @param {string} props.value The current dimension value.
*
* @return {Component} The component to be rendered.
*/
export default function DimensionControl( {
label = __( 'Dimension' ),
onChange,
value,
} ) {
const [ dimensionSizes, availableUnits ] = useSettings(
'dimensions.dimensionSizes',
'spacing.units'
);

const units = useCustomUnits( {
availableUnits: availableUnits || [
'%',
'px',
'em',
'rem',
'vh',
'vw',
],
} );

const options = useDimensionSizes( dimensionSizes );

// Track selected unit for PresetInputControl
const [ selectedUnit, setSelectedUnit ] = useState( () => {
const [ , unit ] = parseQuantityAndUnitFromRawValue( value );
return unit || units[ 0 ]?.value || 'px';
} );

return (
<fieldset className="block-editor-dimension-control">
<BaseControl.VisualLabel as="legend">
{ label }
</BaseControl.VisualLabel>
<PresetInputControl
ariaLabel={ label }
className="block-editor-dimension-control"
customValueSettings={ DIMENSION_CUSTOM_VALUE_SETTINGS }
minimumCustomValue={ 0 }
onChange={ onChange }
onUnitChange={ setSelectedUnit }
presets={ options }
presetType="dimension"
selectedUnit={ selectedUnit }
showTooltip
smoothUnitConversions
units={ units }
value={ value }
/>
</fieldset>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import DimensionControl from '../';

export default {
component: DimensionControl,
title: 'BlockEditor/DimensionControl',
};

const Template = ( props ) => {
const [ value, setValue ] = useState();
return (
<DimensionControl onChange={ setValue } value={ value } { ...props } />
);
};

export const Default = Template.bind( {} );

export const WithCustomLabel = Template.bind( {} );
WithCustomLabel.args = {
label: 'Height',
};

export const WithWidthLabel = Template.bind( {} );
WithWidthLabel.args = {
label: 'Width',
};

export const WithMinHeightLabel = Template.bind( {} );
WithMinHeightLabel.args = {
label: 'Minimum height',
};

export const WithPresets = Template.bind( {} );
WithPresets.args = {
label: 'Height with presets',
};

export const WithInitialValue = Template.bind( {} );
WithInitialValue.args = {
label: 'Height',
value: '24px',
};

const TemplateWithPresetValue = ( props ) => {
const [ value, setValue ] = useState( 'var:preset|dimension|medium' );
return (
<DimensionControl onChange={ setValue } value={ value } { ...props } />
);
};

export const WithPresetValue = TemplateWithPresetValue.bind( {} );
WithPresetValue.args = {
label: 'Height (preset value)',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.block-editor-dimension-control {
border: 0;
margin: 0;
padding: 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { getValueFromVariable } from '@wordpress/global-styles-engine';
*/
import { useToolsPanelDropdownMenuProps } from './utils';
import SpacingSizesControl from '../spacing-sizes-control';
import HeightControl from '../height-control';
import DimensionControl from '../dimension-control';
import ChildLayoutControl from '../child-layout-control';
import AspectRatioTool from '../dimensions-tool/aspect-ratio-tool';
import { cleanEmptyObject } from '../../hooks/utils';
Expand Down Expand Up @@ -700,7 +700,7 @@ export default function DimensionsPanel( {
}
panelId={ panelId }
>
<HeightControl
<DimensionControl
label={ __( 'Minimum height' ) }
value={ minHeightValue }
onChange={ setMinHeightValue }
Expand All @@ -717,7 +717,7 @@ export default function DimensionsPanel( {
}
panelId={ panelId }
>
<HeightControl
<DimensionControl
label={ __( 'Width' ) }
value={ widthValue }
onChange={ setWidthValue }
Expand Down
Loading