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

Buttons block: overhaul alignment/justification controls #23168

Merged
merged 5 commits into from
Oct 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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( {
ZebulanStanphill marked this conversation as resolved.
Show resolved Hide resolved
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="https://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="https://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="https://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