Skip to content

Commit

Permalink
Block Library: Avoid column width auto-adjustment when sibling width …
Browse files Browse the repository at this point in the history
…changes (#19515)

* Block Library: Avoid column auto-adjustment when width changes

* Block Library: Column: Add step attribute to column width range input

Without this attribute value, if a user would enter a decimal value in the input range, the result of Element#checkValidity (in RangeControl) would be `false`, thus making it difficult/impossible to enter non-whole-number widths (e.g. `33.3`).

There's a balance here between the effects of step, where ArrowUp/ArrowDown will now increment/decrement in smaller intervals than previously. This becomes further problematic if we want to support smaller decimal values (e.g. 33.33). A potential alternative would be to change the validation behavior of RangeControl to use a custom validation procedure in place of `Element#checkValidity`.

* Edit Post: Remove horizontal margins from notices rendered in sidebar

* Block Library: Column: Show Notice when total width is not 100%

* Block Library: Show Columns block range control only when "Manual" width

* Revert "Block Library: Show Columns block range control only when "Manual" width"

This reverts commit 92b8fd4.

* Revert "Block Library: Column: Show Notice when total width is not 100%"

This reverts commit e25b28b.

* Revert "Edit Post: Remove horizontal margins from notices rendered in sidebar"

This reverts commit 9f79462.

* Block Library: Column: Add placeholder label for auto width

* Block Library: Columns: Consider explicit only if all blocks

Avoid situation where adding or removing a Column in a Columns would forcefully assign width to a block which did not previously have a width. Only opt to redistribute widths to explicit numbers if all blocks already have widths.

* Block Library: Column: Grow to maximally fill space
  • Loading branch information
aduth authored Feb 10, 2020
1 parent 6c591f4 commit 26e2bf6
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 109 deletions.
70 changes: 8 additions & 62 deletions packages/block-library/src/column/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
import classnames from 'classnames';
import { forEach, find, difference } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -18,22 +17,11 @@ import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
toWidthPrecision,
getTotalColumnsWidth,
getColumnWidths,
getAdjacentBlocks,
getRedistributedColumnWidths,
} from '../columns/utils';

function ColumnEdit( {
attributes,
setAttributes,
className,
updateAlignment,
updateWidth,
hasChildBlocks,
} ) {
const { verticalAlignment, width } = attributes;
Expand All @@ -55,11 +43,17 @@ function ColumnEdit( {
<RangeControl
label={ __( 'Percentage width' ) }
value={ width || '' }
onChange={ updateWidth }
onChange={ ( nextWidth ) => {
setAttributes( { width: nextWidth } );
} }
min={ 0 }
max={ 100 }
step={ 0.1 }
required
allowReset
placeholder={
width === undefined ? __( 'Auto' ) : undefined
}
/>
</PanelBody>
</InspectorControls>
Expand Down Expand Up @@ -104,54 +98,6 @@ export default compose(
verticalAlignment: null,
} );
},
updateWidth( width ) {
const { clientId } = ownProps;
const { updateBlockAttributes } = dispatch(
'core/block-editor'
);
const { getBlockRootClientId, getBlocks } = registry.select(
'core/block-editor'
);

// Constrain or expand siblings to account for gain or loss of
// total columns area.
const columns = getBlocks( getBlockRootClientId( clientId ) );
const adjacentColumns = getAdjacentBlocks( columns, clientId );

// The occupied width is calculated as the sum of the new width
// and the total width of blocks _not_ in the adjacent set.
const occupiedWidth =
width +
getTotalColumnsWidth(
difference( columns, [
find( columns, { clientId } ),
...adjacentColumns,
] )
);

// Compute _all_ next column widths, in case the updated column
// is in the middle of a set of columns which don't yet have
// any explicit widths assigned (include updates to those not
// part of the adjacent blocks).
const nextColumnWidths = {
...getColumnWidths( columns, columns.length ),
[ clientId ]: toWidthPrecision( width ),
...getRedistributedColumnWidths(
adjacentColumns,
100 - occupiedWidth,
columns.length
),
};

forEach(
nextColumnWidths,
( nextColumnWidth, columnClientId ) => {
updateBlockAttributes( columnClientId, {
width: nextColumnWidth,
} );
}
);
},
};
} )
)( ColumnEdit );
1 change: 1 addition & 0 deletions packages/block-library/src/column/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const settings = {
style: {
flexBasis: width + '%',
},
'data-has-explicit-width': true,
};
}
},
Expand Down
14 changes: 11 additions & 3 deletions packages/block-library/src/columns/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,18 @@
// Responsiveness: Show at most one columns on mobile.
flex-basis: 100%;

// Beyond mobile, allow 2 columns.
@include break-small() {
flex-basis: calc(50% - (#{$grid-size-large}));
flex-grow: 0;
flex-grow: 1;
flex-basis: auto;

// Beyond mobile, allow columns. Columns with an explicitly-
// assigned width should maintain their `flex-basis` width and
// not grow. All other blocks should automatically inherit the
// `flex-grow` to occupy the available space.
&[data-has-explicit-width] {
flex-grow: 0;
}

margin-left: 0;
margin-right: 0;
}
Expand Down
10 changes: 7 additions & 3 deletions packages/block-library/src/columns/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@

@include break-small() {

// Beyond mobile, allow 2 columns.
flex-basis: calc(50% - #{$grid-size-large});
flex-grow: 0;
// Beyond mobile, allow columns. Columns with an explicitly-assigned
// width should maintain their `flex-basis` width and not grow. All
// other blocks should automatically inherit the `flex-grow` to occupy
// the available space.
&[style] {
flex-grow: 0;
}

// Add space between the multiple columns. Themes can customize this if they wish to work differently.
// Only apply this beyond the mobile breakpoint, as there's only a single column on mobile.
Expand Down
44 changes: 23 additions & 21 deletions packages/block-library/src/columns/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import {
toWidthPrecision,
getAdjacentBlocks,
getEffectiveColumnWidth,
getTotalColumnsWidth,
getColumnWidths,
Expand All @@ -25,25 +24,6 @@ describe( 'toWidthPrecision', () => {
} );
} );

describe( 'getAdjacentBlocks', () => {
const blockA = { clientId: 'a' };
const blockB = { clientId: 'b' };
const blockC = { clientId: 'c' };
const blocks = [ blockA, blockB, blockC ];

it( 'should return blocks after clientId', () => {
const result = getAdjacentBlocks( blocks, 'b' );

expect( result ).toEqual( [ blockC ] );
} );

it( 'should return blocks before clientId if clientId is last', () => {
const result = getAdjacentBlocks( blocks, 'c' );

expect( result ).toEqual( [ blockA, blockB ] );
} );
} );

describe( 'getEffectiveColumnWidth', () => {
it( 'should return attribute value if set, rounded to precision', () => {
const block = { attributes: { width: 50.108 } };
Expand Down Expand Up @@ -186,7 +166,29 @@ describe( 'hasExplicitColumnWidths', () => {
} );

it( 'returns true if a block has explicit width', () => {
const blocks = [ { attributes: { width: 10 } } ];
const blocks = [ { attributes: { width: 100 } } ];

const result = hasExplicitColumnWidths( blocks );

expect( result ).toBe( true );
} );

it( 'returns false if some, not all blocks have explicit width', () => {
const blocks = [
{ attributes: { width: 10 } },
{ attributes: { width: undefined } },
];

const result = hasExplicitColumnWidths( blocks );

expect( result ).toBe( false );
} );

it( 'returns true if all blocks have explicit width', () => {
const blocks = [
{ attributes: { width: 10 } },
{ attributes: { width: 90 } },
];

const result = hasExplicitColumnWidths( blocks );

Expand Down
22 changes: 2 additions & 20 deletions packages/block-library/src/columns/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { findIndex, sumBy, merge, mapValues } from 'lodash';
import { sumBy, merge, mapValues } from 'lodash';

/**
* Returns a column width attribute value rounded to standard precision.
Expand All @@ -14,24 +14,6 @@ import { findIndex, sumBy, merge, mapValues } from 'lodash';
export const toWidthPrecision = ( value ) =>
Number.isFinite( value ) ? parseFloat( value.toFixed( 2 ) ) : undefined;

/**
* Returns the considered adjacent to that of the specified `clientId` for
* resizing consideration. Adjacent blocks are those occurring after, except
* when the given block is the last block in the set. For the last block, the
* behavior is reversed.
*
* @param {WPBlock[]} blocks Block objects.
* @param {string} clientId Client ID to consider for adjacent blocks.
*
* @return {WPBlock[]} Adjacent block objects.
*/
export function getAdjacentBlocks( blocks, clientId ) {
const index = findIndex( blocks, { clientId } );
const isLastBlock = index === blocks.length - 1;

return isLastBlock ? blocks.slice( 0, index ) : blocks.slice( index + 1 );
}

/**
* Returns an effective width for a given block. An effective width is equal to
* its attribute value if set, or a computed value assuming equal distribution.
Expand Down Expand Up @@ -115,7 +97,7 @@ export function getRedistributedColumnWidths(
* @return {boolean} Whether columns have explicit widths.
*/
export function hasExplicitColumnWidths( blocks ) {
return blocks.some( ( block ) =>
return blocks.every( ( block ) =>
Number.isFinite( block.attributes.width )
);
}
Expand Down

0 comments on commit 26e2bf6

Please sign in to comment.