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: Introduce a isDisabled prop to the Disabled component #26730

Merged
merged 5 commits into from
Dec 7, 2020

Conversation

tyxla
Copy link
Member

@tyxla tyxla commented Nov 5, 2020

Description

A common pattern in projects is to receive the disabled form state from component state or passed props. Then, in order to make one or more @wordpress/components components disabled, we conditionally wrap them in a <Disabled /> component, or in a <Fragment />. And any time we want to do that, we have to wrap the <Disabled /> element with such a condition. This can actually be seen in the existing example in the documentation of <Disabled />.

To make this more intuitive, this PR introduces a isDisabled prop to the <Disabled /> component. Based on its boolean value (which defaults to true), the <Disabled /> component will now decide whether to disable all its children or not.

How has this been tested?

  • Manually - test instructions:
    • Spin up storybook locally with this branch: npm run storybook:dev
    • Go to http://localhost:50240/?path=/story/components-disabled--disableable
    • Clicking the "Set isDisabled to (true)|(false)" button, verify both "disabled" and "non-disabled" states work as expected and disable/enable nested fields.
  • With automated tests: npm run test-unit /packages/components/src/disabled

Screenshots

This PR doesn't introduce any visual changes.

Types of changes

This PR introduces a new isDisabled prop to the <Disabled /> component.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • 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.

@tyxla tyxla added [Package] Components /packages/components [Type] Feature New feature to highlight in changelogs. labels Nov 5, 2020
@tyxla tyxla self-assigned this Nov 5, 2020
@tyxla tyxla requested review from sarayourfriend and a team November 5, 2020 15:07
@github-actions
Copy link

github-actions bot commented Nov 5, 2020

Size Change: +2.99 kB (0%)

Total Size: 1.19 MB

Filename Size Change
build/block-directory/index.js 8.72 kB -1 B
build/block-editor/index.js 128 kB -117 B (0%)
build/block-editor/style-rtl.css 11.2 kB -55 B (0%)
build/block-editor/style.css 11.2 kB -51 B (0%)
build/block-library/editor-rtl.css 9.07 kB +127 B (1%)
build/block-library/editor.css 9.07 kB +124 B (1%)
build/block-library/index.js 149 kB +869 B (0%)
build/block-library/style-rtl.css 8.34 kB +71 B (0%)
build/block-library/style.css 8.34 kB +72 B (0%)
build/blocks/index.js 48.1 kB +2 B (0%)
build/components/index.js 172 kB +280 B (0%)
build/components/style-rtl.css 15.3 kB -8 B (0%)
build/components/style.css 15.3 kB -8 B (0%)
build/compose/index.js 9.95 kB +1 B
build/core-data/index.js 15.2 kB +391 B (2%)
build/edit-navigation/index.js 11.1 kB +3 B (0%)
build/edit-post/index.js 306 kB +699 B (0%)
build/edit-post/style-rtl.css 6.49 kB +71 B (1%)
build/edit-post/style.css 6.47 kB +67 B (1%)
build/edit-site/index.js 24.1 kB -6 B (0%)
build/edit-site/style-rtl.css 4.06 kB +156 B (3%)
build/edit-site/style.css 4.06 kB +155 B (3%)
build/edit-widgets/index.js 26.3 kB +1 B
build/editor/index.js 43.6 kB +268 B (0%)
build/editor/style-rtl.css 3.85 kB -6 B (0%)
build/editor/style.css 3.84 kB -4 B (0%)
build/element/index.js 4.63 kB +5 B (0%)
build/format-library/index.js 6.74 kB -119 B (1%)
build/i18n/index.js 3.57 kB +1 B
build/list-reusable-blocks/index.js 3.1 kB +2 B (0%)
build/media-utils/index.js 5.31 kB +1 B
build/plugins/index.js 2.56 kB +3 B (0%)
build/reusable-blocks/index.js 2.92 kB -6 B (0%)
build/rich-text/index.js 13.4 kB -2 B (0%)
build/server-side-render/index.js 2.77 kB +1 B
build/shortcode/index.js 1.69 kB +1 B
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.8 kB 0 B
build/api-fetch/index.js 3.42 kB 0 B
build/autop/index.js 2.84 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/style-rtl.css 943 B 0 B
build/block-directory/style.css 942 B 0 B
build/block-library/theme-rtl.css 789 B 0 B
build/block-library/theme.css 790 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/data-controls/index.js 827 B 0 B
build/data/index.js 8.98 kB 0 B
build/date/index.js 11.2 kB 0 B
build/deprecated/index.js 768 B 0 B
build/dom-ready/index.js 571 B 0 B
build/dom/index.js 4.95 kB 0 B
build/edit-navigation/style-rtl.css 881 B 0 B
build/edit-navigation/style.css 885 B 0 B
build/edit-widgets/style-rtl.css 3.13 kB 0 B
build/edit-widgets/style.css 3.13 kB 0 B
build/editor/editor-styles-rtl.css 476 B 0 B
build/editor/editor-styles.css 478 B 0 B
build/escape-html/index.js 735 B 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 2.27 kB 0 B
build/html-entities/index.js 623 B 0 B
build/is-shallow-equal/index.js 698 B 0 B
build/keyboard-shortcuts/index.js 2.54 kB 0 B
build/keycodes/index.js 1.93 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/notices/index.js 1.82 kB 0 B
build/nux/index.js 3.42 kB 0 B
build/nux/style-rtl.css 671 B 0 B
build/nux/style.css 668 B 0 B
build/primitives/index.js 1.43 kB 0 B
build/priority-queue/index.js 791 B 0 B
build/redux-routine/index.js 2.84 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/url/index.js 2.84 kB 0 B
build/viewport/index.js 1.86 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.22 kB 0 B

compressed-size-action

@ellatrix
Copy link
Member

ellatrix commented Nov 5, 2020

Could it not be a prop of the existing Disabled component, instead of introducing a new component? Also, no need to wrap in a fragment I think, you can directly return the children.

@tyxla
Copy link
Member Author

tyxla commented Nov 6, 2020

Thanks for the review, @ellatrix 🙌

Could it not be a prop of the existing Disabled component, instead of introducing a new component?

It totally could be! The main rationale for introducing a new component was naming semantics.

For example, I find this way more intuitive:

<Disableable disabled={ false }>
	<ToggleControl label="Something" />
</Disableable>

than:

<Disabled disabled={ false }>
	<ToggleControl label="Something" />
</Disabled>

because we avoid the "disabled" tautology, plus it looks a bit counter-intuitive to have a Disabled component that is not disabled sometimes, right? While a Disableable component makes sense in both "disabled" and "non-disabled" state. Does that make sense?

In any case, if you'd recommend moving the disabled prop to the Disabled component and/or renaming it to something like isDisabled, I don't have strong objections.

Also, no need to wrap in a fragment I think, you can directly return the children.

That's true. The main reason to prefer wrapping in a <Fragment /> here was to return children just once, instead of returning it twice conditionally. This is a minor preference of mine, of course, and I'm happy to alter it if you prefer avoiding Fragment usage.

@tyxla tyxla requested a review from sarayourfriend November 6, 2020 11:40
@ellatrix
Copy link
Member

ellatrix commented Nov 6, 2020

I don't know, to me a disabled prop on Disabled to turn it off or on doesn't seem strange. We have other hooks and components that have an isDisabled prop which turns the logic on or off.

@ellatrix
Copy link
Member

ellatrix commented Nov 6, 2020

The main reason to prefer wrapping in a <Fragment /> here was to return children just once, instead of returning it twice conditionally. This is a minor preference of mine, of course, and I'm happy to alter it if you prefer avoiding Fragment usage.

I don't understand, returning it twice? The fragment seems to add unnecessary nesting to the React tree.

@tyxla tyxla force-pushed the add/components-disableable branch from 2daf41f to ed70ce1 Compare November 9, 2020 11:02
@tyxla
Copy link
Member Author

tyxla commented Nov 9, 2020

Thanks for double-checking and clarifying @ellatrix!

I've reconsidered both your suggestions and implemented them in ed70ce1

This PR could use another review when you get a chance.

@tyxla tyxla changed the title Components: Introduce a Disableable helper component Components: Introduce a isDisabled prop to the Disabled component Nov 9, 2020
@tyxla
Copy link
Member Author

tyxla commented Nov 26, 2020

Would be great if I could get a review here from anyone who has a spare cycle. @adamziel @youknowriad any idea who's best to ping for that?

@adamziel
Copy link
Contributor

adamziel commented Nov 27, 2020

I don't mind having such prop - it makes life easier even if it is a tiny bit awkward. This here is very similar to a discussion we've once had about <VisuallyHidden> and isHidden prop. I wonder if there's a general pattern for situations like that?

cc @noisysocks @gziolo @kevin940726 @draganescu

@adamziel
Copy link
Contributor

adamziel commented Nov 27, 2020

@tyxla I understand you wanted to avoid the following code?

const DisabledMaybe = shouldBeDisabled ? Disabled : Fragment;

return (
    <DisabledMaybe>
        // ...
    </DisabledMaybe>
)

Copy link
Member

@kevin940726 kevin940726 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 also not against it, but mainly because I can't think of any better way to do this 😂. Hooks might be helpful here, but would likely require a larger refactoring though.

packages/components/src/disabled/index.js Outdated Show resolved Hide resolved
@@ -133,6 +133,46 @@ describe( 'Disabled', () => {
expect( div.hasAttribute( 'tabindex' ) ).toBe( true );
} );

it( 'will disable descendant fields if isDisabled prop is set to true', () => {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can try to merge these two test cases together and simulate a state update from isDisabled={true} to isDisabled={false} in between. Just to make sure that the descendant fully updated.

Copy link
Member Author

Choose a reason for hiding this comment

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

Isn't this already covered in the previous test?

Copy link
Member

@kevin940726 kevin940726 Dec 1, 2020

Choose a reason for hiding this comment

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

That test tested from wrapping <Disabled> to not wrapping it. What I expect here is to test it from isDisabled={true} to isDisabled={false} (or the other way around) while always wrapping it with <Disabled>. Makes sense :)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for elaborating @kevin940726 - that makes sense! I'll update the tests shortly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated in 11c1a62. Thanks again!

@tyxla tyxla force-pushed the add/components-disableable branch from ed70ce1 to 4461198 Compare November 30, 2020 14:51
@tyxla
Copy link
Member Author

tyxla commented Nov 30, 2020

@tyxla I understand you wanted to avoid the following code?

const DisabledMaybe = shouldBeDisabled ? Disabled : Fragment;

return (
    <DisabledMaybe>
        // ...
    </DisabledMaybe>
)

Yes, exactly. While it's extremely simple, it could be very useful to avoid writing it every time one uses Disabled. And from my experience, it's the most often used way to consume Disabled.

@tyxla
Copy link
Member Author

tyxla commented Nov 30, 2020

I think all the feedback has been covered here, could I ask for another review when you folks get a chance?

@tyxla tyxla requested review from kevin940726 and adamziel and removed request for adamziel and kevin940726 December 4, 2020 11:36
Copy link
Member

@kevin940726 kevin940726 left a comment

Choose a reason for hiding this comment

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

Looks good enough to me ❤️

@tyxla tyxla merged commit a834386 into master Dec 7, 2020
@tyxla tyxla deleted the add/components-disableable branch December 7, 2020 11:26
@github-actions github-actions bot added this to the Gutenberg 9.6 milestone Dec 7, 2020
@youknowriad youknowriad added [Type] New API New API to be used by plugin developers or package users. and removed [Type] Feature New feature to highlight in changelogs. labels Dec 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Package] Components /packages/components [Type] New API New API to be used by plugin developers or package users.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants