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

ToolsPanel: Use Grid component to handle layout #35621

Merged
merged 11 commits into from
Oct 29, 2021

Conversation

aaronrobertshaw
Copy link
Contributor

@aaronrobertshaw aaronrobertshaw commented Oct 14, 2021

Related:

Follow-up:

Description

This PR refactors the ToolsPanel to leverage the Grid component to handle its layout internally.

By adopting the Grid component to manage the ToolsPanel layout, the panel will be better positioned to expose any custom grid props we desire in future. It will also remove the reliance on the currently hard-coded single-column class name.

How has this been tested?

Manually.

  1. Ensured the layout and behaviour of the ToolsPanel in the storybook examples
  2. Ensured the ToolsPanel displays block support panels and controls correctly.
    • Typography panel will not apply single column span until styles are tweaked in a follow-up
  3. Adjusted various panels' and controls' props to play with custom column layouts.

Testing instructions

  1. Checkout this branch and fire up the storybook: npm run storybook:dev
  2. In the page that opens, select the ToolsPanel > Default example from the left sidebar
  3. Ensure the panel is laid out correctly and behaves
  4. Switch to the block editor, create a post, add a cover block and select it
  5. Ensure that the "Dimensions" panel in the inspector controls displays appropriately

Screenshots

Screen Shot 2021-10-25 at 3 17 27 pm

Types of changes

New feature.

The removal of the reliance on the single-column class is a breaking change although the component is still experimental and the only adoption of the ToolsPanel that has merged is the "Dimensions" panel that does not use single-column.

The Typography panel has now been switched to the ToolsPanel as well however that change hasn't been included in a release yet

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).

@aaronrobertshaw aaronrobertshaw added the [Feature] UI Components Impacts or related to the UI component system label Oct 14, 2021
@aaronrobertshaw aaronrobertshaw self-assigned this Oct 14, 2021
@github-actions
Copy link

github-actions bot commented Oct 14, 2021

Size Change: -3 B (0%)

Total Size: 1.07 MB

Filename Size Change
build/components/index.min.js 212 kB -3 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 931 B
build/admin-manifest/index.min.js 1.09 kB
build/annotations/index.min.js 2.7 kB
build/api-fetch/index.min.js 2.21 kB
build/autop/index.min.js 2.08 kB
build/blob/index.min.js 459 B
build/block-directory/index.min.js 6.2 kB
build/block-directory/style-rtl.css 1.01 kB
build/block-directory/style.css 1.01 kB
build/block-editor/default-editor-styles-rtl.css 378 B
build/block-editor/default-editor-styles.css 378 B
build/block-editor/index.min.js 135 kB
build/block-editor/style-rtl.css 13.9 kB
build/block-editor/style.css 13.9 kB
build/block-library/blocks/archives/editor-rtl.css 61 B
build/block-library/blocks/archives/editor.css 60 B
build/block-library/blocks/archives/style-rtl.css 65 B
build/block-library/blocks/archives/style.css 65 B
build/block-library/blocks/audio/editor-rtl.css 58 B
build/block-library/blocks/audio/editor.css 58 B
build/block-library/blocks/audio/style-rtl.css 111 B
build/block-library/blocks/audio/style.css 111 B
build/block-library/blocks/audio/theme-rtl.css 125 B
build/block-library/blocks/audio/theme.css 125 B
build/block-library/blocks/block/editor-rtl.css 161 B
build/block-library/blocks/block/editor.css 161 B
build/block-library/blocks/button/editor-rtl.css 470 B
build/block-library/blocks/button/editor.css 470 B
build/block-library/blocks/button/style-rtl.css 549 B
build/block-library/blocks/button/style.css 549 B
build/block-library/blocks/buttons/editor-rtl.css 309 B
build/block-library/blocks/buttons/editor.css 309 B
build/block-library/blocks/buttons/style-rtl.css 317 B
build/block-library/blocks/buttons/style.css 317 B
build/block-library/blocks/calendar/style-rtl.css 207 B
build/block-library/blocks/calendar/style.css 207 B
build/block-library/blocks/categories/editor-rtl.css 84 B
build/block-library/blocks/categories/editor.css 83 B
build/block-library/blocks/categories/style-rtl.css 79 B
build/block-library/blocks/categories/style.css 79 B
build/block-library/blocks/code/style-rtl.css 90 B
build/block-library/blocks/code/style.css 90 B
build/block-library/blocks/code/theme-rtl.css 131 B
build/block-library/blocks/code/theme.css 131 B
build/block-library/blocks/columns/editor-rtl.css 206 B
build/block-library/blocks/columns/editor.css 205 B
build/block-library/blocks/columns/style-rtl.css 497 B
build/block-library/blocks/columns/style.css 496 B
build/block-library/blocks/cover/editor-rtl.css 546 B
build/block-library/blocks/cover/editor.css 547 B
build/block-library/blocks/cover/style-rtl.css 1.17 kB
build/block-library/blocks/cover/style.css 1.17 kB
build/block-library/blocks/embed/editor-rtl.css 488 B
build/block-library/blocks/embed/editor.css 488 B
build/block-library/blocks/embed/style-rtl.css 417 B
build/block-library/blocks/embed/style.css 417 B
build/block-library/blocks/embed/theme-rtl.css 124 B
build/block-library/blocks/embed/theme.css 124 B
build/block-library/blocks/file/editor-rtl.css 300 B
build/block-library/blocks/file/editor.css 300 B
build/block-library/blocks/file/style-rtl.css 255 B
build/block-library/blocks/file/style.css 255 B
build/block-library/blocks/file/view.min.js 322 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB
build/block-library/blocks/freeform/editor.css 2.44 kB
build/block-library/blocks/gallery/editor-rtl.css 977 B
build/block-library/blocks/gallery/editor.css 982 B
build/block-library/blocks/gallery/style-rtl.css 1.6 kB
build/block-library/blocks/gallery/style.css 1.59 kB
build/block-library/blocks/gallery/theme-rtl.css 122 B
build/block-library/blocks/gallery/theme.css 122 B
build/block-library/blocks/group/editor-rtl.css 159 B
build/block-library/blocks/group/editor.css 159 B
build/block-library/blocks/group/style-rtl.css 57 B
build/block-library/blocks/group/style.css 57 B
build/block-library/blocks/group/theme-rtl.css 78 B
build/block-library/blocks/group/theme.css 78 B
build/block-library/blocks/heading/style-rtl.css 114 B
build/block-library/blocks/heading/style.css 114 B
build/block-library/blocks/home-link/style-rtl.css 247 B
build/block-library/blocks/home-link/style.css 247 B
build/block-library/blocks/html/editor-rtl.css 332 B
build/block-library/blocks/html/editor.css 333 B
build/block-library/blocks/image/editor-rtl.css 731 B
build/block-library/blocks/image/editor.css 730 B
build/block-library/blocks/image/style-rtl.css 502 B
build/block-library/blocks/image/style.css 505 B
build/block-library/blocks/image/theme-rtl.css 124 B
build/block-library/blocks/image/theme.css 124 B
build/block-library/blocks/latest-comments/style-rtl.css 284 B
build/block-library/blocks/latest-comments/style.css 284 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B
build/block-library/blocks/latest-posts/editor.css 137 B
build/block-library/blocks/latest-posts/style-rtl.css 528 B
build/block-library/blocks/latest-posts/style.css 527 B
build/block-library/blocks/list/style-rtl.css 94 B
build/block-library/blocks/list/style.css 94 B
build/block-library/blocks/media-text/editor-rtl.css 266 B
build/block-library/blocks/media-text/editor.css 263 B
build/block-library/blocks/media-text/style-rtl.css 493 B
build/block-library/blocks/media-text/style.css 490 B
build/block-library/blocks/more/editor-rtl.css 431 B
build/block-library/blocks/more/editor.css 431 B
build/block-library/blocks/navigation-link/editor-rtl.css 488 B
build/block-library/blocks/navigation-link/editor.css 489 B
build/block-library/blocks/navigation-link/style-rtl.css 94 B
build/block-library/blocks/navigation-link/style.css 94 B
build/block-library/blocks/navigation-submenu/editor-rtl.css 299 B
build/block-library/blocks/navigation-submenu/editor.css 299 B
build/block-library/blocks/navigation-submenu/style-rtl.css 195 B
build/block-library/blocks/navigation-submenu/style.css 195 B
build/block-library/blocks/navigation-submenu/view.min.js 343 B
build/block-library/blocks/navigation/editor-rtl.css 1.71 kB
build/block-library/blocks/navigation/editor.css 1.71 kB
build/block-library/blocks/navigation/style-rtl.css 1.7 kB
build/block-library/blocks/navigation/style.css 1.69 kB
build/block-library/blocks/navigation/view.min.js 2.74 kB
build/block-library/blocks/nextpage/editor-rtl.css 395 B
build/block-library/blocks/nextpage/editor.css 395 B
build/block-library/blocks/page-list/editor-rtl.css 377 B
build/block-library/blocks/page-list/editor.css 377 B
build/block-library/blocks/page-list/style-rtl.css 198 B
build/block-library/blocks/page-list/style.css 198 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B
build/block-library/blocks/paragraph/editor.css 157 B
build/block-library/blocks/paragraph/style-rtl.css 273 B
build/block-library/blocks/paragraph/style.css 273 B
build/block-library/blocks/post-author/style-rtl.css 175 B
build/block-library/blocks/post-author/style.css 176 B
build/block-library/blocks/post-comments-form/style-rtl.css 347 B
build/block-library/blocks/post-comments-form/style.css 347 B
build/block-library/blocks/post-comments/style-rtl.css 475 B
build/block-library/blocks/post-comments/style.css 475 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B
build/block-library/blocks/post-excerpt/editor.css 73 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B
build/block-library/blocks/post-excerpt/style.css 69 B
build/block-library/blocks/post-featured-image/editor-rtl.css 396 B
build/block-library/blocks/post-featured-image/editor.css 397 B
build/block-library/blocks/post-featured-image/style-rtl.css 156 B
build/block-library/blocks/post-featured-image/style.css 156 B
build/block-library/blocks/post-template/editor-rtl.css 99 B
build/block-library/blocks/post-template/editor.css 98 B
build/block-library/blocks/post-template/style-rtl.css 391 B
build/block-library/blocks/post-template/style.css 392 B
build/block-library/blocks/post-terms/style-rtl.css 73 B
build/block-library/blocks/post-terms/style.css 73 B
build/block-library/blocks/post-title/style-rtl.css 60 B
build/block-library/blocks/post-title/style.css 60 B
build/block-library/blocks/preformatted/style-rtl.css 103 B
build/block-library/blocks/preformatted/style.css 103 B
build/block-library/blocks/pullquote/editor-rtl.css 198 B
build/block-library/blocks/pullquote/editor.css 198 B
build/block-library/blocks/pullquote/style-rtl.css 378 B
build/block-library/blocks/pullquote/style.css 378 B
build/block-library/blocks/pullquote/theme-rtl.css 167 B
build/block-library/blocks/pullquote/theme.css 167 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B
build/block-library/blocks/query-pagination/editor-rtl.css 262 B
build/block-library/blocks/query-pagination/editor.css 255 B
build/block-library/blocks/query-pagination/style-rtl.css 234 B
build/block-library/blocks/query-pagination/style.css 231 B
build/block-library/blocks/query/editor-rtl.css 131 B
build/block-library/blocks/query/editor.css 132 B
build/block-library/blocks/quote/style-rtl.css 187 B
build/block-library/blocks/quote/style.css 187 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/rss/editor-rtl.css 202 B
build/block-library/blocks/rss/editor.css 204 B
build/block-library/blocks/rss/style-rtl.css 289 B
build/block-library/blocks/rss/style.css 288 B
build/block-library/blocks/search/editor-rtl.css 165 B
build/block-library/blocks/search/editor.css 165 B
build/block-library/blocks/search/style-rtl.css 397 B
build/block-library/blocks/search/style.css 398 B
build/block-library/blocks/search/theme-rtl.css 64 B
build/block-library/blocks/search/theme.css 64 B
build/block-library/blocks/separator/editor-rtl.css 99 B
build/block-library/blocks/separator/editor.css 99 B
build/block-library/blocks/separator/style-rtl.css 250 B
build/block-library/blocks/separator/style.css 250 B
build/block-library/blocks/separator/theme-rtl.css 172 B
build/block-library/blocks/separator/theme.css 172 B
build/block-library/blocks/shortcode/editor-rtl.css 474 B
build/block-library/blocks/shortcode/editor.css 474 B
build/block-library/blocks/site-logo/editor-rtl.css 770 B
build/block-library/blocks/site-logo/editor.css 770 B
build/block-library/blocks/site-logo/style-rtl.css 165 B
build/block-library/blocks/site-logo/style.css 165 B
build/block-library/blocks/site-tagline/editor-rtl.css 86 B
build/block-library/blocks/site-tagline/editor.css 86 B
build/block-library/blocks/site-title/editor-rtl.css 84 B
build/block-library/blocks/site-title/editor.css 84 B
build/block-library/blocks/social-link/editor-rtl.css 177 B
build/block-library/blocks/social-link/editor.css 177 B
build/block-library/blocks/social-links/editor-rtl.css 824 B
build/block-library/blocks/social-links/editor.css 823 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB
build/block-library/blocks/social-links/style.css 1.32 kB
build/block-library/blocks/spacer/editor-rtl.css 307 B
build/block-library/blocks/spacer/editor.css 307 B
build/block-library/blocks/spacer/style-rtl.css 48 B
build/block-library/blocks/spacer/style.css 48 B
build/block-library/blocks/table/editor-rtl.css 471 B
build/block-library/blocks/table/editor.css 472 B
build/block-library/blocks/table/style-rtl.css 481 B
build/block-library/blocks/table/style.css 481 B
build/block-library/blocks/table/theme-rtl.css 188 B
build/block-library/blocks/table/theme.css 188 B
build/block-library/blocks/tag-cloud/style-rtl.css 146 B
build/block-library/blocks/tag-cloud/style.css 146 B
build/block-library/blocks/template-part/editor-rtl.css 560 B
build/block-library/blocks/template-part/editor.css 559 B
build/block-library/blocks/template-part/theme-rtl.css 101 B
build/block-library/blocks/template-part/theme.css 101 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B
build/block-library/blocks/text-columns/editor.css 95 B
build/block-library/blocks/text-columns/style-rtl.css 166 B
build/block-library/blocks/text-columns/style.css 166 B
build/block-library/blocks/verse/style-rtl.css 87 B
build/block-library/blocks/verse/style.css 87 B
build/block-library/blocks/video/editor-rtl.css 571 B
build/block-library/blocks/video/editor.css 572 B
build/block-library/blocks/video/style-rtl.css 173 B
build/block-library/blocks/video/style.css 173 B
build/block-library/blocks/video/theme-rtl.css 124 B
build/block-library/blocks/video/theme.css 124 B
build/block-library/common-rtl.css 815 B
build/block-library/common.css 812 B
build/block-library/editor-rtl.css 9.62 kB
build/block-library/editor.css 9.62 kB
build/block-library/index.min.js 149 kB
build/block-library/reset-rtl.css 474 B
build/block-library/reset.css 474 B
build/block-library/style-rtl.css 10.5 kB
build/block-library/style.css 10.5 kB
build/block-library/theme-rtl.css 668 B
build/block-library/theme.css 673 B
build/block-serialization-default-parser/index.min.js 1.09 kB
build/block-serialization-spec-parser/index.min.js 2.79 kB
build/blocks/index.min.js 46 kB
build/components/style-rtl.css 15.3 kB
build/components/style.css 15.3 kB
build/compose/index.min.js 10.4 kB
build/core-data/index.min.js 12.4 kB
build/customize-widgets/index.min.js 11.2 kB
build/customize-widgets/style-rtl.css 1.5 kB
build/customize-widgets/style.css 1.49 kB
build/data-controls/index.min.js 614 B
build/data/index.min.js 7.1 kB
build/date/index.min.js 31.5 kB
build/deprecated/index.min.js 428 B
build/dom-ready/index.min.js 304 B
build/dom/index.min.js 4.44 kB
build/edit-navigation/index.min.js 15.8 kB
build/edit-navigation/style-rtl.css 3.76 kB
build/edit-navigation/style.css 3.76 kB
build/edit-post/classic-rtl.css 492 B
build/edit-post/classic.css 494 B
build/edit-post/index.min.js 29.4 kB
build/edit-post/style-rtl.css 7.12 kB
build/edit-post/style.css 7.12 kB
build/edit-site/index.min.js 30.7 kB
build/edit-site/style-rtl.css 5.71 kB
build/edit-site/style.css 5.71 kB
build/edit-widgets/index.min.js 16.3 kB
build/edit-widgets/style-rtl.css 4.17 kB
build/edit-widgets/style.css 4.18 kB
build/editor/index.min.js 37.6 kB
build/editor/style-rtl.css 3.78 kB
build/editor/style.css 3.77 kB
build/element/index.min.js 3.21 kB
build/escape-html/index.min.js 517 B
build/format-library/index.min.js 5.99 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.55 kB
build/html-entities/index.min.js 424 B
build/i18n/index.min.js 3.6 kB
build/is-shallow-equal/index.min.js 501 B
build/keyboard-shortcuts/index.min.js 1.72 kB
build/keycodes/index.min.js 1.3 kB
build/list-reusable-blocks/index.min.js 1.85 kB
build/list-reusable-blocks/style-rtl.css 838 B
build/list-reusable-blocks/style.css 838 B
build/media-utils/index.min.js 2.92 kB
build/notices/index.min.js 845 B
build/nux/index.min.js 2.03 kB
build/nux/style-rtl.css 747 B
build/nux/style.css 743 B
build/plugins/index.min.js 1.83 kB
build/primitives/index.min.js 921 B
build/priority-queue/index.min.js 582 B
build/react-i18n/index.min.js 671 B
build/redux-routine/index.min.js 2.63 kB
build/reusable-blocks/index.min.js 2.19 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 10.7 kB
build/server-side-render/index.min.js 1.52 kB
build/shortcode/index.min.js 1.48 kB
build/token-list/index.min.js 562 B
build/url/index.min.js 1.74 kB
build/viewport/index.min.js 1.02 kB
build/warning/index.min.js 248 B
build/widgets/index.min.js 7.11 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.04 kB

compressed-size-action

@diegohaz diegohaz self-requested a review October 14, 2021 15:03
Copy link
Contributor

@andrewserong andrewserong left a comment

Choose a reason for hiding this comment

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

Nice work, @aaronrobertshaw, this looks great in the Storybook demo, I think this is going to allow for some really nice layouts. It's quite fun to interact with:

Kapture 2021-10-15 at 12 07 08

I like the addition of being able to set columns at the ToolsPanel level. While I imagine we won't be refactoring away from Grid, I was wondering if using gridColumn at the ToolsPanelItem level ties the prop closely to the specific implementation? I could imagine a plugin author going to add a ToolsPanelItem to an existing panel and not being sure what value to put into the gridColumn string. Would an integer based columnSpan prop be clearer as an API? Also, if we ever needed to refactor to flex, the integer value could be used to calculate flex-basis without the ToolsPanelItem needing to change its value.

Of course, on the other hand, the gridColumn prop passing the value directly to the CSS does give the ToolsPanelItem more control if someone wanted to set a different grid-column-start / grid-column-end value than just spanning, so keeping it as is could offer more flexibility.

Curious to hear what you and other folks think, but this is testing nicely for me in Storybook and in existing ToolsPanels in the editor 👍

@aaronrobertshaw
Copy link
Contributor Author

Thanks for taking this for a test drive 👍

Of course, on the other hand, the gridColumn prop passing the value directly to the CSS does give the ToolsPanelItem more control if someone wanted to set a different grid-column-start / grid-column-end value than just spanning, so keeping it as is could offer more flexibility.

This is why I went with the current approach. More power and flexibility for free and it aligns more directly with an external spec i.e. CSS.

and not being sure what value to put into the gridColumn string

I mentioned the direct mapping to the CSS property in the README so it should be clear. I originally had a link to external CSS specs but couldn't find many other cases of doing that so removed it.

Would an integer based columnSpan prop be clearer as an API? Also, if we ever needed to refactor to flex, the integer value could be used to calculate flex-basis without the ToolsPanelItem needing to change its value.

I did consider it however it seemed to be unnecessarily restrictive when we could get the positioning functionality for free otherwise. If we needed to refactor to flex columnSpan would no longer make sense either as a name.

@andrewserong
Copy link
Contributor

I did consider it however it seemed to be unnecessarily restrictive when we could get the positioning functionality for free otherwise

Thanks for explaining the rationale! Agreed, since it offers better flexibility and matches the CSS spec, that sounds like a good way to go. And it avoids adding an extra abstraction with the columnSpan idea that didn’t really map to the right CSS property anyway 👍

Base automatically changed from remove/toolspanel-hardcoded-classnames to trunk October 15, 2021 05:51
@ciampo ciampo requested a review from mirka October 15, 2021 14:52
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

Thank you for continuing to improve the ToolsPanel component — the new grid layout looks great!

packages/components/src/tools-panel/styles.ts Show resolved Hide resolved
packages/components/src/tools-panel/types.ts Outdated Show resolved Hide resolved
packages/components/src/tools-panel/types.ts Outdated Show resolved Hide resolved
Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

I'm wondering what happens in cases like this, where you have an implicit group of optional panel items that belong in their own row. For example width/height/depth and padding/margin. The "wrap" behavior ("auto-placement"? unsure what the correct term is!) is not what you want:

CleanShot.2021-10-16.at.01.46.10.mp4

Setting explicit grid-column-start values will make it better, but then it doesn't auto-place within the row:

CleanShot.2021-10-16.at.02.26.36.mp4

I'm probably missing context on how ToolsPanel is intended to be used, but I was actually imagining the consumer being responsible for doing the layout (Grid or otherwise) inside ToolsPanel.

<ToolsPanel>
  <Grid columns={2} gap={2}>
    <ToolsPanelItem />
    <ToolsPanelItem />
  </Grid>
  <Grid columns={3} gap={2}>
    <ToolsPanelItem />
    <ToolsPanelItem />
    <ToolsPanelItem />
  </Grid>
</ToolsPanel>

One could also say that an implicit group (like width/height/depth) should be encapsulated inside a single ToolsPanelItem. In that case, it might be that an elaborate gridColumn system built into ToolsPanel is a bit overkill, because there is a limit to the amount of random auto-placement you want to occur on unrelated optional items that are not full-width.

Just a non-blocking observation, please disregard if it doesn't matter 🙂

@aaronrobertshaw
Copy link
Contributor Author

Thanks for the feedback @mirka 👍

I'll explore the suggestion further and see what I can come up with.

I'm wondering what happens in cases like this, where you have an implicit group of optional panel items that belong in their own row. For example width/height/depth and padding/margin. The "wrap" behavior ("auto-placement"? unsure what the correct term is!) is not what you want:

I believe the idea was for all the controls within a ToolsPanel to be related in a way that such implicit groups wouldn't really be needed. In your example, this would be the separation of the dimensions vs spacing controls into separate panels. This has been a topic of discussion already although I'm not sure if we've settled on anything concrete yet.

Perhaps @jasmussen might have some insight as to what the ToolsPanel really needs to achieve in terms of layout in the bigger picture?

I'm probably missing context on how ToolsPanel is intended to be used, but I was actually imagining the consumer being responsible for doing the layout (Grid or otherwise) inside ToolsPanel.

At a glance, this would provide more flexibility though I'm not sure how it would play when SlotFills are used to allow injection of controls into the panel. We'd likely be back to adding a generic grid wrapping all those fills and this same limitation/issue. This is something I'll need to dig into a little deeper.

One could also say that an implicit group (like width/height/depth) should be encapsulated inside a single ToolsPanelItem.

I'm not sure I agree with this. These individual items need to be represented within, display controlled, or value reset, by the tools panel menu.

The current approach in the ToolsPanel allows an individual ToolsPanelItem to register itself with the panel via the ToolsPanelContext. This does allow items to be wrapped in other components etc. As a result, the current functionality might already be close to supporting the approach within your snippet.

If it turns out to be more involved, given this was non-blocking as you mentioned, a follow-up PR refining this layout could be an option.

@jasmussen
Copy link
Contributor

The neat arrangement of controls in the inspector, as more are added or removed, is definitely a tricky one, and important one to get right. In many ways, that's a key part of addressing #27331: ensuring a system where controls that get shown or hidden as part of theme.json or global styles or users, stil arranges itself in a neat way, and can appear consistent across inspectors.

Ultimately I'm not personally sure how far we can go with regards to controls resizing and adjusting themselves depending on context, I'll need to defer to you all (and CC: @ciampo as well).

But just as a baseline, I imagine controls registering themselves as half or full-size controls, possibly with an option for 3rds as well, and then as one half-size item gets hidden, it will make room for a subsequent half-size item to take its place:
Frame 862

It doesn't seem like it will be necessary for a full size control to be able to shift between full-size and half-size automatically, but it's an optimization that could be looked at if/when it becomes necessary.

@aaronrobertshaw
Copy link
Contributor Author

Thanks for sharing that @jasmussen 👍

But just as a baseline, I imagine controls registering themselves as half or full-size controls, possibly with an option for 3rds as well, and then as one half-size item gets hidden, it will make room for a subsequent half-size item to take its place:

This sounds to me like the current behaviour. The ToolsPanel was built to satisfy the mockups in #27331.

I think the question Lena is asking is whether that next subsequent half-size item should in fact take its place in some situations.


This does allow items to be wrapped in other components etc. As a result, the current functionality might already be close to supporting the approach within your snippet.

After a little testing, I believe we can achieve the "implicit group layout" raised earlier with only a small tweak to the styles to hide an empty grid. The items in the group would be wrapped in a Grid similar to the suggested markup.

Screen.Recording.2021-10-18.at.5.48.43.pm.mp4
Here's a diff for the style tweak and storybook example changes demo'd in the above video.
diff --git a/packages/components/src/tools-panel/stories/index.js b/packages/components/src/tools-panel/stories/index.js
index e9a39b2932..e5b7d9b73e 100644
--- a/packages/components/src/tools-panel/stories/index.js
+++ b/packages/components/src/tools-panel/stories/index.js
@@ -15,6 +15,7 @@ import { ToolsPanel, ToolsPanelItem } from '../';
 import Panel from '../../panel';
 import UnitControl from '../../unit-control';
 import { createSlotFill, Provider as SlotFillProvider } from '../../slot-fill';
+import { Grid } from '../../grid';
 
 export default {
 	title: 'Components (Experimental)/ToolsPanel',
@@ -258,45 +259,49 @@ export const WithCustomColumns = () => {
 							onChange={ ( next ) => setSize( next ) }
 						/>
 					</ToolsPanelItem>
-					<ToolsPanelItem
-						gridColumn="span 1"
-						hasValue={ () => !! width }
-						label="Width"
-						onDeselect={ () => setWidth( undefined ) }
-						isShownByDefault={ true }
+					<Grid
+						style={ { gridColumn: '1/-1' } }
+						columns={ 3 }
+						columnGap={ 16 }
+						rowGap={ 24 }
 					>
-						<UnitControl
+						<ToolsPanelItem
+							gridColumn="span 1"
+							hasValue={ () => !! width }
 							label="Width"
-							value={ width }
-							onChange={ ( next ) => setWidth( next ) }
-						/>
-					</ToolsPanelItem>
-					<ToolsPanelItem
-						gridColumn="span 1"
-						hasValue={ () => !! height }
-						label="Height"
-						onDeselect={ () => setHeight( undefined ) }
-						isShownByDefault={ true }
-					>
-						<UnitControl
+							onDeselect={ () => setWidth( undefined ) }
+						>
+							<UnitControl
+								label="Width"
+								value={ width }
+								onChange={ ( next ) => setWidth( next ) }
+							/>
+						</ToolsPanelItem>
+						<ToolsPanelItem
+							gridColumn="span 1"
+							hasValue={ () => !! height }
 							label="Height"
-							value={ height }
-							onChange={ ( next ) => setHeight( next ) }
-						/>
-					</ToolsPanelItem>
-					<ToolsPanelItem
-						gridColumn="span 1"
-						hasValue={ () => !! depth }
-						label="Depth"
-						onDeselect={ () => setDepth( undefined ) }
-						isShownByDefault={ true }
-					>
-						<UnitControl
+							onDeselect={ () => setHeight( undefined ) }
+						>
+							<UnitControl
+								label="Height"
+								value={ height }
+								onChange={ ( next ) => setHeight( next ) }
+							/>
+						</ToolsPanelItem>
+						<ToolsPanelItem
+							gridColumn="span 1"
+							hasValue={ () => !! depth }
 							label="Depth"
-							value={ depth }
-							onChange={ ( next ) => setDepth( next ) }
-						/>
-					</ToolsPanelItem>
+							onDeselect={ () => setDepth( undefined ) }
+						>
+							<UnitControl
+								label="Depth"
+								value={ depth }
+								onChange={ ( next ) => setDepth( next ) }
+							/>
+						</ToolsPanelItem>
+					</Grid>
 					<ToolsPanelItem
 						gridColumn="span 2"
 						hasValue={ () => !! padding }
diff --git a/packages/components/src/tools-panel/styles.ts b/packages/components/src/tools-panel/styles.ts
index d9aa409abd..405a621510 100644
--- a/packages/components/src/tools-panel/styles.ts
+++ b/packages/components/src/tools-panel/styles.ts
@@ -31,6 +31,10 @@ export const ToolsPanel = css`
 	border-top: ${ CONFIG.borderWidth } solid ${ COLORS.gray[ 200 ] };
 	margin-top: -1px;
 	padding: ${ space( 4 ) };
+
+	> div:empty {
+		display: none;
+	}
 `;
 
 /**

If this satisfies both giving consumers the ability to group controls while still allowing a default layout to be applied by the ToolsPanel thereby reducing friction from a devx perspective I think we could move forward with this approach without any drastic changes.

I'm open to other ideas or thoughts in case I've missed something.

@jasmussen
Copy link
Contributor

I think the question Lena is asking is whether that next subsequent half-size item should in fact take its place in some situations.

Yes, I'm missing some nuance. For example, I'm not sure we should introduce thirds yet — it's possible it might be necessary in the future, but it doesn't seem like something to optimize for, especially yet. If we can accomplish the designs in #34574, that feels like it will put us in a good place.

But more specifically, I don't know that we'll need to optimize for a design like this:

Especially for the tools panel, we'll curate the sequence of panels to always be in the same sequence. For example, full-width controls will almost always be at the top, with half size controls below that. So you shouldn't encounter a situation where you remove a half-size item, and a full size item can't take it's place.

So to rephrase it a bit: the panels need smarts so that when items are hidden or added, controls reorient themselves. However we'll nearly always want to curate the sequence of items.

@ciampo
Copy link
Contributor

ciampo commented Oct 18, 2021

Sorry for being a bit late to the conversation! I haven't really got the the time to review the code patches in depth, and from tomorrow I won't be able to provide feedback on GitHub reliably until November 8.

Having said that, I believe that a good compromise and a safer approach would be to keep things simple for now — we can always add more complex layout behaviours later. In contrast, adding stuff now that we may need to remove later on will be more disruptive. The approach that I propose for the changes in this PR is:

  • refactor the component to use Grid internally, and keep the current 2 columns layout implementation
  • remove the single-column hardcoded className
  • Do not add any new prop on ItemGroup — for now, we may agree that, by default, each ToolsPanelItem occupies 1 columns in the layout. If that needs to be changed, the user of ToolsPanelItem may want to apply CSS grid styles externally via className (e.g. by adding grid-column: 1 / -1 for full-width)

This solution buys us some time to discuss around a few questions that come to mind, which may need further time and exploration before reaching an agreement:

  • How many columns should the ToolsPanel layout have? (e.g 2, 3...) Should the number of columns be exposed as a prop? Should it changed based on the width of the component (e.g. using container queries)?
  • Should we add additional props to ToolsPanelItem (e.g. gridColumn)? Should these props be a 1:1 with the CSS properties?
  • How do we handle the potential auto-placing algorithm of CSS grid when hiding / showing elements?

What do folks think? (Also note, as said earlier, that I may not be able to follow up to this comment in the next days, until November 8)

@mirka
Copy link
Member

mirka commented Oct 18, 2021

If this satisfies both giving consumers the ability to group controls while still allowing a default layout to be applied by the ToolsPanel thereby reducing friction from a devx perspective I think we could move forward with this approach without any drastic changes.

@aaronrobertshaw Nice, this addresses my concern perfectly, and it looks hopeful that we can have the flexibility while providing a default layout!

That said, Marco's plan of not exposing new props in this PR is probably wise. It warrants some more exploration/discussion, and I'm still doubtful that we need to expose unrealistic (>2 columns) or "implementation detail" (gridColumn) options as part of ToolsPanel.

@aaronrobertshaw
Copy link
Contributor Author

  • refactor the component to use Grid internally, and keep the current 2 columns layout implementation
  • remove the single-column hardcoded className
  • Do not add any new prop on ItemGroup — for now, we may agree that, by default, each ToolsPanelItem occupies 1 columns in the layout. If that needs to be changed, the user of ToolsPanelItem may want to apply CSS grid styles externally via className (e.g. by adding grid-column: 1 / -1 for full-width)

This PR has been updated to address the majority of @ciampo's proposal. The main difference is that items still default to spanning the full width. This is by far the most common use case for the ToolsPanel to date and I believe requires consumers to make the least amount of custom styling changes.

Action Taken

  • Removed the columns prop from ToolsPanel
  • Prevented blindly passing props through to the Grid component used as the root element for the panel
    • This was to avoid introducing extra markup and styling changes if moving the grid to an inner component
  • Removed gridColumn prop from the ToolsPanelItem. Handling grid column styling is now up to consumers
  • Kept the ToolsPanel defaulting to 2 columns
  • Kept ToolsPanelItems defaulting to spanning all columns
  • Removed the custom columns example from the storybook
  • Updated other storybook examples to handle single column span styles
  • Updated types according to the above changes
  • Updated docs

Summary

After making the above changes:

  • ToolsPanel is behaving as expected for me in the storybook
  • Unit tests are all green
  • Type checking passes
  • ToolsPanel works for block supports in the inspector controls
  • SlotFill provided items are still rendering correctly within their inner wrapper

I do think all this begs the question though as to whether this PR should be put on ice until the required discussions are had and a decision on behaviour made. As it is now, we're switching to the grid component to handle layout but not really allowing it to do any of that.

Given this makes very little in the way of user-facing or consumer-orientated changes, would it be better to leave the status quo so this is iterated on once properly?

@aaronrobertshaw
Copy link
Contributor Author

Having had some time to reflect, I think it would be best to land this so that the reliance on the ToolsPanel providing the single-column class is removed.

The recent switch of the Typography block supports panel to use the ToolsPanel relies on some controls only spanning a single column. I'll create a follow up to this PR that will re-establish the desired layout in the Typography panel.

Copy link
Member

@mirka mirka left a comment

Choose a reason for hiding this comment

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

Having had some time to reflect, I think it would be best to land this so that the reliance on the ToolsPanel providing the single-column class is removed.

Sounds good, and thanks for the solid improvements and exploration here 👍

Let's also add a brief entry under the "Experimental" section in the changelog.

Comment on lines 234 to 236
.single-column {
grid-column: span 1;
}
Copy link
Member

Choose a reason for hiding this comment

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

Not super important since our columns API is still in flux, but since story code serve as examples it might be nicer to have a styled( ToolsPanelItem ) rather than use an explicit class name here. (Non-blocking nit)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion @mirka and your time reviewing this PR.

I've just pushed a commit switching to a styled component for the stories as well as a changelog.

If you're still happy with the changes, I can merge this after the e2es pass.

Copy link
Member

Choose a reason for hiding this comment

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

Let's do it! 🚢

@aaronrobertshaw
Copy link
Contributor Author

A follow-up to fix the Typography panel layout and letter-spacing control after this PR lands can be found in #35911. It would be best to land these as close together as possible.

@stacimc stacimc mentioned this pull request Oct 25, 2021
7 tasks
@aaronrobertshaw aaronrobertshaw merged commit 30ec8c2 into trunk Oct 29, 2021
@aaronrobertshaw aaronrobertshaw deleted the refactor/toolspanel-to-use-grid branch October 29, 2021 04:00
@github-actions github-actions bot added this to the Gutenberg 11.9 milestone Oct 29, 2021
@andrewserong andrewserong added the [Type] Code Quality Issues or PRs that relate to code quality label Nov 5, 2021
Copy link
Contributor

@ciampo ciampo left a comment

Choose a reason for hiding this comment

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

A bit late to the party, but — first of all, kudos to everyone for shipping this PR! It's great to see us moving away from the single-column className.

Regarding the next steps, I think that we may be able to make a better decision after getting a bit more experience in using ToolsPanel in more place sin Gutenberg — what do folks think?

I also left a couple of minor comments, possibly requiring a small follow-up PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] UI Components Impacts or related to the UI component system [Type] Code Quality Issues or PRs that relate to code quality
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants