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

Introduce the layout prop to InnerBlocks #26380

Merged
merged 2 commits into from
Oct 27, 2020
Merged

Introduce the layout prop to InnerBlocks #26380

merged 2 commits into from
Oct 27, 2020

Conversation

youknowriad
Copy link
Contributor

InnerBlocks as they stand today come with a number of assumptions about how their child blocks are laid out:

  • They assume that blocks are sequential, one after the other.
  • They assume that blocks are rendered with the default HTML positioning (without any style), we do some CSS hacks to support flex alignments in columns, buttons, but ideally, this could be a declarative API instead.
  • They assume that all "alignments" are available for their children: "wide", "full", "left", "right" and "center". This falls short very quickly, for example in narrow columns where we should probably forbid the wide alignments...
  • They don't allow things like absolute positioning, flex or grid positioning of their inner blocks.

This PR introduces a new prop/concept to inner blocks called layout and absorbs these assumptions into a "default" layout. The idea is that alternative layouts could be introduced to support different ways to layout the children blocks inside a container.

The PR also replaces the experimental AlignmentHookSettingsProvider context that was used in the Buttons block to remove alignments from the regular "core/button" block and makes the allowed alignments a property of the default layout: This will allow us to solve the pitfalls mentioned above allowing wide alignments in contexts where they don't make sense.

The vision

Positioning and laying out elements in HTML requires two things in general:

1- A definition of the layout strategy at the container level (think display: grid, display: flex or something else)
2- A property per children to define how it is specifically laid out.

Currently, in Gutenberg 1 is assumed as a regular default block container and sometimes tweaked adhoc in CSS. And 2 is in general implemented in blocks using the align attribute (wide, full, left, right). While this decent enough for the "default" layout, I'm thinking this behavior can be made more generic and more controlled:

  • InnerBlocks (or BlockList) defines the current layout (this means container blocks can choose their layout as they wish)
  • InnerBlocks also applies the layout strategy to the container automatically (flex, grid...) depending on the defined layout.
  • All blocks could have a position attribute which format differ between layout types: In the default layout, it could correspond to the current "align" attribute use in most blocks, in an absolute layout, it can be a {top, left, width, height} record, in a grid layout, it could be things like (area, start, end). And moving a block outside its current container should reset the position attribute.
  • Eventually, the UI of the editor can also react and adapts to the defined layout: For example, the movers might not make sense on the "absolute" layout, drag & drop could behave differently. A grid layout could trigger snapping...

Current state of the PR

It introduces an experimental layout concept, it allows tweaking the available alignments for the default layout per container, It's a starting point that is not engaging for the future as it doesn't introduce any change in behavior, or any public API yet.

@youknowriad youknowriad added [Feature] Block API API that allows to express the block paradigm. [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible [Type] Experimental Experimental feature or API. labels Oct 22, 2020
@youknowriad youknowriad self-assigned this Oct 22, 2020
@github-actions
Copy link

github-actions bot commented Oct 22, 2020

Size Change: +32 B (0%)

Total Size: 1.2 MB

Filename Size Change
build/block-editor/index.js 130 kB +27 B (0%)
build/block-library/index.js 145 kB -18 B (0%)
build/blocks/index.js 47.6 kB +23 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.54 kB 0 B
build/api-fetch/index.js 3.35 kB 0 B
build/autop/index.js 2.72 kB 0 B
build/blob/index.js 668 B 0 B
build/block-directory/index.js 8.59 kB 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-editor/style-rtl.css 11 kB 0 B
build/block-editor/style.css 11 kB 0 B
build/block-library/editor-rtl.css 8.93 kB 0 B
build/block-library/editor.css 8.93 kB 0 B
build/block-library/style-rtl.css 7.75 kB 0 B
build/block-library/style.css 7.75 kB 0 B
build/block-library/theme-rtl.css 741 B 0 B
build/block-library/theme.css 741 B 0 B
build/block-serialization-default-parser/index.js 1.77 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/components/index.js 170 kB 0 B
build/components/style-rtl.css 15.4 kB 0 B
build/components/style.css 15.4 kB 0 B
build/compose/index.js 9.63 kB 0 B
build/core-data/index.js 12.1 kB 0 B
build/data-controls/index.js 684 B 0 B
build/data/index.js 8.63 kB 0 B
build/date/index.js 31.9 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 569 B 0 B
build/dom/index.js 4.43 kB 0 B
build/edit-navigation/index.js 10.8 kB 0 B
build/edit-navigation/style-rtl.css 881 B 0 B
build/edit-navigation/style.css 885 B 0 B
build/edit-post/index.js 306 kB 0 B
build/edit-post/style-rtl.css 6.37 kB 0 B
build/edit-post/style.css 6.35 kB 0 B
build/edit-site/index.js 21.7 kB 0 B
build/edit-site/style-rtl.css 3.79 kB 0 B
build/edit-site/style.css 3.79 kB 0 B
build/edit-widgets/index.js 26.6 kB 0 B
build/edit-widgets/style-rtl.css 3.09 kB 0 B
build/edit-widgets/style.css 3.09 kB 0 B
build/editor/editor-styles-rtl.css 480 B 0 B
build/editor/editor-styles.css 482 B 0 B
build/editor/index.js 42.6 kB 0 B
build/editor/style-rtl.css 3.85 kB 0 B
build/editor/style.css 3.84 kB 0 B
build/element/index.js 4.45 kB 0 B
build/escape-html/index.js 733 B 0 B
build/format-library/index.js 7.49 kB 0 B
build/format-library/style-rtl.css 547 B 0 B
build/format-library/style.css 548 B 0 B
build/hooks/index.js 1.74 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.54 kB 0 B
build/is-shallow-equal/index.js 709 B 0 B
build/keyboard-shortcuts/index.js 2.39 kB 0 B
build/keycodes/index.js 1.85 kB 0 B
build/list-reusable-blocks/index.js 3.02 kB 0 B
build/list-reusable-blocks/style-rtl.css 476 B 0 B
build/list-reusable-blocks/style.css 476 B 0 B
build/media-utils/index.js 5.12 kB 0 B
build/notices/index.js 1.69 kB 0 B
build/nux/index.js 3.27 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/plugins/index.js 2.45 kB 0 B
build/primitives/index.js 1.35 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.85 kB 0 B
build/reusable-blocks/index.js 3.06 kB 0 B
build/rich-text/index.js 13 kB 0 B
build/server-side-render/index.js 2.61 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.24 kB 0 B
build/url/index.js 4.06 kB 0 B
build/viewport/index.js 1.75 kB 0 B
build/warning/index.js 1.13 kB 0 B
build/wordcount/index.js 1.23 kB 0 B

compressed-size-action

@jasmussen
Copy link
Contributor

Love it. Whether grid or flex or vanilla, just like how HTML and CSS handles it, blocks just like elements are laid out according to rules. Being able to surface some of those in a UI friendly and abstracted way, I believe, can provide some amazing layouts, and as you suggest, even refactor and simplifiy some of the structures currently in place. (CC: @shaunandrews because you were thinking about flex the other day)

This PR introduces a new prop/concept to inner blocks called layout and absorbs these assumptions into a "default" layout. The idea is that alternative layouts could be introduced to support different ways to layout the children blocks inside a container.

This feels like it could be the technical underpinning for the effort being explored in #16998, that ticket suggesting the layout controls being attached to a "Site" or "Area" block. Would you agree?

@youknowriad
Copy link
Contributor Author

This feels like it could be the technical underpinning for the effort being explored in #16998, that ticket suggesting the layout controls being attached to a "Site" or "Area" block. Would you agree?

Yes, for me any container whether it's the "site", a specific "area" or a random "group" block should be able to "change" the rules for its children. Surfacing these options on the UI is another question though, it could be a "block choice" (choose a group, a flex container or an area) or it could be an option/UI to change the layout per block... these are all things that could be possible here and that we'd have to explore.

};
} );
const layout = useLayout();
const supportsAlignments = layout.type === 'default';
Copy link
Contributor

@ntsekouras ntsekouras Oct 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to check the type === default and not check explicitly for alignments. I'm trying to understand your changes (haven't thoroughly yet :) )

In my head for now, I understand that we could have the new property layout filled with any property we would like and handle that new property per Block/use case.

For example if I would like to have a grid layout, should I add something like:

__experimentalLayout: { type: 'grid', ...other options }

or just

__experimentalLayout: { grid: {  columns: 3 } }

Am I missing the concept entirely?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly and other types of layouts might not have "alignments" support at all, so we bail out early for these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where your exactly goes :) That I'm missing the concept or is related in something for the above grid examples? :)

I still didn't understand if for checking alignment, we would need both type and another property alignments, or just one property alignments would be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alignments might not even exist in some layouts, the shape of the "layout" object depends on the type. Also, alignments on other layouts could have a completely different meaning. Basically the alignments as we know them today only make sense in the default layout, so we need to check the type first.

@jasmussen
Copy link
Contributor

#17275 could also benefit from this.

@youknowriad
Copy link
Contributor Author

So what do you think folks? Should we move forward with this experimental API and see how we can leverage it for all these use-cases?

@vcanales
Copy link
Member

So what do you think folks? Should we move forward with this experimental API and see how we can leverage it for all these use-cases?

I am very interested; I’ve been already toying with it a little bit. I can’t assess its reach fully yet, but I’d like to try at least to implement a grid layout with this.

@youknowriad
Copy link
Contributor Author

Ok, let's try this. @vcanales please do explore a grid layout with this and let me know how it goes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Type] Experimental Experimental feature or API. [Type] Technical Prototype Offers a technical exploration into an idea as an example of what's possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants