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

[Components]: Add ToggleGroupControlOptionIcon component #39760

Merged
merged 8 commits into from
Mar 31, 2022

Conversation

ntsekouras
Copy link
Contributor

What?

Part of: #36230
Needed for: #36735

This PR adds icon support to ToggleGroupControlOption component (child of ToggleGroupControl).

Why?

This will be needed for implementing other controls like textTransform or textDecoration to use ToggleGroupControl.

How?

This implementation makes the use of icon and label mutually exclusive. What this means is that if we provide an icon it will be used instead of the label and a tooltip will be shown automatically.

Testing Instructions

  1. Check the storybook examples of the component.

Notes

I've noticed that in storybook the options are not set properly when we switch to different stories. It's not related to this PR and it should be handled separately.

Screen.Recording.2022-03-25.at.2.36.20.PM.mov

Screenshots or screencast

Screen.Recording.2022-03-25.at.2.22.27.PM.mov

@ntsekouras ntsekouras added [Type] Enhancement A suggestion for improvement. [Package] Components /packages/components labels Mar 25, 2022
@ntsekouras ntsekouras requested review from mirka, ciampo and ramonjd March 25, 2022 12:38
@ntsekouras ntsekouras requested a review from ajitbohra as a code owner March 25, 2022 12:38
@ntsekouras ntsekouras self-assigned this Mar 25, 2022
@ntsekouras ntsekouras changed the title [Components - ToggleGroupControl]: Add icons support [Components - ToggleGroupControlOption]: Add icons support Mar 25, 2022
* Icon for the option. If `icon` is provided it will be used instead of the `label`
* and will show a tooltip automatically.
*/
icon?: JSX.Element;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure about the best type here... --cc @ciampo

Copy link
Member

Choose a reason for hiding this comment

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

JSX.Element is the type I get back from the compiler for components in icons/src/library/*

Screen Shot 2022-03-28 at 11 54 23 am

Copy link
Member

@ramonjd ramonjd left a comment

Choose a reason for hiding this comment

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

This LGTM, but I'd defer to @mirka or @ciampo for their opinions.

I thought an update to the storybook npm packages might fix the args not updating on the canvas, but it didn't for me. Possibly related issue: storybookjs/storybook#16174

* Icon for the option. If `icon` is provided it will be used instead of the `label`
* and will show a tooltip automatically.
*/
icon?: JSX.Element;
Copy link
Member

Choose a reason for hiding this comment

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

JSX.Element is the type I get back from the compiler for components in icons/src/library/*

Screen Shot 2022-03-28 at 11 54 23 am

@ntsekouras ntsekouras force-pushed the add/icon-support-toggle-group-control-option branch from 5058932 to d89572e Compare March 28, 2022 10:25
@github-actions
Copy link

github-actions bot commented Mar 28, 2022

Size Change: +66 B (0%)

Total Size: 1.22 MB

Filename Size Change
build/components/index.min.js 223 kB +66 B (0%)
ℹ️ View Unchanged
Filename Size
build/a11y/index.min.js 993 B
build/admin-manifest/index.min.js 1.24 kB
build/annotations/index.min.js 2.77 kB
build/api-fetch/index.min.js 2.27 kB
build/autop/index.min.js 2.15 kB
build/blob/index.min.js 487 B
build/block-directory/index.min.js 6.49 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 148 kB
build/block-editor/style-rtl.css 15.4 kB
build/block-editor/style.css 15.4 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 150 B
build/block-library/blocks/audio/editor.css 150 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/avatar/editor-rtl.css 116 B
build/block-library/blocks/avatar/editor.css 116 B
build/block-library/blocks/avatar/style-rtl.css 59 B
build/block-library/blocks/avatar/style.css 59 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 445 B
build/block-library/blocks/button/editor.css 445 B
build/block-library/blocks/button/style-rtl.css 560 B
build/block-library/blocks/button/style.css 560 B
build/block-library/blocks/buttons/editor-rtl.css 292 B
build/block-library/blocks/buttons/editor.css 292 B
build/block-library/blocks/buttons/style-rtl.css 275 B
build/block-library/blocks/buttons/style.css 275 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 103 B
build/block-library/blocks/code/style.css 103 B
build/block-library/blocks/code/theme-rtl.css 124 B
build/block-library/blocks/code/theme.css 124 B
build/block-library/blocks/columns/editor-rtl.css 108 B
build/block-library/blocks/columns/editor.css 108 B
build/block-library/blocks/columns/style-rtl.css 406 B
build/block-library/blocks/columns/style.css 406 B
build/block-library/blocks/comment-author-avatar/editor-rtl.css 125 B
build/block-library/blocks/comment-author-avatar/editor.css 125 B
build/block-library/blocks/comment-template/style-rtl.css 127 B
build/block-library/blocks/comment-template/style.css 127 B
build/block-library/blocks/comments-pagination-numbers/editor-rtl.css 123 B
build/block-library/blocks/comments-pagination-numbers/editor.css 121 B
build/block-library/blocks/comments-pagination/editor-rtl.css 222 B
build/block-library/blocks/comments-pagination/editor.css 209 B
build/block-library/blocks/comments-pagination/style-rtl.css 235 B
build/block-library/blocks/comments-pagination/style.css 231 B
build/block-library/blocks/comments-query-loop/editor-rtl.css 95 B
build/block-library/blocks/comments-query-loop/editor.css 95 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.56 kB
build/block-library/blocks/cover/style.css 1.56 kB
build/block-library/blocks/embed/editor-rtl.css 293 B
build/block-library/blocks/embed/editor.css 293 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 353 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 961 B
build/block-library/blocks/gallery/editor.css 964 B
build/block-library/blocks/gallery/style-rtl.css 1.51 kB
build/block-library/blocks/gallery/style.css 1.51 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 76 B
build/block-library/blocks/heading/style.css 76 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 529 B
build/block-library/blocks/image/style.css 535 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 199 B
build/block-library/blocks/latest-posts/editor.css 198 B
build/block-library/blocks/latest-posts/style-rtl.css 447 B
build/block-library/blocks/latest-posts/style.css 446 B
build/block-library/blocks/list/style-rtl.css 88 B
build/block-library/blocks/list/style.css 88 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 708 B
build/block-library/blocks/navigation-link/editor.css 706 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/view.min.js 375 B
build/block-library/blocks/navigation/editor-rtl.css 2.03 kB
build/block-library/blocks/navigation/editor.css 2.04 kB
build/block-library/blocks/navigation/style-rtl.css 1.93 kB
build/block-library/blocks/navigation/style.css 1.92 kB
build/block-library/blocks/navigation/view.min.js 2.85 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 363 B
build/block-library/blocks/page-list/editor.css 363 B
build/block-library/blocks/page-list/style-rtl.css 175 B
build/block-library/blocks/page-list/style.css 175 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 260 B
build/block-library/blocks/paragraph/style.css 260 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 446 B
build/block-library/blocks/post-comments-form/style.css 446 B
build/block-library/blocks/post-comments/style-rtl.css 521 B
build/block-library/blocks/post-comments/style.css 521 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 721 B
build/block-library/blocks/post-featured-image/editor.css 721 B
build/block-library/blocks/post-featured-image/style-rtl.css 153 B
build/block-library/blocks/post-featured-image/style.css 153 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 323 B
build/block-library/blocks/post-template/style.css 323 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 80 B
build/block-library/blocks/post-title/style.css 80 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 370 B
build/block-library/blocks/pullquote/style.css 370 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 221 B
build/block-library/blocks/query-pagination/editor.css 211 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 201 B
build/block-library/blocks/quote/style.css 201 B
build/block-library/blocks/quote/theme-rtl.css 223 B
build/block-library/blocks/quote/theme.css 226 B
build/block-library/blocks/read-more/style-rtl.css 132 B
build/block-library/blocks/read-more/style.css 132 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 140 B
build/block-library/blocks/separator/editor.css 140 B
build/block-library/blocks/separator/style-rtl.css 233 B
build/block-library/blocks/separator/style.css 233 B
build/block-library/blocks/separator/theme-rtl.css 194 B
build/block-library/blocks/separator/theme.css 194 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 759 B
build/block-library/blocks/site-logo/editor.css 759 B
build/block-library/blocks/site-logo/style-rtl.css 181 B
build/block-library/blocks/site-logo/style.css 181 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 674 B
build/block-library/blocks/social-links/editor.css 673 B
build/block-library/blocks/social-links/style-rtl.css 1.37 kB
build/block-library/blocks/social-links/style.css 1.36 kB
build/block-library/blocks/spacer/editor-rtl.css 332 B
build/block-library/blocks/spacer/editor.css 332 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 226 B
build/block-library/blocks/tag-cloud/style.css 227 B
build/block-library/blocks/template-part/editor-rtl.css 149 B
build/block-library/blocks/template-part/editor.css 149 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 934 B
build/block-library/common.css 932 B
build/block-library/editor-rtl.css 9.96 kB
build/block-library/editor.css 9.96 kB
build/block-library/index.min.js 173 kB
build/block-library/reset-rtl.css 478 B
build/block-library/reset.css 478 B
build/block-library/style-rtl.css 11.3 kB
build/block-library/style.css 11.3 kB
build/block-library/theme-rtl.css 689 B
build/block-library/theme.css 694 B
build/block-serialization-default-parser/index.min.js 1.12 kB
build/block-serialization-spec-parser/index.min.js 2.83 kB
build/blocks/index.min.js 46.8 kB
build/components/style-rtl.css 14.9 kB
build/components/style.css 14.9 kB
build/compose/index.min.js 11.2 kB
build/core-data/index.min.js 14.5 kB
build/customize-widgets/index.min.js 11 kB
build/customize-widgets/style-rtl.css 1.39 kB
build/customize-widgets/style.css 1.39 kB
build/data-controls/index.min.js 663 B
build/data/index.min.js 8.61 kB
build/date/index.min.js 32 kB
build/deprecated/index.min.js 518 B
build/dom-ready/index.min.js 336 B
build/dom/index.min.js 4.58 kB
build/edit-navigation/index.min.js 15.8 kB
build/edit-navigation/style-rtl.css 4.04 kB
build/edit-navigation/style.css 4.05 kB
build/edit-post/classic-rtl.css 546 B
build/edit-post/classic.css 547 B
build/edit-post/index.min.js 29.6 kB
build/edit-post/style-rtl.css 7.07 kB
build/edit-post/style.css 7.07 kB
build/edit-site/index.min.js 46.6 kB
build/edit-site/style-rtl.css 7.74 kB
build/edit-site/style.css 7.71 kB
build/edit-widgets/index.min.js 16.3 kB
build/edit-widgets/style-rtl.css 4.4 kB
build/edit-widgets/style.css 4.39 kB
build/editor/index.min.js 38.4 kB
build/editor/style-rtl.css 3.71 kB
build/editor/style.css 3.71 kB
build/element/index.min.js 4.29 kB
build/escape-html/index.min.js 548 B
build/format-library/index.min.js 6.62 kB
build/format-library/style-rtl.css 571 B
build/format-library/style.css 571 B
build/hooks/index.min.js 1.66 kB
build/html-entities/index.min.js 454 B
build/i18n/index.min.js 3.79 kB
build/is-shallow-equal/index.min.js 535 B
build/keyboard-shortcuts/index.min.js 1.83 kB
build/keycodes/index.min.js 1.41 kB
build/list-reusable-blocks/index.min.js 1.75 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.94 kB
build/notices/index.min.js 957 B
build/nux/index.min.js 2.12 kB
build/nux/style-rtl.css 751 B
build/nux/style.css 749 B
build/plugins/index.min.js 1.98 kB
build/preferences/index.min.js 1.2 kB
build/primitives/index.min.js 949 B
build/priority-queue/index.min.js 611 B
build/react-i18n/index.min.js 704 B
build/react-refresh-entry/index.min.js 8.44 kB
build/react-refresh-runtime/index.min.js 7.31 kB
build/redux-routine/index.min.js 2.69 kB
build/reusable-blocks/index.min.js 2.24 kB
build/reusable-blocks/style-rtl.css 256 B
build/reusable-blocks/style.css 256 B
build/rich-text/index.min.js 11.2 kB
build/server-side-render/index.min.js 1.61 kB
build/shortcode/index.min.js 1.52 kB
build/token-list/index.min.js 668 B
build/url/index.min.js 1.99 kB
build/vendors/react-dom.min.js 38.5 kB
build/vendors/react.min.js 4.34 kB
build/viewport/index.min.js 1.08 kB
build/warning/index.min.js 280 B
build/widgets/index.min.js 7.21 kB
build/widgets/style-rtl.css 1.16 kB
build/widgets/style.css 1.16 kB
build/wordcount/index.min.js 1.07 kB

compressed-size-action

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.

Super happy to see this getting closer to unification! Pinging @jasmussen for a design review, since it's not entirely clear to me from the Figma mockups what the intended proportions are. (Mostly talking about the horizontal paddings. Should it be narrower so each icon option is a square? It kind of needs to be narrower for it to fit in the 50% sidebar width like in the mockups.)

in storybook the options are not set properly when we switch to different stories

My hunch is that this is due to using both Knobs and Controls in the same stories. I don't think they're designed to coexist. And even on their own, Knobs are pretty buggy when clicking between stories! We'll need to refactor them all to Controls soon.

packages/components/CHANGELOG.md Outdated Show resolved Hide resolved
@mirka mirka requested a review from jasmussen March 28, 2022 17:40
@ntsekouras
Copy link
Contributor Author

Thanks for the reviews!

for a design review, since it's not entirely clear to me from the Figma mockups what the intended proportions are. (Mostly talking about the horizontal paddings. Should it be narrower so each icon option is a square? It kind of needs to be narrower for it to fit in the 50% sidebar width like in the mockups.)

@mirka I saw that padding because I was testing this with changing the current textTransform control and I think we can handle this in a follow up. This has to do with the current padding applied(0 12px) and affects the component in general.

I think when we'll make the transition to other typography controls we might end up with some small differences from the original mockup, and I don't think that's a bad thing. It will be easier to test/iterate there.

@ciampo
Copy link
Contributor

ciampo commented Mar 28, 2022

We'll need to refactor them all to Controls soon.

Yup, we should definitely convert our Storybook examples to Controls!

This implementation makes the use of icon and label mutually exclusive. What this means is that if we provide an icon it will be used instead of the label and a tooltip will be shown automatically.

I'm not sure if this is the best strategy for this component's APIs:

  • label is required, but if using an icon it will be used for the tooltip instead
  • if aria-label is passed, label is not used for the tooltip
  • and so there is the change that the label prop is passed (as it's required), but it's never used in case both icon and aria-label are passed

We could also evaluate a different approach, which aims at simplifying the API by removing any hidden conventions:

  • label is not required
  • if both label and icon are passed, the component displays both (and therefore it would be up to the consumer of the component to pass only what is necessary)
  • the showTooltip prop would need to be explicitly set (and therefore it would be up to the consumer of the component to set the prop and pass an appropriate label or, even better in case of icons, an aria-label)

What do folks think?

@jasmussen
Copy link
Contributor

Thanks for the ping, nice one.

Needed for: #36735

I would caution this a bit, for two reasons. 1: we still need an interface control for a row of toggles, similar to bold/italic/link in the Paragraph toolbar. Here's a couple of examples:

Inspector

width

These are more like buttons or individual toggles, than they are items in a group. Furthermore, you can combine both strike-through and underline, so they aren't mutually exclusive, even if in the interface they are at the moment.

That's not to say we shouldn't add an icon to the option group, just that it likely can't replace the basic togglegroup.

Super happy to see this getting closer to unification! Pinging @jasmussen for a design review, since it's not entirely clear to me from the Figma mockups what the intended proportions are. (Mostly talking about the horizontal paddings. Should it be narrower so each icon option is a square? It kind of needs to be narrower for it to fit in the 50% sidebar width like in the mockups.)

Yes indeed, it's changed a few times back and forth. Like with inputs, I suspect this is one of the cases where we'd want to support both 36 and 40. I see it at 32px in Global Styles, not sure we need that, but it seems fine to start with 36 and go from there.

#38990 and #38577 both use a basic segmented control and the metrics we could start with are these:

segmented

Screenshot 2022-03-29 at 08 59 18

  • 36px by default
  • 1px border, #949494
  • 2px outer border radius (i.e. border-radius: 2px; if an inset shadow, 1px if an outset border)
  • 2px inner padding between the gray and the dark toggle
  • 2px border radius on the pill inside

Let me know if that was helpful!

@ntsekouras
Copy link
Contributor Author

We could also evaluate a different approach, which aims at simplifying the API by removing any hidden conventions:

  • label is not required
  • if both label and icon are passed, the component displays both (and therefore it would be up to the consumer of the component to pass only what is necessary)
  • the showTooltip prop would need to be explicitly set (and therefore it would be up to the consumer of the component to set the prop and pass an appropriate label or, even better in case of icons, an aria-label)

@ciampo we could try that. Personally I think showing both icon and label will make this a bit crowded, but 🤷 .

Also if we make label optional, is it okay to allow none of them passed?

both use a basic segmented control and the metrics we could start with are these:
36px by default
1px border, #949494
2px outer border radius (i.e. border-radius: 2px; if an inset shadow, 1px if an outset border)
2px inner padding between the gray and the dark toggle
2px border radius on the pill inside

@jasmussen these styles are for the component in general, correct? If yes I can open a separate PR for that, as it's not related to this one.

@jasmussen
Copy link
Contributor

these styles are for the component in general, correct? If yes I can open a separate PR for that, as it's not related to this one.

Yes, the general component. My mistake!

@jasmussen
Copy link
Contributor

if both label and icon are passed, the component displays both (and therefore it would be up to the consumer of the component to pass only what is necessary)

I'd do icon or label, not both, exactly for the space problems mentioned. If we find a particular need for this combination in the future, we can always revisit, but I wouldn't start with this.

@ciampo
Copy link
Contributor

ciampo commented Mar 29, 2022

Personally I think showing both icon and label will make this a bit crowded, but 🤷

I agree that it will look crowded — in this scenario, it would be up to the consumer of ToggleGroupControl to pass only what is necessary (icon or text label).

Also if we make label optional, is it okay to allow none of them passed?

It's not a great option, but my reasoning is that a situation where the component doesn't show anything (because neither label not icon were passed) is quite easy to spot and to understand what is the fix for.

If the content of the label prop is shown in different ways depending on other props (text label, toolptip text, or even ignored if aria-label and icon props are passed), it makes difficult for a consumer of ToggleGroupControl to understand what is happening and debug any issues.

I am basically not a fan of component APIs that rely on conventions like the ones proposed above, e.g "if propA is specified, than propB is ignored and propC is forced to true". It makes it hard to maintain and evolve a component, and difficult for a consumer to understand the APIs

Other alternative approaches could be:

  • to stop relying on label and replace it with a generic children mandatory prop — at that point, we could pass any contents to ToggleGroupControlOption. We could still write styles for text and icons in ToggleGroupControl to make sure that the design specs are applied
  • We could create a different ToggleGroupControlIconOption component with its own props

@ciampo
Copy link
Contributor

ciampo commented Mar 29, 2022

I missed this comment when writing my latest reply (thank you @ntsekouras for pointing it out!)

It's not a great option, but my reasoning is that a situation where the component doesn't show anything (because neither label not icon were passed) is quite easy to spot and to understand what is the fix for.

I agree that the approach that I proposed earlier (if both label and icon are passed, the component displays both) is not ideal, and I'm happy to drop it.

I left some thoughts about other alternative approaches in my last comment, let me know your thoughts!

@mirka
Copy link
Member

mirka commented Mar 29, 2022

@jasmussen Talking specifically about the horizontal paddings, should we decrease them to make each icon button a tight square, or keep the current ToggleGroupControlOption paddings for a rectangular shape?

Square Rectangle
Mockup with square-shaped icon button Implementation with rectangular icon button

(No strong opinion either way. It might even make sense to keep them visually distinct like this, so it's easier to grasp the difference between a group that's mutually exclusive and one that's not.)

@mirka
Copy link
Member

mirka commented Mar 29, 2022

these styles are for the component in general, correct? If yes I can open a separate PR for that, as it's not related to this one.

@ntsekouras Just FYI, the Components Squad will be coordinating height changes (#39397, though ToggleGroupControl is already correct) and border colors (#39425), so no need for you to independently address these two points for this specific component 👍

@mirka
Copy link
Member

mirka commented Mar 29, 2022

cc: @ciampo

  • to stop relying on label and replace it with a generic children mandatory prop — at that point, we could pass any contents to ToggleGroupControlOption. We could still write styles for text and icons in ToggleGroupControl to make sure that the design specs are applied
  • We could create a different ToggleGroupControlIconOption component with its own props

My vote goes to ToggleGroupControlIconOption, which I think is the most straightforward. Which, interestingly, would best be implemented in combination with the first approach ("generic children mandatory prop").

For example, something like this could be backwards compatible and simple to maintain:

  1. Internally, genericize ToggleGroupControlOption so it takes a children mandatory prop. Name it something different like ToggleGroupControlOptionBase. (We don't necessarily have to export this component publicly yet.)
  2. Using ToggleGroupControlOptionBase, make a thin wrapper component called ToggleGroupControlOption and keep the existing APIs (i.e. forward the label prop to <ToggleGroupControlOptionBase>{ label }</ToggleGroupControlOptionBase>).
  3. Using ToggleGroupControlOptionBase, make a thin wrapper component called ToggleGroupControlIconOption for icon buttons.

@jasmussen
Copy link
Contributor

It's not a great option, but my reasoning is that a situation where the component doesn't show anything (because neither label not icon were passed) is quite easy to spot and to understand what is the fix for.

If you provide both a label and an icon, can't we use the label just for aria-label?

@jasmussen
Copy link
Contributor

Talking specifically about the horizontal paddings, should we decrease them to make each icon button a tight square, or keep the current ToggleGroupControlOption paddings for a rectangular shape?

Ah, that's a good question. Visually, I'd actually think these work best the same as they are today:

same

That is — the black buttons are 32x32 inside a borderless 36px tall container.

Should we add a borderless version of the segmented control to account for this?

@ntsekouras ntsekouras force-pushed the add/icon-support-toggle-group-control-option branch from 176488a to 125fee4 Compare March 29, 2022 14:57
@ciampo
Copy link
Contributor

ciampo commented Mar 29, 2022

If you provide both a label and an icon, can't we use the label just for aria-label?

We could, but I see two drawbacks with this approach:

  • the contents of the label prop would be used in two different ways depending on the value of other props (in normal conditions, the label contents would be displayed to the user — but if the icon prop is specified, the label contents would either be used for accessibility-only purposes, or moved to a tooltip)
  • if the standard HTML aria-label prop is defined and the icon prop is defined, the contents of the label prop would be ignored

I'd personally prefer the approach highlighted by @mirka above, which is more straightforward in terms of API design and easier to maintain in the future:

My vote goes to ToggleGroupControlIconOption, which I think is the most straightforward. Which, interestingly, would best be implemented in combination with the first approach ("generic children mandatory prop").

For example, something like this could be backwards compatible and simple to maintain:

  1. Internally, genericize ToggleGroupControlOption so it takes a children mandatory prop. Name it something different like ToggleGroupControlOptionBase. (We don't necessarily have to export this component publicly yet.)
  2. Using ToggleGroupControlOptionBase, make a thin wrapper component called ToggleGroupControlOption and keep the existing APIs (i.e. forward the label prop to <ToggleGroupControlOptionBase>{ label }</ToggleGroupControlOptionBase>).
  3. Using ToggleGroupControlOptionBase, make a thin wrapper component called ToggleGroupControlIconOption for icon buttons.

@ntsekouras ntsekouras requested a review from mkaz as a code owner March 30, 2022 09: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 so much @ntsekouras for applying the feedback!

I've left a few comments, but most of them a very minor requests. We're close to being able to merge this 🎉

@ntsekouras
Copy link
Contributor Author

Thanks for the review and the help here @ciampo! Feedback addressed 😄

@ntsekouras ntsekouras force-pushed the add/icon-support-toggle-group-control-option branch from 2d00190 to 8c69689 Compare March 31, 2022 09:43
@ntsekouras ntsekouras force-pushed the add/icon-support-toggle-group-control-option branch from 8c69689 to 05e1573 Compare March 31, 2022 12:07
@ntsekouras ntsekouras changed the title [Components - ToggleGroupControlOption]: Add icons support [Components]: Add ToggleGroupControlOptionIcon component Mar 31, 2022
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 your patience when working on this PR, @ntsekouras !

Changes LGTM 🚀 (not sure if we want to get a final 👍 from @jasmussen and/or @mirka )

@ciampo ciampo requested a review from mirka March 31, 2022 13:21
@jasmussen
Copy link
Contributor

I'll trust you all on the inner mechanisms here! What's important on the visual side is that the letter case/text transform remain visually as they appear here. and aren't suddenly bordered or something.

@ntsekouras ntsekouras merged commit 98a478f into trunk Mar 31, 2022
@ntsekouras ntsekouras deleted the add/icon-support-toggle-group-control-option branch March 31, 2022 17:35
@github-actions github-actions bot added this to the Gutenberg 13.0 milestone Mar 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants