Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Separator: Trial custom separator height with independent top/bottom margins #28688

8 changes: 2 additions & 6 deletions packages/block-library/src/separator/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@
"customColor": {
"type": "string"
},
"height": {
"type": "number"
},
"heightUnit": {
"type": "string",
"default": "px"
"style": {
"type": "object"
}
},
"supports": {
Expand Down
113 changes: 49 additions & 64 deletions packages/block-library/src/separator/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,55 @@
* External dependencies
*/
import classnames from 'classnames';
import { clamp } from 'lodash';

/**
* WordPress dependencies
*/
import { HorizontalRule, ResizableBox } from '@wordpress/components';
import { useEffect, useState } from '@wordpress/element';
import { useState } from '@wordpress/element';
import { withColors, useBlockProps } from '@wordpress/block-editor';
import { View } from '@wordpress/primitives';

/**
* Internal dependencies
*/
import SeparatorSettings from './separator-settings';
import { getHeightConstraints } from './shared';
import {
MARGIN_CONSTRAINTS,
calculateMargins,
getHeightFromStyle,
parseUnit,
} from './shared';

function SeparatorEdit( props ) {
const { attributes, setAttributes, color, setColor, isSelected } = props;
const { height, heightUnit } = attributes;
const [ isResizing, setIsResizing ] = useState( false );
const {
attributes: { style },
setAttributes,
color,
setColor,
isSelected,
} = props;

const hasDotsStyle = attributes.className?.indexOf( 'is-style-dots' ) >= 0;
const minimumHeightScale = hasDotsStyle ? 1.5 : 1;
const heightConstraints = getHeightConstraints( minimumHeightScale );
const currentMinHeight = heightConstraints[ heightUnit ].min;
const currentMaxHeight = heightConstraints[ heightUnit ].max;

useEffect( () => {
if ( height < currentMinHeight ) {
setAttributes( { height: currentMinHeight } );
}
}, [ hasDotsStyle, heightConstraints ] );

const onResizeStart = () => {
setIsResizing( true );
};

// Change handler for sidebar height control only.
const updateHeight = ( value ) => {
setAttributes( {
height: clamp(
parseFloat( value ), // Rounding or parsing as integer here isn't ideal for em and rem units.
currentMinHeight,
currentMaxHeight
),
heightUnit,
} );
};

const updateHeightUnit = ( value ) => {
setAttributes( {
height: heightConstraints[ value ].default,
heightUnit: value,
} );
};
const { top, bottom } = style?.spacing?.margin || {};
const marginUnit = parseUnit( top || bottom );
const { height, cssHeight } = getHeightFromStyle( style, marginUnit );

// ResizableBox callback to set height and force pixel units.
const onResizeStop = ( _event, _direction, elt ) => {
const onResize = ( _event, _direction, elt ) => {
const newHeight = parseInt( elt.clientHeight, 10 );
setAttributes( {
height: clamp(
parseInt( elt.clientHeight, 10 ),
heightConstraints.px.min,
heightConstraints.px.max
),
heightUnit: 'px',
style: {
...style,
spacing: {
...style?.spacing,
margin: calculateMargins( newHeight, top, bottom ),
},
},
} );
setIsResizing( false );
};

const cssHeight = `${ height }${ heightUnit }`;
const blockProps = useBlockProps();
const wrapperClasses = blockProps.className?.replace(
'wp-block-separator',
'wp-block-separator__wrapper'
);

// The block's className and styles are moved to the inner <hr> to retain
// the different styling approaches between themes. The use of bottom
Expand All @@ -87,8 +61,15 @@ function SeparatorEdit( props ) {
<>
<View
{ ...blockProps }
className={ wrapperClasses }
style={ { height: height ? cssHeight : undefined } }
className={ blockProps.className?.replace(
'wp-block-separator',
'wp-block-separator__wrapper'
) }
style={ {
height: height
? cssHeight
: MARGIN_CONSTRAINTS.px.minHeight,
} }
>
<HorizontalRule
className={ classnames( blockProps.className, {
Expand All @@ -98,6 +79,9 @@ function SeparatorEdit( props ) {
style={ {
backgroundColor: color.color,
color: color.color,
marginTop: top || MARGIN_CONSTRAINTS[ marginUnit ].min,
marginBottom:
bottom || MARGIN_CONSTRAINTS[ marginUnit ].min,
} }
/>
<ResizableBox
Expand All @@ -109,7 +93,7 @@ function SeparatorEdit( props ) {
) }
size={ {
height:
heightUnit === 'px' && height ? cssHeight : '100%',
marginUnit === 'px' && height ? cssHeight : '100%',
} }
enable={ {
top: false,
Expand All @@ -121,9 +105,13 @@ function SeparatorEdit( props ) {
bottomLeft: false,
topLeft: false,
} }
minHeight={ heightConstraints.px.min }
onResizeStart={ onResizeStart }
onResizeStop={ onResizeStop }
minHeight={ MARGIN_CONSTRAINTS.px.min * 2 } // Height will account for top and bottom margin.
onResizeStart={ () => setIsResizing( true ) }
onResize={ onResize }
onResizeStop={ ( ...args ) => {
onResize( ...args );
setIsResizing( false );
} }
showHandle={ isSelected }
__experimentalShowTooltip={ true }
__experimentalTooltipProps={ {
Expand All @@ -136,12 +124,9 @@ function SeparatorEdit( props ) {
<SeparatorSettings
color={ color }
setColor={ setColor }
minHeight={ currentMinHeight }
maxHeight={ currentMaxHeight }
height={ height }
heightUnit={ heightUnit }
updateHeight={ updateHeight }
updateHeightUnit={ updateHeightUnit }
marginUnit={ marginUnit }
separatorStyles={ style }
setAttributes={ setAttributes }
/>
</>
);
Expand Down
157 changes: 31 additions & 126 deletions packages/block-library/src/separator/edit.native.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,35 @@
/**
* External dependencies
*/
import classnames from 'classnames';
import { clamp } from 'lodash';

/**
* WordPress dependencies
*/
import {
HorizontalRule,
ResizableBox,
useConvertUnitToMobile,
} from '@wordpress/components';
import { useEffect, useState } from '@wordpress/element';
import { HorizontalRule, useConvertUnitToMobile } from '@wordpress/components';
import { withColors, useBlockProps } from '@wordpress/block-editor';
import { View } from '@wordpress/primitives';

/**
* Internal dependencies
*/
import SeparatorSettings from './separator-settings';
import { getHeightConstraints } from './shared';
import { MARGIN_CONSTRAINTS, parseUnit } from './shared';

function SeparatorEdit( props ) {
const { attributes, setAttributes, color, setColor, isSelected } = props;
const { height, heightUnit } = attributes;
const [ isResizing, setIsResizing ] = useState( false );

const hasDotsStyle = attributes.className?.indexOf( 'is-style-dots' ) >= 0;
const minimumHeightScale = hasDotsStyle ? 1.5 : 1;
const heightConstraints = getHeightConstraints( minimumHeightScale );
const currentMinHeight = heightConstraints[ heightUnit ].min;
const currentMaxHeight = heightConstraints[ heightUnit ].max;

useEffect( () => {
if ( height < currentMinHeight ) {
setAttributes( { height: currentMinHeight } );
}
}, [ hasDotsStyle, heightConstraints ] );

const onResizeStart = () => {
setIsResizing( true );
};

// Change handler for sidebar height control only.
const updateHeight = ( value ) => {
setAttributes( {
height: clamp(
parseFloat( value ), // Rounding or parsing as integer here isn't ideal for em and rem units.
currentMinHeight,
currentMaxHeight
),
heightUnit,
} );
};

const updateHeightUnit = ( value ) => {
setAttributes( {
height: heightConstraints[ value ].default,
heightUnit: value,
} );
};

// ResizableBox callback to set height and force pixel units.
const onResizeStop = ( _event, _direction, elt ) => {
setAttributes( {
height: clamp(
parseInt( elt.clientHeight, 10 ),
heightConstraints.px.min,
heightConstraints.px.max
),
heightUnit: 'px',
} );
setIsResizing( false );
};

const blockProps = useBlockProps();
const wrapperClasses = blockProps.className?.replace(
'wp-block-separator',
'wp-block-separator__wrapper'
const {
attributes: { style },
setAttributes,
color,
setColor,
} = props;

const { top, bottom } = style?.spacing?.margin || {};
const marginUnit = parseUnit( top || bottom );
const currentMinMargin = MARGIN_CONSTRAINTS[ marginUnit ].min;

const convertedMarginTop = useConvertUnitToMobile(
parseFloat( top || 0 ) || currentMinMargin,
marginUnit
);

const convertedHeightValue = useConvertUnitToMobile(
height || currentMinHeight,
heightUnit
const convertedMarginBottom = useConvertUnitToMobile(
parseFloat( bottom || 0 ) || currentMinMargin,
marginUnit
);

// The block's className and styles are moved to the inner <hr> to retain
Expand All @@ -93,62 +39,21 @@ function SeparatorEdit( props ) {
// block selection.
return (
<>
<View
{ ...blockProps }
className={ wrapperClasses }
style={ { height: convertedHeightValue } }
>
<HorizontalRule
className={ classnames( blockProps.className, {
'has-background': color.color,
[ color.class ]: color.class,
} ) }
style={ {
backgroundColor: color.color,
color: color.color,
} }
/>
<ResizableBox
className={ classnames(
'block-library-separator__resize-container',
{
'is-selected': isSelected,
}
) }
size={ {
height: heightUnit === 'px' && height ? height : '100%',
} }
enable={ {
top: false,
right: false,
bottom: true, // Only enable bottom handle.
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
} }
minHeight={ heightConstraints.px.min }
onResizeStart={ onResizeStart }
onResizeStop={ onResizeStop }
showHandle={ isSelected }
__experimentalShowTooltip={ true }
__experimentalTooltipProps={ {
axis: 'y',
position: 'bottom',
isVisible: isResizing,
} }
/>
</View>
<HorizontalRule
{ ...useBlockProps() }
style={ {
backgroundColor: color.color,
color: color.color,
marginTop: convertedMarginTop,
marginBottom: convertedMarginBottom,
} }
/>
<SeparatorSettings
color={ color }
setColor={ setColor }
minHeight={ currentMinHeight }
maxHeight={ currentMaxHeight }
height={ height }
heightUnit={ heightUnit }
updateHeight={ updateHeight }
updateHeightUnit={ updateHeightUnit }
marginUnit={ marginUnit }
separatorStyles={ style }
setAttributes={ setAttributes }
/>
</>
);
Expand Down
9 changes: 5 additions & 4 deletions packages/block-library/src/separator/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,16 @@

// Duplicate selector to overcome theme specificity.
.editor-styles-wrapper .wp-block .wp-block-separator.wp-block-separator {
// Remove default margins and center within ResizableBox control.
left: 50%;
margin: 0;
position: absolute;
top: 50%;
width: 100%;
transform: translate(-50%, -50%);

&.is-style-dots {
border-top: none;
}
}

// Counter the added height of the dots style's pseudo after element
.wp-block-separator__wrapper.is-style-dots .is-style-dots {
transform: translateY(-0.75em);
}
Loading