Skip to content

Commit

Permalink
Min Height: Add height control component with slider (#45875)
Browse files Browse the repository at this point in the history
* Min Height: Add height control component with slider

* Fix typo for rem unit

Co-authored-by: Ramon <ramonjd@users.noreply.github.com>

* Add some handling for switching between unit types

* Add storybook example

Co-authored-by: Ramon <ramonjd@users.noreply.github.com>
  • Loading branch information
andrewserong and ramonjd authored Nov 24, 2022
1 parent 2a50308 commit f592820
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 25 deletions.
123 changes: 123 additions & 0 deletions packages/block-editor/src/components/height-control/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';
import {
BaseControl,
RangeControl,
Flex,
FlexItem,
__experimentalSpacer as Spacer,
__experimentalUseCustomUnits as useCustomUnits,
__experimentalUnitControl as UnitControl,
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import useSetting from '../use-setting';

const RANGE_CONTROL_CUSTOM_SETTINGS = {
px: { max: 1000, step: 1 },
'%': { max: 100, step: 1 },
vw: { max: 100, step: 1 },
vh: { max: 100, step: 1 },
em: { max: 50, step: 0.1 },
rem: { max: 50, step: 0.1 },
};

export default function HeightControl( {
onChange,
label = __( 'Height' ),
value,
} ) {
const customRangeValue = parseFloat( value );

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

const selectedUnit =
useMemo(
() => parseQuantityAndUnitFromRawValue( value ),
[ value ]
)[ 1 ] ||
units[ 0 ]?.value ||
'px';

const handleSliderChange = ( next ) => {
onChange( [ next, selectedUnit ].join( '' ) );
};

const handleUnitChange = ( newUnit ) => {
// Attempt to smooth over differences between currentUnit and newUnit.
// This should slightly improve the experience of switching between unit types.
const [ currentValue, currentUnit ] =
parseQuantityAndUnitFromRawValue( value );

if ( [ 'em', 'rem' ].includes( newUnit ) && currentUnit === 'px' ) {
// Convert pixel value to an approximate of the new unit, assuming a root size of 16px.
onChange( ( currentValue / 16 ).toFixed( 2 ) + newUnit );
} else if (
[ 'em', 'rem' ].includes( currentUnit ) &&
newUnit === 'px'
) {
// Convert to pixel value assuming a root size of 16px.
onChange( Math.round( currentValue * 16 ) + newUnit );
} else if (
[ 'vh', 'vw', '%' ].includes( newUnit ) &&
currentValue > 100
) {
// When converting to `vh`, `vw`, or `%` units, cap the new value at 100.
onChange( 100 + newUnit );
}
};

return (
<fieldset className="block-editor-height-control">
<BaseControl.VisualLabel as="legend">
{ label }
</BaseControl.VisualLabel>
<Flex>
<FlexItem isBlock>
<UnitControl
value={ value }
units={ units }
onChange={ onChange }
onUnitChange={ handleUnitChange }
min={ 0 }
size={ '__unstable-large' }
/>
</FlexItem>
<FlexItem isBlock>
<Spacer marginX={ 2 } marginBottom={ 0 }>
<RangeControl
value={ customRangeValue }
min={ 0 }
max={
RANGE_CONTROL_CUSTOM_SETTINGS[ selectedUnit ]
?.max ?? 100
}
step={
RANGE_CONTROL_CUSTOM_SETTINGS[ selectedUnit ]
?.step ?? 0.1
}
withInputField={ false }
onChange={ handleSliderChange }
__nextHasNoMarginBottom
/>
</Spacer>
</FlexItem>
</Flex>
</fieldset>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';

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

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

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

export const Default = Template.bind( {} );
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.block-editor-height-control {
border: 0;
margin: 0;
padding: 0;
}
1 change: 1 addition & 0 deletions packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export { default as __experimentalColorGradientControl } from './colors-gradient
export { default as __experimentalColorGradientSettingsDropdown } from './colors-gradients/dropdown';
export { default as __experimentalPanelColorGradientSettings } from './colors-gradients/panel-color-gradient-settings';
export { default as __experimentalUseMultipleOriginColorsAndGradients } from './colors-gradients/use-multiple-origin-colors-and-gradients';
export { default as __experimentalHeightControl } from './height-control';
export {
default as __experimentalImageEditor,
ImageEditingProvider as __experimentalImageEditingProvider,
Expand Down
1 change: 0 additions & 1 deletion packages/block-editor/src/hooks/dimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ export function DimensionsPanel( props ) {
) }
{ ! isMinHeightDisabled && (
<ToolsPanelItem
className="single-column"
hasValue={ () => hasMinHeightValue( props ) }
label={ __( 'Min. height' ) }
onDeselect={ () => resetMinHeight( props ) }
Expand Down
21 changes: 2 additions & 19 deletions packages/block-editor/src/hooks/min-height.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';
import {
__experimentalUseCustomUnits as useCustomUnits,
__experimentalUnitControl as UnitControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import useSetting from '../components/use-setting';
import HeightControl from '../components/height-control';
import { DIMENSIONS_SUPPORT_KEY } from './dimensions';
import { cleanEmptyObject } from './utils';

Expand Down Expand Up @@ -81,17 +78,6 @@ export function MinHeightEdit( props ) {
setAttributes,
} = props;

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

if ( useIsMinHeightDisabled( props ) ) {
return null;
}
Expand All @@ -109,13 +95,10 @@ export function MinHeightEdit( props ) {
};

return (
<UnitControl
<HeightControl
label={ __( 'Min. height' ) }
value={ style?.dimensions?.minHeight }
units={ units }
onChange={ onChange }
min={ 0 }
size={ '__unstable-large' }
/>
);
}
1 change: 1 addition & 0 deletions packages/block-editor/src/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
@import "./components/date-format-picker/style.scss";
@import "./components/duotone-control/style.scss";
@import "./components/font-appearance-control/style.scss";
@import "./components/height-control/style.scss";
@import "./components/image-size-control/style.scss";
@import "./components/inner-blocks/style.scss";
@import "./components/inserter-list-item/style.scss";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from '@wordpress/components';
import {
__experimentalUseCustomSides as useCustomSides,
__experimentalHeightControl as HeightControl,
__experimentalSpacingSizesControl as SpacingSizesControl,
} from '@wordpress/block-editor';
import { Icon, positionCenter, stretchWide } from '@wordpress/icons';
Expand Down Expand Up @@ -556,19 +557,15 @@ export default function DimensionsPanel( { name } ) {
) }
{ showMinHeightControl && (
<ToolsPanelItem
className="single-column"
hasValue={ hasMinHeightValue }
label={ __( 'Min. height' ) }
onDeselect={ resetMinHeightValue }
isShownByDefault={ true }
>
<UnitControl
<HeightControl
label={ __( 'Min. height' ) }
value={ minHeightValue }
onChange={ setMinHeightValue }
units={ units }
min={ 0 }
size={ '__unstable-large' }
/>
</ToolsPanelItem>
) }
Expand Down

0 comments on commit f592820

Please sign in to comment.