Skip to content

Commit

Permalink
Buttons block: overhaul alignment/justification controls (#23168)
Browse files Browse the repository at this point in the history
* Buttons block: overhaul alignment/justification controls.

* Make icon names consistent with CSS terminology.

* Move onClick function inline.

* Mobile - Buttons block - Support content justification and ContentJustificationDropdown (#26166)

* Fix control title inconsistency.

Co-authored-by: Gerardo Pacheco <[email protected]>
  • Loading branch information
ZebulanStanphill and Gerardo Pacheco authored Oct 28, 2020
1 parent 148e2b2 commit a03ea51
Show file tree
Hide file tree
Showing 20 changed files with 412 additions and 52 deletions.
2 changes: 1 addition & 1 deletion lib/patterns/two-buttons.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

return array(
'title' => __( 'Two buttons', 'gutenberg' ),
'content' => "<!-- wp:buttons {\"align\":\"center\"} -->\n<div class=\"wp-block-buttons aligncenter\"><!-- wp:button {\"borderRadius\":2,\"style\":{\"color\":{\"background\":\"#ba0c49\",\"text\":\"#fffffa\"}}} -->\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-color has-background\" style=\"border-radius:2px;background-color:#ba0c49;color:#fffffa\">" . __( 'Download now', 'gutenberg' ) . "</a></div>\n<!-- /wp:button -->\n\n<!-- wp:button {\"borderRadius\":2,\"style\":{\"color\":{\"text\":\"#ba0c49\"}},\"className\":\"is-style-outline\"} -->\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link has-text-color\" style=\"border-radius:2px;color:#ba0c49\">" . __( 'About Cervantes', 'gutenberg' ) . "</a></div>\n<!-- /wp:button --></div>\n<!-- /wp:buttons -->",
'content' => "<!-- wp:buttons {\"contentJustification\":\"center\"} -->\n<div class=\"wp-block-buttons is-content-justification-center\"><!-- wp:button {\"borderRadius\":2,\"style\":{\"color\":{\"background\":\"#ba0c49\",\"text\":\"#fffffa\"}}} -->\n<div class=\"wp-block-button\"><a class=\"wp-block-button__link has-text-color has-background\" style=\"border-radius:2px;background-color:#ba0c49;color:#fffffa\">" . __( 'Download now', 'gutenberg' ) . "</a></div>\n<!-- /wp:button -->\n\n<!-- wp:button {\"borderRadius\":2,\"style\":{\"color\":{\"text\":\"#ba0c49\"}},\"className\":\"is-style-outline\"} -->\n<div class=\"wp-block-button is-style-outline\"><a class=\"wp-block-button__link has-text-color\" style=\"border-radius:2px;color:#ba0c49\">" . __( 'About Cervantes', 'gutenberg' ) . "</a></div>\n<!-- /wp:button --></div>\n<!-- /wp:buttons -->",
'viewportWidth' => 500,
'categories' => array( 'buttons' ),
'description' => _x( 'Two buttons, one filled and one outlined, side by side.', 'Block pattern description', 'gutenberg' ),
Expand Down
8 changes: 6 additions & 2 deletions packages/block-library/src/buttons/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@
"apiVersion": 2,
"name": "core/buttons",
"category": "design",
"attributes": {
"contentJustification": {
"type": "string"
}
},
"supports": {
"anchor": true,
"align": true,
"alignWide": false
"align": [ "wide", "full" ]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* WordPress dependencies
*/
import { DropdownMenu } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
contentJustificationCenterIcon,
contentJustificationLeftIcon,
contentJustificationRightIcon,
} from './icons';

const DEFAULT_ALLOWED_VALUES = [ 'left', 'center', 'right' ];

const CONTROLS = {
left: {
icon: contentJustificationLeftIcon,
title: __( 'Justify content left' ),
},
center: {
icon: contentJustificationCenterIcon,
title: __( 'Justify content center' ),
},
right: {
icon: contentJustificationRightIcon,
title: __( 'Justify content right' ),
},
};

const DEFAULT_ICON = CONTROLS.center.icon;

/**
* Dropdown for selecting a content justification option.
*
* @param {Object} props Component props.
* @param {string[]} [props.allowedValues] List of options to include. Default:
* ['left', 'center', 'right'].
* @param {()=>void} props.onChange Callback to run when an option is
* selected in the dropdown.
* @param {Object} props.toggleProps Props to pass to the dropdown toggle.
* @param {string} props.value The current content justification
* value.
*
* @return {WPComponent} The component.
*/
export default function ContentJustificationDropdown( {
onChange,
allowedValues = DEFAULT_ALLOWED_VALUES,
toggleProps,
value,
} ) {
return (
<DropdownMenu
icon={ CONTROLS[ value ]?.icon ?? DEFAULT_ICON }
label={ __( 'Change content justification' ) }
controls={ allowedValues.map( ( allowedValue ) => {
return {
...CONTROLS[ allowedValue ],
isActive: value === allowedValue,
role: 'menuitemradio',
onClick: () =>
onChange(
value === allowedValue ? undefined : allowedValue
),
};
} ) }
toggleProps={ toggleProps }
/>
);
}
38 changes: 38 additions & 0 deletions packages/block-library/src/buttons/deprecated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/**
* WordPress dependencies
*/
import { InnerBlocks } from '@wordpress/block-editor';

const deprecated = [
{
supports: {
align: [ 'center', 'left', 'right' ],
anchor: true,
},
save() {
return (
<div>
<InnerBlocks.Content />
</div>
);
},
isEligible( { align } ) {
return align && [ 'center', 'left', 'right' ].includes( align );
},
migrate( attributes ) {
return {
...attributes,
align: undefined,
// Floating Buttons blocks shouldn't have been supported in the
// first place. Most users using them probably expected them to
// act like content justification controls, so these blocks are
// migrated to use content justification.
// As for center-aligned Buttons blocks, the content justification
// equivalent will create an identical end result in most cases.
contentJustification: attributes.align,
};
},
},
];

export default deprecated;
46 changes: 41 additions & 5 deletions packages/block-library/src/buttons/edit.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import {
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
BlockControls,
useBlockProps,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
} from '@wordpress/block-editor';
import { ToolbarGroup, ToolbarItem } from '@wordpress/components';

/**
* Internal dependencies
*/
import { name as buttonBlockName } from '../button/';
import { name as buttonBlockName } from '../button';
import ContentJustificationDropdown from './content-justification-dropdown';

const ALLOWED_BLOCKS = [ buttonBlockName ];
const BUTTONS_TEMPLATE = [ [ 'core/button' ] ];

function ButtonsEdit() {
const blockProps = useBlockProps();
function ButtonsEdit( {
attributes: { contentJustification },
setAttributes,
} ) {
const blockProps = useBlockProps( {
className: classnames( {
[ `is-content-justification-${ contentJustification }` ]: contentJustification,
} ),
} );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
allowedBlocks: ALLOWED_BLOCKS,
template: BUTTONS_TEMPLATE,
Expand All @@ -25,7 +40,28 @@ function ButtonsEdit() {
alignments: [],
},
} );
return <div { ...innerBlocksProps } />;
return (
<>
<BlockControls>
<ToolbarGroup>
<ToolbarItem>
{ ( toggleProps ) => (
<ContentJustificationDropdown
toggleProps={ toggleProps }
value={ contentJustification }
onChange={ ( updatedValue ) => {
setAttributes( {
contentJustification: updatedValue,
} );
} }
/>
) }
</ToolbarItem>
</ToolbarGroup>
</BlockControls>
<div { ...innerBlocksProps } />
</>
);
}

export default ButtonsEdit;
28 changes: 25 additions & 3 deletions packages/block-library/src/buttons/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,28 @@ import { View } from 'react-native';
/**
* WordPress dependencies
*/
import { InnerBlocks } from '@wordpress/block-editor';
import { BlockControls, InnerBlocks } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
import { useResizeObserver } from '@wordpress/compose';
import { useDispatch, useSelect } from '@wordpress/data';
import { useState, useEffect, useRef } from '@wordpress/element';
import { ToolbarGroup, ToolbarItem } from '@wordpress/components';

/**
* Internal dependencies
*/
import { name as buttonBlockName } from '../button/';
import styles from './editor.scss';
import ContentJustificationDropdown from './content-justification-dropdown';

const ALLOWED_BLOCKS = [ buttonBlockName ];
const BUTTONS_TEMPLATE = [ [ 'core/button' ] ];

export default function ButtonsEdit( {
attributes: { align },
attributes: { contentJustification },
clientId,
isSelected,
setAttributes,
} ) {
const [ resizeObserver, sizes ] = useResizeObserver();
const [ maxWidth, setMaxWidth ] = useState( 0 );
Expand Down Expand Up @@ -85,6 +88,12 @@ export default function ButtonsEdit( {
selectBlock( insertedBlock.clientId );
}, 200 );

function onChangeContentJustification( updatedValue ) {
setAttributes( {
contentJustification: updatedValue,
} );
}

const renderFooterAppender = useRef( () => (
<View style={ styles.appenderContainer }>
<InnerBlocks.ButtonBlockAppender
Expand All @@ -98,6 +107,19 @@ export default function ButtonsEdit( {

return (
<>
<BlockControls>
<ToolbarGroup>
<ToolbarItem>
{ ( toggleProps ) => (
<ContentJustificationDropdown
toggleProps={ toggleProps }
value={ contentJustification }
onChange={ onChangeContentJustification }
/>
) }
</ToolbarItem>
</ToolbarGroup>
</BlockControls>
{ resizeObserver }
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
Expand All @@ -106,7 +128,7 @@ export default function ButtonsEdit( {
shouldRenderFooterAppender && renderFooterAppender.current
}
orientation="horizontal"
horizontalAlignment={ align }
horizontalAlignment={ contentJustification }
onDeleteBlock={
shouldDelete ? () => removeBlock( clientId ) : undefined
}
Expand Down
3 changes: 2 additions & 1 deletion packages/block-library/src/buttons/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
}

.wp-block-buttons > .block-list-appender {
display: inline-block;
display: inline-flex;
align-items: center;
}
37 changes: 37 additions & 0 deletions packages/block-library/src/buttons/icons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* WordPress dependencies
*/
import { Path, SVG } from '@wordpress/components';

export const contentJustificationLeftIcon = (
<SVG
width="20"
height="20"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<Path d="M11 16v-3h10v-2H11V8l-4 4 4 4zM5 4H3v16h2V4z" />
</SVG>
);

export const contentJustificationCenterIcon = (
<SVG
width="20"
height="20"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<Path d="M5 8v3H1v2h4v3l4-4-4-4zm14 8v-3h4v-2h-4V8l-4 4 4 4zM13 4h-2v16h2V4z" />
</SVG>
);

export const contentJustificationRightIcon = (
<SVG
width="20"
height="20"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<Path d="M13 8v3H3v2h10v3l4-4-4-4zm8-4h-2v16h2V4z" />
</SVG>
);
2 changes: 2 additions & 0 deletions packages/block-library/src/buttons/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { button as icon } from '@wordpress/icons';
/**
* Internal dependencies
*/
import deprecated from './deprecated';
import transforms from './transforms';
import edit from './edit';
import metadata from './block.json';
Expand Down Expand Up @@ -35,6 +36,7 @@ export const settings = {
},
],
},
deprecated,
transforms,
edit,
save,
Expand Down
15 changes: 13 additions & 2 deletions packages/block-library/src/buttons/save.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { InnerBlocks, useBlockProps } from '@wordpress/block-editor';

export default function save() {
export default function save( { attributes: { contentJustification } } ) {
return (
<div { ...useBlockProps.save() }>
<div
{ ...useBlockProps.save( {
className: classnames( {
[ `is-content-justification-${ contentJustification }` ]: contentJustification,
} ),
} ) }
>
<InnerBlocks.Content />
</div>
);
Expand Down
Loading

0 comments on commit a03ea51

Please sign in to comment.