diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md
index 95f2e047dd0e31..138e32f76505ee 100644
--- a/docs/reference-guides/theme-json-reference/theme-json-living.md
+++ b/docs/reference-guides/theme-json-reference/theme-json-living.md
@@ -74,6 +74,7 @@ Settings related to borders.
| radius | Allow users to set custom border radius. | `boolean` | `false` |
| style | Allow users to set custom border styles. | `boolean` | `false` |
| width | Allow users to set custom border widths. | `boolean` | `false` |
+| radiusSizes | Border radius size presets for the border radius selector. | `[ { name, slug, size } ]` | |
---
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 083ce3516b71af..69e33e9459c7e5 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -204,6 +204,15 @@ class WP_Theme_JSON_Gutenberg {
'classes' => array(),
'properties' => array( 'box-shadow' ),
),
+ array(
+ 'path' => array( 'border', 'radiusSizes' ),
+ 'prevent_override' => false,
+ 'use_default_names' => false,
+ 'value_key' => 'size',
+ 'css_vars' => '--wp--preset--border-radius--$slug',
+ 'classes' => array(),
+ 'properties' => array( 'border-radius' ),
+ ),
);
/**
@@ -386,10 +395,11 @@ class WP_Theme_JSON_Gutenberg {
'backgroundSize' => null,
),
'border' => array(
- 'color' => null,
- 'radius' => null,
- 'style' => null,
- 'width' => null,
+ 'color' => null,
+ 'radius' => null,
+ 'style' => null,
+ 'width' => null,
+ 'radiusSizes' => null,
),
'color' => array(
'background' => null,
diff --git a/lib/theme-i18n.json b/lib/theme-i18n.json
index e4d14502132cbe..1da001f7eb842b 100644
--- a/lib/theme-i18n.json
+++ b/lib/theme-i18n.json
@@ -45,6 +45,13 @@
}
]
},
+ "border": {
+ "radiusSizes": [
+ {
+ "name": "Border radius size name"
+ }
+ ]
+ },
"blocks": {
"*": {
"typography": {
@@ -77,6 +84,13 @@
"name": "Space size name"
}
]
+ },
+ "border": {
+ "radiusSizes": [
+ {
+ "name": "Border radius size name"
+ }
+ ]
}
}
}
diff --git a/packages/block-editor/src/components/border-radius-control/all-input-control.js b/packages/block-editor/src/components/border-radius-control/all-input-control.js
deleted file mode 100644
index 14abf3c6c2bc94..00000000000000
--- a/packages/block-editor/src/components/border-radius-control/all-input-control.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import {
- getAllValue,
- getAllUnit,
- hasMixedValues,
- hasDefinedValues,
-} from './utils';
-
-export default function AllInputControl( {
- onChange,
- selectedUnits,
- setSelectedUnits,
- values,
- ...props
-} ) {
- let allValue = getAllValue( values );
-
- if ( allValue === undefined ) {
- // If we don't have any value set the unit to any current selection
- // or the most common unit from the individual radii values.
- allValue = getAllUnit( selectedUnits );
- }
-
- const hasValues = hasDefinedValues( values );
- const isMixed = hasValues && hasMixedValues( values );
- const allPlaceholder = isMixed ? __( 'Mixed' ) : null;
-
- // Filter out CSS-unit-only values to prevent invalid styles.
- const handleOnChange = ( next ) => {
- const isNumeric = ! isNaN( parseFloat( next ) );
- const nextValue = isNumeric ? next : undefined;
- onChange( nextValue );
- };
-
- // Store current unit selection for use as fallback for individual
- // radii controls.
- const handleOnUnitChange = ( unit ) => {
- setSelectedUnits( {
- topLeft: unit,
- topRight: unit,
- bottomLeft: unit,
- bottomRight: unit,
- } );
- };
-
- return (
-
- );
-}
diff --git a/packages/block-editor/src/components/border-radius-control/index.js b/packages/block-editor/src/components/border-radius-control/index.js
index cab9b87b3b29c0..a9a7c44d586e21 100644
--- a/packages/block-editor/src/components/border-radius-control/index.js
+++ b/packages/block-editor/src/components/border-radius-control/index.js
@@ -3,26 +3,21 @@
*/
import {
BaseControl,
- RangeControl,
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
__experimentalUseCustomUnits as useCustomUnits,
+ __experimentalVStack as VStack,
+ __experimentalHStack as HStack,
} from '@wordpress/components';
-import { useState } from '@wordpress/element';
+import { useState, useMemo } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import AllInputControl from './all-input-control';
-import InputControls from './input-controls';
import LinkedButton from './linked-button';
import { useSettings } from '../use-settings';
-import {
- getAllValue,
- getAllUnit,
- hasDefinedValues,
- hasMixedValues,
-} from './utils';
+import { hasDefinedValues, hasMixedValues } from './utils';
+import SingleInputControl from './single-input-control';
const DEFAULT_VALUES = {
topLeft: undefined,
@@ -30,12 +25,33 @@ const DEFAULT_VALUES = {
bottomLeft: undefined,
bottomRight: undefined,
};
-const MIN_BORDER_RADIUS_VALUE = 0;
-const MAX_BORDER_RADIUS_VALUES = {
- px: 100,
- em: 20,
- rem: 20,
-};
+const RANGE_CONTROL_MAX_SIZE = 8;
+const EMPTY_ARRAY = [];
+function useBorderRadiusSizes( 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.length > RANGE_CONTROL_MAX_SIZE
+ ? [
+ {
+ name: __( 'Default' ),
+ slug: 'default',
+ size: undefined,
+ },
+ ...sizes,
+ ]
+ : sizes;
+ }, [ customSizes, themeSizes, defaultSizes ] );
+}
/**
* Control to display border radius options.
@@ -43,14 +59,15 @@ const MAX_BORDER_RADIUS_VALUES = {
* @param {Object} props Component props.
* @param {Function} props.onChange Callback to handle onChange.
* @param {Object} props.values Border radius values.
+ * @param {Object} props.presets Border radius presets.
*
* @return {Element} Custom border radius control.
*/
-export default function BorderRadiusControl( { onChange, values } ) {
+export default function BorderRadiusControl( { onChange, values, presets } ) {
const [ isLinked, setIsLinked ] = useState(
! hasDefinedValues( values ) || ! hasMixedValues( values )
);
-
+ const options = useBorderRadiusSizes( presets );
// Tracking selected units via internal state allows filtering of CSS unit
// only values from being saved while maintaining preexisting unit selection
// behaviour. Filtering CSS unit only values prevents invalid style values.
@@ -72,64 +89,49 @@ export default function BorderRadiusControl( { onChange, values } ) {
availableUnits: availableUnits || [ 'px', 'em', 'rem' ],
} );
- const unit = getAllUnit( selectedUnits );
- const unitConfig = units && units.find( ( item ) => item.value === unit );
- const step = unitConfig?.step || 1;
-
- const [ allValue ] = parseQuantityAndUnitFromRawValue(
- getAllValue( values )
- );
-
const toggleLinked = () => setIsLinked( ! isLinked );
- const handleSliderChange = ( next ) => {
- onChange( next !== undefined ? `${ next }${ unit }` : undefined );
- };
-
return (
);
}
diff --git a/packages/block-editor/src/components/border-radius-control/input-controls.js b/packages/block-editor/src/components/border-radius-control/input-controls.js
deleted file mode 100644
index 4529c00b997ac7..00000000000000
--- a/packages/block-editor/src/components/border-radius-control/input-controls.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * WordPress dependencies
- */
-import {
- __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
- __experimentalUnitControl as UnitControl,
- Tooltip,
-} from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
-
-const CORNERS = {
- topLeft: __( 'Top left' ),
- topRight: __( 'Top right' ),
- bottomLeft: __( 'Bottom left' ),
- bottomRight: __( 'Bottom right' ),
-};
-
-export default function BoxInputControls( {
- onChange,
- selectedUnits,
- setSelectedUnits,
- values: valuesProp,
- ...props
-} ) {
- const createHandleOnChange = ( corner ) => ( next ) => {
- if ( ! onChange ) {
- return;
- }
-
- // Filter out CSS-unit-only values to prevent invalid styles.
- const isNumeric = ! isNaN( parseFloat( next ) );
- const nextValue = isNumeric ? next : undefined;
-
- onChange( {
- ...values,
- [ corner ]: nextValue,
- } );
- };
-
- const createHandleOnUnitChange = ( side ) => ( next ) => {
- const newUnits = { ...selectedUnits };
- newUnits[ side ] = next;
- setSelectedUnits( newUnits );
- };
-
- // For shorthand style & backwards compatibility, handle flat string value.
- const values =
- typeof valuesProp !== 'string'
- ? valuesProp
- : {
- topLeft: valuesProp,
- topRight: valuesProp,
- bottomLeft: valuesProp,
- bottomRight: valuesProp,
- };
-
- // Controls are wrapped in tooltips as visible labels aren't desired here.
- // Tooltip rendering also requires the UnitControl to be wrapped. See:
- // https://github.com/WordPress/gutenberg/pull/24966#issuecomment-685875026
- return (
-
- { Object.entries( CORNERS ).map( ( [ corner, label ] ) => {
- const [ parsedQuantity, parsedUnit ] =
- parseQuantityAndUnitFromRawValue( values[ corner ] );
-
- const computedUnit = values[ corner ]
- ? parsedUnit
- : selectedUnits[ corner ] || selectedUnits.flat;
-
- return (
-
-
-
-
-
- );
- } ) }
-
- );
-}
diff --git a/packages/block-editor/src/components/border-radius-control/linked-button.js b/packages/block-editor/src/components/border-radius-control/linked-button.js
index 58afe350b72126..e8a967e7ee5677 100644
--- a/packages/block-editor/src/components/border-radius-control/linked-button.js
+++ b/packages/block-editor/src/components/border-radius-control/linked-button.js
@@ -11,7 +11,7 @@ export default function LinkedButton( { isLinked, ...props } ) {
return (