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

Allow for core block Inspector Controls to be extended and removed #6023

Closed
paulwilde opened this issue Apr 5, 2018 · 44 comments
Closed

Allow for core block Inspector Controls to be extended and removed #6023

paulwilde opened this issue Apr 5, 2018 · 44 comments
Labels
[Feature] Extensibility The ability to extend blocks or the editing experience Framework Issues related to broader framework topics, especially as it relates to javascript [Type] Enhancement A suggestion for improvement.
Milestone

Comments

@paulwilde
Copy link
Contributor

paulwilde commented Apr 5, 2018

For all client websites that I build I strip the WordPress admin down to the bare minimum as to reduce the burden and learning curve for my clients. This includes things like removing the Posts menu item if posts are not used on the site, and every meta box which aren't being used.

One big issue I'm struggling with Gutenberg at the moment in terms of extensibility, is that there's a bunch of inspector controls which I don't need, thus increasing said burden. A good example of this is the core/paragraph block, as that has a bunch of options allowing you to recreate a Geocities website where you can set inline background & font colours and whacky text sizes.

As there is currently no API or filter to remove the controls, I've had to resort to a bunch of sophistically CSS to simply display: none the Text Settings panel and recreate the options I want.

An idea for an API would be to wrap each control which gets rendered in the Text Settings panel inside a keyed array, where the value is the control component which gets rendered.

Using core/gallery as an example, due to it only having 3 controls currently, something like this:

let controls = {
    setColumnsNumber: <RangeControl
        label={ __( 'Columns' ) }
        value={ columns }
        onChange={ this.setColumnsNumber }
        min={ 1 }
        max={ Math.min( MAX_COLUMNS, images.length ) }
    />,
    imageCrop: <ToggleControl
        label={ __( 'Crop Images' ) }
        checked={ !! imageCrop }
        onChange={ this.toggleImageCrop }
    />,
    linkTo: <SelectControl
        label={ __( 'Link to' ) }
        value={ linkTo }
        onChange={ this.setLinkTo }
        options={ linkOptions }
    />,
};
controls = applyFilters( 'blocks.inspectorControls', controls, this );

Then with such a pattern in place, one can easily remove controls as they desire. Assuming lodash is being used, this filter would remove the setColumnsNumber and imageCrop controls:

function removeGalleryControls( controls, block ) {
    if ( 'core/gallery' == block.props.name ) {
        return omit( controls, [ 'setColumnsNumber', 'imageCrop' ] );
    }
    return controls;
}
addFilter( 'blocks.inspectorControls', 'remove-gallery-controls', removeGalleryControls );

This filter would update the Columns control by changing the maximum range, and updating its label:

function replaceGalleryControl( controls, block ) {
    if ( 'core/gallery' == block.props.name ) {
        const { columns } = block.props.attributes
        
        controls.setColumnsNumber = <RangeControl
            label={ __( 'New Label!' ) }
            value={ columns }
            onChange={ block.setColumnsNumber }
            min={ 1 }
            max={ 3 }
        />;
    }
    return controls;
}
addFilter( 'blocks.inspectorControls', 'replace-gallery-control', replaceGalleryControl ); 

And obviously reordering the controls along with adding additional ones should be quite evident at this point. Also it's easier to globally add controls to more than 1 block at a time which is an added advantage.

It's possible that there might be a cleaner or more React-like approach which allows for such extensibility, however I do believe it's quite a critical pain point prior to Gutenberg shipping.

@noisysocks noisysocks added [Type] Question Questions about the design or development of the editor. [Feature] Extensibility The ability to extend blocks or the editing experience labels Apr 5, 2018
@noisysocks
Copy link
Member

cc. @gziolo

@gziolo
Copy link
Member

gziolo commented Apr 9, 2018

Related comment from #5995:

Although I like the changes, this has had an impact on my implementation where I've been adding additional controls to core blocks.

As an example with the 'Advanced' Settings disabled (Custom CSS and Anchors), I have added 3 additional controls to the Heading Settings. The last 3 at the bottom:

screen shot 2018-04-05 at 13 40 54

However, when the panel is closed, these additional settings are no longer contained within the same panel:

screen shot 2018-04-05 at 13 42 21

I don't want to be limited to where I need to create a separate expandable panel for very basic additional settings such as text colour as it adds more weight to the UI. I'd want them to live in the same main 'Heading Settings' panel.

As there is currently no documentation on how controls can be added to existing blocks I used the implementation that the Custom CSS and Anchors uses in order to learn on how to add these additional controls. Maybe its possible to target the controls to be rendered at the bottom of the 'Heading Text' component, although I couldn't figure it out.

For clarify sake, here is what I'm doing to add new controls:

function onUpdate( BlockEdit ) {
    const WrappedBlockEdit = ( props ) => {
        if ( 'core/heading' !== props.name ) {
            return <BlockEdit { ...props } />
        }

        const { attributes, setAttributes, isSelected } = props
        
        return [
            <BlockEdit { ...props } />,
            isSelected && <InspectorControls key="inspector">
                <ToggleControl
                    label={ __( 'Custom Control' ) }
                    checked={ !! attributes.customControl }
                    onChange={ onChangeEvent }
                />
            </InspectorControls>,
        ]
    }
    return WrappedBlockEdit
}
addFilter( 'blocks.BlockEdit', 'custom/heading/update', onUpdate )

@jasmussen
Copy link
Contributor

This use case seems perfectly valid as a point of extensibility going both ways.

Before starting work on addressing the specific use case, it seems worth looking at inspector controls as they are today, as they are a little bit all over the place (yes, we've had to work fast!):

  • Heading has panels for all controls
  • Button does not have a panel for the first set of controls
  • Paragraph starts with most panels collapsed, but not the alignment one
  • the lack of borders between panels, like in the Document sidebar, makes it a bit hard to see where one panel ends and another panel begins
  • state of panel isn't saved between sessions or users (separate point you made, @paulwilde)

It seems like the first step then, is to add consistency between all current inspector controls, just as a stepping stone to more advanced extensibility. Without patterns, any extensibility we build will be a nightmare to work with.

Such a ToDo could be to add borders between panels, to match the Document sidebar:

screen_shot_2018-04-09_at_12 54 54

(not with the double border as shown above, that's just a bad inspector mockup)

Decide a pattern for which panels are open by default. For example we could decide that only the topmost panel is open, all subsequent ones are closed. A future PR that stores this state on a user basis would then ameliorate any commonly used settings, while still keeping a strong default pattern.

Decide, perhaps, that no settings can be added to the sidebar, without being part of a panel. I.e. Button block would need some work.


In the end we'd have something far more manageable — every inspector would look like this:

[block description]
---
Block Settings ▼
... various block settings ...
---
Other Settings ▶
---
Advanced Settings ▶

The benefit of doing this legwork, aside from the consistency it would bring, is that it would help surface answers to how to best extend this.

Maybe we'll learn it is sufficient to be able to unregister/remove a panel and/or add your own.

Or maybe we'll learn that you do in fact need to be able to extend every panel, in addition to removing panels or adding your own.

@gziolo gziolo added the Needs Design Feedback Needs general design feedback. label Apr 9, 2018
@gziolo
Copy link
Member

gziolo commented Apr 9, 2018

@jasmussen @paulwilde thanks for sharing your feedback. I think that the most important part is to decide first how we want to have the Inspector Controls designed and structure before we come up with any further refinements. We need to make sure that we have consistent look and feel for those controls before we allow any advanced detailed manipulations.

The biggest challenge I see here is to decide where we draw the line between modifying the existing block and creating your own instance of the same block which has some options removed.

Also the proposed API for modifying the list of controls could be as simple as:

supports: {
    allowedInspectorControls: [ 'align', 'fontSize' ],
}

where allowedInspectorControls would list all enabled controls. There is still questions if it should be control based or control groups based. That's why we need to finalize how it should be designed first.

@gziolo gziolo removed the Needs Design Feedback Needs general design feedback. label Apr 9, 2018
@jasmussen
Copy link
Contributor

That's a great way to frame it, and pseudo code API example. It can also help frame the decision.

Hypothetical: let's say there's a panel called Alignment, or Layout, that came with a core block. Let's say a plugin wanted to extend that panel, and provide additional alignment or layout related options. If the API was control groups based, would the plugin be able to unregister, copy the initial one, and then recreate the panel with additional options?

@MikeB8s
Copy link

MikeB8s commented Apr 19, 2018

I think that this discussion might also apply to custom taxonomy blocks in the side panel. For instance, a plugin should be able to disable/hide the taxonomy Parent form (issue #6057)

@jasonbahl
Copy link

Without the ability to filter controls right now, we’re replacing just about every core block with our own custom versions of blocks so we can control the experience better. I think the filterability of the inspector fields is very critical to consider Gutenberg ready to ship.

I believe this should be considered as related to #2751, as core inspector controls should be defined in the server side registry for blocks, so that all clients(CLI, Gutenberg, REST, WPGraphQL, iOS/Android) can have appropriate knowledge of what controls exist for interaction with any given block.

Gutenberg Fields Middleware (https://github.com/rtCamp/gutenberg-fields-middleware) is a great project worth looking at to show how Inspector controls can be registered (and thus filtered/deregistered) all from the server block registry.

@chrisvanpatten
Copy link
Contributor

We're in a similar position — we want to remove support for font sizes and drop caps in the paragraph block, and are likely going to need to resort to a CSS display: none hack since we want to avoid replacing core blocks.

@MikeB8s
Copy link

MikeB8s commented May 15, 2018

At least for the case of custom taxonomies in the Gutenberg plugin, ids have been removed from the side panel controls, which hinders even using CSS to hide controls.

@jasonbahl
Copy link

Ya, I’d be curious to see a CSS solution to hide specific controls based on the current CSS output. 🤔

@chrisvanpatten
Copy link
Contributor

For text size, it's quite easy. That inspector panel can be targeted with .components-panel__body.blocks-font-size. Luckily for me, we don't need to hide anything else on this particular project.

@dionysous
Copy link

dionysous commented Jul 15, 2018

@gziolo I have another example of how I would like to extend core blocks (I don't know if this have been already mentioned). I want to add a control called "Additional CSS ID", right under "Additional CSS Class". My theme needs anchors/IDs to navigate on a single page navigation. With the current tools and props of the core blocks, this is not possible.

I would like to add a new prop "id" and to let it appear in the sidebar control panel. I am not sure how to do it now. It would make sense to have it on every block, including the columns block.

Is it planed to be implemented into Gutenberg, or should it be extended by the users? How can I start to do it?

@gziolo
Copy link
Member

gziolo commented Jul 23, 2018

@HippDesign - a quick solution would be to reuse existing solution for anchor which behind the scenes adds id attribute to the block.
Related code: https://github.com/WordPress/gutenberg/blob/master/editor/hooks/anchor.js.
Related docs: https://wordpress.org/gutenberg/handbook/block-api/#supports-optional.

You can either reimplement the logic yourself using code similar to what I shared or set supports option anchor to true for your block. I think we use it only for Heading block at the moment:
https://github.com/WordPress/gutenberg/blob/master/core-blocks/heading/index.js#L37

@benlk
Copy link
Contributor

benlk commented Aug 30, 2018

Yes, so far the only place where the anchor control is used is the heading block.

But there are no details in the heading block's code to explain how anchor is supported. The only reference to anchor in the whole of the package is the supports declaration:

const supports = {
className: false,
anchor: true,
};

It just supports anchors, magically. There's no information about how to get the anchor value to apply in any custom block.

@luistinygod
Copy link

I'm interested to hide the custom font size control and the drop-cap toggle in the Paragraph block Inspector. There are already some get_theme_support/add_theme_support calls available to customize/disable custom colors, and to customize the font sizes. Why not considering to extend this pattern like:

add_theme_support( 'disable-drop-cap' );
add_theme_support( 'disable-custom-font-sizes' );

Although this pattern is not as good as the one described by @paulwilde here, I would say it is a quick win, at least to the Paragraph block, which is the most used block.

@mrpritchett
Copy link

Is there any update to this extensibility?

@gziolo
Copy link
Member

gziolo commented Oct 4, 2018

@noisysocks is working on adding a modal with options - so far document settings are going to covered. Let's see how block fit this.

@noisysocks
Copy link
Member

#10210, for reference.

@mrpritchett
Copy link

I honestly think having them extensible is a far better goal than a UI fix, but I guess it would be helpful in some cases for now?

@noisysocks
Copy link
Member

It's likely that the UI would be built on top of an API that developers could call, e.g. a disablePanel action.

@MizuBishi
Copy link

Hi there...I am struggling to disable the Advanced meta box (HTML Anchor and Additional CSS Class) in all core blocks. Any recommendations? Thanks!

@mrpritchett
Copy link

Hi there...I am struggling to disable the Advanced meta box (HTML Anchor and Additional CSS Class) in all core blocks. Any recommendations? Thanks!

Any reason you can't simply hide it with CSS for now?

@MizuBishi
Copy link

Hi there...I am struggling to disable the Advanced meta box (HTML Anchor and Additional CSS Class) in all core blocks. Any recommendations? Thanks!

Any reason you can't simply hide it with CSS for now?

Sure, I just thought maybe there is function, e.g. remove_post_type_support(...) like in the themes.

@youknowriad
Copy link
Contributor

youknowriad commented Apr 22, 2019

Hi there and thanks for the discussions here. Ultimately I agree that we need a good API to toggle features in the editor. We have a precedent here with disable-custom-font-sizes and disable-custom-font-sizes but I don't think is going to scale properly if we keep adding these options per "feature".

I think a good way to think about this might be to try to be more "generic" and "semantic" instead of thinking specifically about given features of particular block types or thinking about specific UI elements (inspector/block controls)

For example, the editor settings could say "colors are disabled" and block authors would have the possibility to understand this setting and implement it properly. I think a path forward would be to try to find these "generic/global configs". A rough list could be:

  • Colors
  • Font Sizes
  • Image manipulation
  • Advanced typography (dropcap)
  • ...

Based on this the editor settings and the existing editor settings filter https://developer.wordpress.org/reference/hooks/block_editor_settings/ could be a good solution here.

For people interested in this area, I'd like to propose that you come up with an RFC explaining the pros/cons and the proposed technical solution. This would help discuss the API properly and move to implementation.

@youknowriad youknowriad added [Type] Enhancement A suggestion for improvement. Framework Issues related to broader framework topics, especially as it relates to javascript and removed [Type] Question Questions about the design or development of the editor. labels Apr 22, 2019
@gziolo
Copy link
Member

gziolo commented May 6, 2019

For people interested in this area, I'd like to propose that you come up with an RFC explaining the pros/cons and the proposed technical solution. This would help discuss the API properly and move to implementation.

I opened #15450 to centralize the discussion related to Common Block Functionality.

@mrwweb
Copy link

mrwweb commented Oct 4, 2019

It's really frustrating not to have any progress on this in 5.2 or 5.3. As more and more options get added to core blocks (Button Border Radius chief among them), it is becoming more and more important that site builders are able to hide presentational settings that don't align with the design of the site. The general concept of blocks is gloriously compatible with empowering site editors to implement content in a well-crafted design system (including the ability to provide predefined component style variations), but these immovable options either allow site editors to break from the intended site styles or frustrate editors if the theme intentionally overrides them so they have no effect.

While I get the sense there was some distaste for this option in the past, simply putting unique CSS classes on blocks panels and block settings would essentially solve the problem sufficiently for many of us, at least in the short term. Is that something that could happen in 5.3.1?

@gziolo
Copy link
Member

gziolo commented Oct 7, 2019

While I get the sense there was some distaste for this option in the past, simply putting unique CSS classes on blocks panels and block settings would essentially solve the problem sufficiently for many of us, at least in the short term. Is that something that could happen in 5.3.1?

As noted earlier, the goal is to provide a solution that is more flexible and can satisfy the needs of users, site owners, designers, and developers. This is something that is going to be one of the priorities in the WordPress 5.4 cycle. While I understand that adding a class name would solve some of the issues, but I personally don't think that it's something we want to commit to and support it forever. There is more to it, you can add a single control in core, but it can be also a group of related controls. There is also this huge ecosystem of plugins that can register their own options as well. It's hard to imagine a single way where all use cases are covered.

I encourage everyone to join the discussion in #15450 to find the approach which would take into account all that I shared above. At the same time, feel free to open a Pull Request with a proposal on how such an approach using class names would work. It's much easier to talk about seeing working prototypes that address the issues that discuss in theory. I'm happy to review it and change my mind.

cc @mtias @youknowriad

@mrwweb
Copy link

mrwweb commented Oct 7, 2019

This is something that is going to be one of the priorities in the WordPress 5.4 cycle

This is fabulous to hear, and I hadn't seen that elsewhere.

My suggestion of the class name half-solution is really about enabling something so those of us eager to reduce the number of core block options can act. I assume that adding some CSS classes (to panel sections and settings) would be significantly easier than refactoring all settings panels to allow a unified API that unregisters core settings. (And I'm also unclear on what harm would be caused by doing so.) If that is something that could even happen in 5.3.1, it would be immensely beneficial for the sites I build.

There is also this huge ecosystem of plugins that can register their own options as well. It's hard to imagine a single way where all use cases are covered.

With plugins, developers at least have the option of not using them. With core blocks, everyone has to use them (at least for something like the Paragraph block and it's accompanying and much-maligned Dropcap setting) and so the inability to disable formatting options is very frustrating.

@kraftner
Copy link

kraftner commented Oct 8, 2019

@mrwweb I totally agree to the urgent need, but coming from over a decade of WordPress experience even though the waiting time is painful I rather have a solid solution than a shot from the hip that then haunts us forever in the form of backwards compatibility.

@LukaszJaro
Copy link

LukaszJaro commented Oct 29, 2019

Glad to hear 5.4 will include a solution to this, I was testing the latest WP nightly build new columns block, which now include column settings for column width:

#15499

If you have a design style guide to follow this can cause issues, what would of been nice is if you can create your own style guideline for columns without code, example:

Column sizes
50/50
33/33/33
60/30
30/60
etc

I would prefer this over dragging column widths, which is actually more tedious if you have to do it for each block column.

This would give more power to WordPress implementer's to lock down the layout of their site. Right now it looks like a Elementor feature, which I hope Gutenberg does not turn into (content editors praise Gutenberg for its simplicity and minimalist design where I work)

Is CSS the best way to hide this new feature when it comes out in 5.3? Or use JS to disable this?

Update: there is no way to target the panel or control through css or js since their is no distinct class or id

@gziolo
Copy link
Member

gziolo commented Mar 3, 2020

We have now an official proposal from @youknowriad on how to introduce more control over block editor features as explained in https://make.wordpress.org/core/2020/01/23/controlling-the-block-editor/ and tracked in #20588. It should address the concerns in regard to most of the visual features discussed in this issue. In case of configuration options like the number of columns, ranges in general, we have another tracking issue where we collect use cases: #15450. They seem to be related more to the topic of making some controls configurable.

Do you think, we can close this issue in favor of the two existing issues or do I miss anything important?

@youknowriad
Copy link
Contributor

Seems like it for me. Let us know if we missed anything and once the API in place we can follow up with issues for specific things in order to discuss each key separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Extensibility The ability to extend blocks or the editing experience Framework Issues related to broader framework topics, especially as it relates to javascript [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

No branches or pull requests