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

Separator: Add means to control height #28409

Closed
wants to merge 10 commits into from
7 changes: 7 additions & 0 deletions packages/block-library/src/separator/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
},
"customColor": {
"type": "string"
},
"height": {
"type": "number"
},
"heightUnit": {
"type": "string",
"default": "px"
}
},
"supports": {
Expand Down
108 changes: 98 additions & 10 deletions packages/block-library/src/separator/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,121 @@
* External dependencies
*/
import classnames from 'classnames';
import { clamp } from 'lodash';

/**
* WordPress dependencies
*/
import { HorizontalRule } from '@wordpress/components';
import { HorizontalRule, ResizableBox } from '@wordpress/components';
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 { HEIGHT_CONSTRAINTS } from './shared';

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

const currentMinHeight = HEIGHT_CONSTRAINTS[ heightUnit ].min;
const currentMaxHeight = HEIGHT_CONSTRAINTS[ heightUnit ].max;

// Resize handler for when user is drag resizing block via ResizableBlock.
const onResize = ( _event, _direction, elt ) => {
setAttributes( {
height: clamp(
parseInt( elt.clientHeight, 10 ),
HEIGHT_CONSTRAINTS.px.min,
HEIGHT_CONSTRAINTS.px.max
),
heightUnit: 'px',
} );
};

const cssHeight = `${ height }${ heightUnit }`;
const blockProps = useBlockProps();
const margin = height
? `${ height / 2 }${ heightUnit }`
: `${ currentMinHeight / 2 }${ heightUnit }`;

function SeparatorEdit( { color, setColor, className } ) {
// The block's className and styles are moved to the inner <hr> to retain
// the different styling approaches between themes. The use of bottom
// borders and background colors prevents using padding internally on the
// edit component. Adjusting margins leads to losing visual indicators for
// block selection.
return (
<>
<HorizontalRule
{ ...useBlockProps( {
className: classnames( className, {
<View
{ ...blockProps }
className={ blockProps.className?.replace(
'wp-block-separator',
'wp-block-separator__wrapper'
) }
style={ { height: height ? cssHeight : currentMinHeight } }
>
<HorizontalRule
className={ classnames( blockProps.className, {
'has-background': color.color,
[ color.class ]: color.class,
} ),
style: {
} ) }
style={ {
backgroundColor: color.color,
color: color.color,
},
} ) }
marginTop: margin,
marginBottom: margin,
} }
/>
<ResizableBox
className={ classnames(
'block-library-separator__resize-container',
{
'is-selected': isSelected,
}
) }
size={ {
height:
heightUnit === 'px' && height ? cssHeight : '100%',
} }
enable={ {
top: false,
right: false,
bottom: true, // Only enable bottom handle.
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
} }
minHeight={ HEIGHT_CONSTRAINTS.px.min }
onResizeStart={ () => setIsResizing( true ) }
onResize={ onResize }
onResizeStop={ ( ...args ) => {
onResize( ...args );
setIsResizing( false );
} }
showHandle={ isSelected }
__experimentalShowTooltip={ true }
__experimentalTooltipProps={ {
axis: 'y',
position: 'bottom',
isVisible: isResizing,
} }
/>
</View>
<SeparatorSettings
color={ color }
setColor={ setColor }
minHeight={ currentMinHeight }
maxHeight={ currentMaxHeight }
height={ height }
heightUnit={ heightUnit }
setAttributes={ setAttributes }
/>
<SeparatorSettings color={ color } setColor={ setColor } />
</>
);
}
Expand Down
79 changes: 79 additions & 0 deletions packages/block-library/src/separator/edit.native.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
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 { HEIGHT_CONSTRAINTS } from './shared';

function SeparatorEdit( props ) {
const {
attributes: { height, heightUnit },
setAttributes,
color,
setColor,
} = props;

const currentMinHeight = HEIGHT_CONSTRAINTS[ heightUnit ].min;
const currentMaxHeight = HEIGHT_CONSTRAINTS[ heightUnit ].max;

const convertedHeightValue = useConvertUnitToMobile(
height || currentMinHeight,
heightUnit
);

const margin = convertedHeightValue / 2;
const blockProps = useBlockProps();

// The block's className and styles are moved to the inner <hr> to retain
// the different styling approaches between themes. The use of bottom
// borders and background colors prevents using padding internally on the
// edit component. Adjusting margins leads to losing visual indicators for
// block selection.
return (
<>
<View
{ ...blockProps }
className={ blockProps.className?.replace(
'wp-block-separator',
'wp-block-separator__wrapper'
) }
style={ { height: convertedHeightValue } }
>
<HorizontalRule
className={ classnames( blockProps.className, {
'has-background': color.color,
[ color.class ]: color.class,
} ) }
style={ {
backgroundColor: color.color,
color: color.color,
marginTop: margin,
marginBottom: margin,
} }
/>
</View>
<SeparatorSettings
color={ color }
setColor={ setColor }
minHeight={ currentMinHeight }
maxHeight={ currentMaxHeight }
height={ height || currentMinHeight }
heightUnit={ heightUnit }
setAttributes={ setAttributes }
/>
</>
);
}

export default withColors( 'color', { textColor: 'color' } )( SeparatorEdit );
26 changes: 26 additions & 0 deletions packages/block-library/src/separator/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,29 @@
padding-top: 0.1px;
padding-bottom: 0.1px;
}

.block-library-separator__wrapper {
position: relative;
}

.editor-styles-wrapper {
.wp-block.wp-block-separator__wrapper {
margin: 0 auto;
}
}

// Duplicate selector to overcome theme specificity.
.editor-styles-wrapper .wp-block .wp-block-separator.wp-block-separator {
margin: 0;
position: absolute;
width: 100%;

&.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);
}
5 changes: 4 additions & 1 deletion packages/block-library/src/separator/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import classnames from 'classnames';
import { getColorClassName, useBlockProps } from '@wordpress/block-editor';

export default function separatorSave( { attributes } ) {
const { color, customColor } = attributes;
const { color, customColor, height, heightUnit } = attributes;
const margin = height ? `${ height / 2 }${ heightUnit }` : undefined;

// the hr support changing color using border-color, since border-color
// is not yet supported in the color palette, we use background-color
Expand All @@ -27,6 +28,8 @@ export default function separatorSave( { attributes } ) {
const style = {
backgroundColor: backgroundClass ? undefined : customColor,
color: colorClass ? undefined : customColor,
marginBottom: margin,
marginTop: margin,
};

return <hr { ...useBlockProps.save( { className, style } ) } />;
Expand Down
75 changes: 61 additions & 14 deletions packages/block-library/src/separator/separator-settings.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,69 @@
/**
* External dependencies
*/
import { clamp } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { InspectorControls, PanelColorSettings } from '@wordpress/block-editor';
import {
PanelBody,
__experimentalUnitControl as UnitControl,
} from '@wordpress/components';

/**
* Internal dependencies
*/
import { HEIGHT_CONSTRAINTS, HEIGHT_CSS_UNITS } from './shared';

const SeparatorSettings = ( props ) => {
const { color, setColor, height, heightUnit, setAttributes } = props;
const minHeight = HEIGHT_CONSTRAINTS[ heightUnit ].min;
const maxHeight = HEIGHT_CONSTRAINTS[ heightUnit ].max;

const updateHeight = ( value ) => {
setAttributes( {
height: clamp( parseFloat( value ), minHeight, maxHeight ),
heightUnit,
} );
};

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

const SeparatorSettings = ( { color, setColor } ) => (
<InspectorControls>
<PanelColorSettings
title={ __( 'Color settings' ) }
colorSettings={ [
{
value: color.color,
onChange: setColor,
label: __( 'Color' ),
},
] }
></PanelColorSettings>
</InspectorControls>
);
return (
<InspectorControls>
<PanelBody title={ __( 'Separator settings' ) }>
<UnitControl
label={ __( 'Height' ) }
min={ minHeight }
max={ maxHeight }
onChange={ updateHeight }
onUnitChange={ updateHeightUnit }
value={ `${ height }${ heightUnit }` }
unit={ heightUnit }
units={ HEIGHT_CSS_UNITS }
step={ heightUnit === 'px' ? '1' : '0.25' }
/>
</PanelBody>
<PanelColorSettings
title={ __( 'Color settings' ) }
colorSettings={ [
{
value: color.color,
onChange: setColor,
label: __( 'Color' ),
},
] }
></PanelColorSettings>
</InspectorControls>
);
};

export default SeparatorSettings;
Loading