Open augustuswm opened 3 years ago
@augustuswm What are the additional alignment options you're looking to add?
It depends on the frontend that we are implementing, but for a current project we are working on we would be looking to add additional left / right floating alignments for images and multiple "Wide" alignments.
For images we have a standard left floated treatment that aligns with the left hand edge of the text as well as a left floated treatment that extends out past the left hand edge. (With the same options for right floating images).
The wide alignment case is simpler, essentially adding (for lack of better names) a slight wide and extra wide option. Alignment widths that are narrower and wider than the Wide alignment.
@augustuswm: were you able to add any more alignment options? If so, would you care to share how you achieved this?
@landwire - We have not. That work was put off as getting something implemented looked like it would be too much effort for what we were going to use it for. We may revisit in the next few months depending on what priorities look like.
Taking a quick 2 minute look at the master branch, I think the same core issue exists as it doesn't look like there is an api to modify BLOCK_ALIGNMENTS_CONTROLS
. Certainly possible I've missed a change though.
This is similar to something we would like to achieve. Most of the time we have a layout with a base content width, which is used nearly throughout all pages. But there are elements that need to be narrower. So what we would need instead of "no alignment (default), wide, full" is something like "narrow, no alignment (default), wide (maybe), full". I know this could be done by using the default width on every element that needs to be narrow and wide on every other element. But that is not very intuitiv when setting up a page.
Have you any thoughts on this?
This would be beneficial on so many projects. Right now we just use custom classes to alter alignment, but that's not the smoothest use of Gutenberg. And since users can't select multiple block styles, we're lacking any sort of UI based design features for alignment outside of the box.
A filter for BLOCK_ALIGNMENTS_CONTROLS
would work great, as then my parent theme can supply additional alignments, and take advantage of wp.hooks.addFilter
to enable them on specific blocks for each project.
I'm trying to achieve the same as well. Most websites are using wide container on desktop, usually 1200px and higher. A Narrow option or even Custom Width is vital to limit certain sections on desktop. It can be useful for almost all block types such as single paragraph, images or even columns block. In my opinion, asking customers to add a "align-narrow" CSS class through Additional CSS Classes field is "asking too much" :)
I would really like this too. I'd love to be able to use a filter to add to the alignment options.
Right now I make a filter that adds an option for "extra wide" in the sidebar, but it's hard to explain to clients why they choose an alignment option on the block toolbar, but for "extra wide" they need to use the sidebar.
This is not at all PR ready, but internally at my company we are using the following if it is helpful to sketch out the idea. It is by no means extensively tested, and is really targeted to work for our use case.
Replace direct use of BLOCK_ALIGNMENTS_CONTROLS
with filtered value in
packages/block-editor/src/components/block-alignment-control/ui.js
const blockAlignmentControls = applyFilters('layout.alignments.controls', BLOCK_ALIGNMENTS_CONTROLS);
Replace default use of DEFAULT_CONTROLS
and direct use of WIDE_CONTROLS
in
packages/block-editor/src/components/block-alignment-control/use-available-alignments.js
controls = applyFilters('layout.alignments.availableControls', controls);
const { alignments: availableAlignments = applyFilters('layout.alignments.availableControls', DEFAULT_CONTROLS) } = layout;
const wideControls = applyFilters('layout.alignments.availableWideControls', WIDE_CONTROLS);
Filter alignments returned from getAlignments
for flow layout in
packages/block-editor/src/layouts/flow.js
return applyFilters('layout.alignments', alignments);
Filter default controls used by useAvailableAlignments
in
packages/block-editor/src/components/block-alignment-control/use-available-alignments.js
export default function useAvailableAlignments(controls = applyFilters('layout.alignments.availableControls', DEFAULT_CONTROLS)) {
Filter direct use of ALL_ALIGNMENTS
and WIDE_ALIGNMENTS
in
packages/block-editor/src/hooks/align.js
let allAlignments = applyFilters('layout.alignments.allValid', ALL_ALIGNMENTS);
return without(validAlignments, ...applyFilters('layout.alignments.allWide', WIDE_ALIGNMENTS));
There is likely more to do to make this really generic and work everywhere, but we use these filters in to extend the list of alignments to ['left', 'center', 'right', 'narrow', 'wide', 'extrawide', 'full']
I would like to add the option of small
alignment myself. Sometimes you just want an element to end up a tiny bit smaller in width then other blocks. To be able to extend the allignments would be a great addition.
I'm a bit new to block development and not familiar with react. But I was playing around with native javascript here. Unfortunately, there is no way to extend the core block alignment toolbar. But it is possible to create our own. Here's my solution with a cool advantage: you can extend your custom alignments like narrowWidth
.
Another advantage is that you can use "wide
" and "full
" even if a block is nested as innerBlock.
Apart from the fact that the control element does not appear as active, it already works very well. I think I need to use other components here and work with React UseState. Anyone interested is welcome to help.
var {
__,
} = wp.i18n;
var {
BlockControls,
useBlockProps,
} = wp.blockEditor;
var {
ToolbarDropdownMenu,
ToolbarGroup,
DropdownMenu,
MenuGroup,
MenuItem,
} = wp.components;
var {
createHigherOrderComponent,
} = wp.compose;
var {
getBlockSupport,
} = wp.blocks;
var {
Fragment,
createElement,
} = wp.element;
var el = createElement;
/*
* Disable default "align" to hide the core block alignment toolbar.
* Clone the block specific "align" supports values and store these in "alignCustom" instead.
*/
function modifyBlockAlignmentSupport( settings, name ) {
if ( ! name.includes('acf/') ) {
// Only modify our acf blocks
return settings;
}
const hasAlignSupport = getBlockSupport( name, 'align', false );
if( ! hasAlignSupport ) {
return settings;
}
// Get the original align values from the block supports settings
let originalAlignSupport = settings.supports.align;
// Modify the default block supports settings
newSettings = {
...settings,
supports: {
...settings.supports,
align: false, // <-- This will disable the default align to hide the core block alignment toolbar
alignCustom: originalAlignSupport, // <-- We clone the default align and store it here instead
}
};
return newSettings;
}
wp.hooks.addFilter( 'blocks.registerBlockType', 'plugin-name/modify-block-align-support', modifyBlockAlignmentSupport );
/*
* Function to handle the block alignment icons
*/
function blockAlignIcon( name ) {
var icons = {
'none': 'M5 15h14V9H5v6zm0 4.8h14v-1.5H5v1.5zM5 4.2v1.5h14V4.2H5z',
'full': 'M5 4v11h14V4H5zm3 15.8h8v-1.5H8v1.5z',
'wide': 'M5 9v6h14V9H5zm11-4.8H8v1.5h8V4.2zM8 19.8h8v-1.5H8v1.5z',
'narrow': 'M5 9v6h14V9H5zm11-4.8H8v1.5h8V4.2zM8 19.8h8v-1.5H8v1.5z',
'left': 'M4 9v6h14V9H4zm8-4.8H4v1.5h8V4.2zM4 19.8h8v-1.5H4v1.5z',
'center': 'M7 9v6h10V9H7zM5 19.8h14v-1.5H5v1.5zM5 4.3v1.5h14V4.3H5z',
'right': 'M6 15h14V9H6v6zm6-10.8v1.5h8V4.2h-8zm0 15.6h8v-1.5h-8v1.5z',
}
//var path = icons.name ? icons.name : icons.none;
var path = icons[name];
return el('svg', { width: 24, height: 24 },
el('path', { d: path } )
);
}
/*
* Filter to add custom block alignment toolbar controls
*/
var customBlockAlignmentControls = createHigherOrderComponent( function( BlockEdit ) {
return function( props ) {
const blockName = props.name;
const currentAlign = props.attributes.align;
const originalEdit = el( BlockEdit, props );
// Check for block align support
const blockAlignSupport = getBlockSupport( blockName, 'alignCustom', false );
// We add this custom controls to our acf blocks only
if( ! blockName.includes('acf/') ) {
// Return unmodified block edit
return originalEdit;
}
// Do not add this custom controls if the block type has no align support
if( ! blockAlignSupport ) {
// Return unmodified block edit
return originalEdit;
}
// Get the current ToolbarDropdownMenu icon, depending on the selected align
let currentIcon = currentAlign ? currentAlign : 'none';
currentIcon = blockAlignIcon( currentIcon );
/*
* Define a function to set the "align" attribute, after selecting a specific block alignment
*/
function onChangeAlignment( newAlignment ) {
let iconName = newAlignment;
if( newAlignment === 'none' ) {
// Because we don't want a "alignnone" classname in our block
newAlignment = false;
}
// Change the block align attribute
props.setAttributes( {
align: newAlignment === undefined ? 'none' : newAlignment,
} );
// Change the current ToolbarDropdownMenu icon if the block align has been changed
const alignToolbarButton = document.querySelector('[aria-label="Align"]');
if( alignToolbarButton ) {
let iconPath = blockAlignIcon( iconName );
iconPath = iconPath.props.children.props.d;
alignToolbarButton.innerHTML = '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="' + iconPath + '"/></svg>';
}
}
/*
* List all possible block alignments
*/
const alignControls = {
none: __('None', 'textdomain'),
full: __('Full width', 'textdomain'),
wide: __('Wide width', 'textdomain'),
narrow: __('Narrow width', 'textdomain'),
left: __('Align left', 'textdomain'),
center: __('Align center', 'textdomain'),
right: __('Align right', 'textdomain'),
}
/*
* Build the toolbar block alignment controls depening on the align support of the block type
*/
const allowedAlignControls = [];
for( let key in alignControls ) {
if( ! blockAlignSupport.includes( key ) && key !== 'none' ) {
// [None] should be there all the time to reset other selected alignments
// Only add the current align control if it's supported
continue;
}
let controlTitle = alignControls[key];
let newControl = {
title: controlTitle,
icon: blockAlignIcon( key ),
onClick: () => onChangeAlignment( key ),
};
allowedAlignControls.push(newControl);
}
/*
* Re-Build the block toolbar and edit
*/
return el(
Fragment,
{},
el( BlockControls, {
key: 'controls',
group: 'default',
},
el( ToolbarGroup, null,
el( ToolbarDropdownMenu, {
label: 'Align',
icon: currentIcon,
controls: allowedAlignControls,
} ),
),
), el( BlockEdit, props )
);
};
}, 'withInspectorControls' );
wp.hooks.addFilter( 'editor.BlockEdit', 'plugin-name/with-inspector-controls', customBlockAlignmentControls );
Would be great if this could be done just by adding some layout settings in theme.json. That would be so helpful!
I've been looking for something like this since using gutenberg, pretty much all the designs I have to implement have more than wide and full alignement (it's often normal/wide/wider/fullscreen) but a flexible way to achieve this would be great. There's currently two ways of enabling wide and full alignment:
"layout": {
"contentSize": "886px",
"wideSize": "1114px"
},
A more generalized system with add_theme_support('alignments', true) and a configuration in theme.json like this:
"layout": {
"default": "700px",
"wide": "880px"
"wider": "1000px"
"even-wider": "1200px"
"full": "100vw"
}
or something like this:
{
"layout": {
"default": {
"name": "Default",
"size": "700px",
"icon": "<svg></svg>"
},
"wide": {
"name": "Wide",
"size": "800px",
"icon": "<svg></svg>"
},
"wider": {
"name": "Wider",
"size": "1000px",
"icon": "<svg></svg>"
},
"even-wider": {
"name": "Even wider",
"size": "1200px",
"icon": "<svg></svg>"
},
"full": {
"name": "Full",
"size": "100vw",
"icon": "<svg></svg>"
}
}
}
@markhowellsmead @talldan @skorasaurus what do you think ?
I've been waiting for this for five years. It looks as though no-one cares about this.
@mtias could we add this to the ongoing work over at #41241 or #33447 ?
As I said, pretty much all the websites I did over the last few years have been needing more than 3 alignments options, I'm guessing this is the case for a lot of people
This has been a constant source of friction for us when using Gutenberg, and is something I've mentioned in other threads (and I know many others have as well).
I do not understand why max-width options are not handled in theme.json
like almost every other value - with an array of options defined within the theme. Just like we are not limited to 3 color options, 3 font sizes, or 3 spacing values, we shouldn't be limited to 3 width options. Let theme and site developers decide what is best for their stakeholders.
As it works now, we are assigning our two most common widths to default
and wide
options, then adding custom classes to our child themes to take care of what should be narrow
or wider
options, for instance. This is very cumbersome to our clients who expect to be able to create their content in fundamental ways without resorting to utility classes.
@eric-michel This is so true. I cannot believe that it would be much code involved to allow more custom alignments like narrow and extrawide in theme.json. @augustuswm showed a good way to start I assume, but I have not checked the code in detail. It would be so helpful for developers as my clients also find it very annoying to use utility classes.
@landwire Agreed. I'm not sure how to bring more visibility to this issue given how long it's been waiting in the wings.
One workaround that does work is altering the content max-widths via the Layout setting in Group blocks:
But this solution is just as cumbersome as using utility classes - maybe moreso. If I want to regularly use a "narrow" alignment of 500px max width, I don't want to have to create a Group block where I manually enter 500px
into the "Content" field every single time. That's the antithesis of DRY.
Pinging @WordPress/outreach to get some more visibility and feedback on this, please. 🙏
Is your feature request related to a problem? Please describe.
Short: We would like to be able to extend
BLOCK_ALIGNMENTS_CONTROLS
at runtime.My apologies in advance if this is already configurable somewhere (or if this is not in the scope of Gutenberg) as I am still getting a handle on the Gutenberg source.
Longer: We currently develop our in house CMS on top of WordPress, and we were looking to extend the default alignment options. From what I can tell we can currently define custom alignment keys in our block registrations (
supports.align
) or filter existing block registrations to add additional alignment keys. While they are technically functional, these alignments do not have icons or titles in the AlignmentToolbar as they are not present in theBLOCK_ALIGNMENTS_CONTROLS
object that is defined in https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/block-alignment-toolbar/index.jsDescribe the solution you'd like
A filter we could hook with a function that would return the extended
BLOCK_ALIGNMENTS_CONTROLS
. This filter would then be invoked by the AlignmentToolbar instead of the referencing theBLOCK_ALIGNMENTS_CONTROLS
object.Describe alternatives you've considered
I think this functionality could also be handled by a registration model with a store, but that seems like a lot of extra work. I'm sure there are other options, but I'm not familiar enough with Gutenberg internals to suggest them.
Alternatively we can certainly solve this with a self-built version of Gutenberg, but we prefer to stay with the version distributed with WordPress releases if possible.