Widget Customizer Feature-as-Plugin Merge Proposal

Widgets in WordPress provide an easy way to add functionality to predefined areas of your theme templates. However, once you add a widget to a sidebar you have to leave the WordPress admin to go back to the frontend to actually see how the updated widget appears in the sidebar on your site’s public frontend. While you are making these changes and experimenting with a widget, it could be completely broken and everyone visiting your site will see this broken widget since there is no core way to preview changes made to widgets. But WordPress also provides an excellent way to preview changes to various settings on your site via the (Theme) Customizer. Changes made when using the Customizer are not visible to site visitors until you hit Save & Publish. So what if widgets could be edited in the Customizer? That’s what the Widget Customizer plugin makes possible. No longer do you have to edit your widgets blind!

Each registered sidebar on your site gets its own section in the Customizer panel. Within each section, widgets appear in their sidebar order. The widget controls appear there just as they appear when editing widgets in the widgets admin page. Upon making a change to the widget control, pressing the form’s Update button causes the changes to appear in the preview window; no changes to the widgets are saved permanently for others to see until you hit the Customizer’s Save & Publish button. This goes for whether you’re adding a new widget, editing existing widgets, reordering widgets, dragging widgets to other sidebars, or even removing widgets from the sidebars entirely: all of these actions are previewable.

Adding a widget to a sidebar slides open a panel for browsing the available widgets, complete with the usual names and descriptions, but also featuring widget icons to help quickly identify widgets. The list of available widgets can also be filtered down with a search input.

When you remove a widget from a sidebar, it is not deleted. Instead, it is moved from an active sidebar to the “Inactive Widgets” sidebar which can currently be seen on the widgets admin page. As such, removing a widget now is the same as trashing a widget.

Customizer control sections for sidebars are shown and hidden dynamically when the preview window is initially loaded or when navigating the site within the preview window, based on whether or not the sidebar gets rendered in the previewed URL. (You may not know this, but you can navigate your site by clicking links in the preview window.) Only sidebars which can be previewed will be shown in the customizer panel. Likewise, widgets that are not rendered in the preview (for example, by means of Jetpack’s Widget Visibility module) will appear in the Customizer as semi-transparent.

Accessibility has also been a key concern for Widget Customizer. The current keyboard navigation on the widgets admin page feels cumbersome, having to open screen options to enable a separate accessibility mode. We wanted to make re-ordering with widgets as seamless as possible. So now when any sidebar section is open, you can invoke a reorder mode to reveal up/down arrows to reorder widgets, as well as a subpanel to open for moving the widget to another sidebar entirely. (This feature is nearing completion in pull request #21.)

While all themes and widgets should work with Widget Customizer, for the best experience the themes and widgets need to indicate they support live previews of sidebars and widgets. Without such support added, each change to a sidebar or widget will result in the preview window being refreshed, resulting in a delay before the changes can be seen (settings default to transport=refresh). To enable a much more responsive preview experience, themes and widgets should indicate that they support Widget Customizer live previews; this will update the relevant settings to use transport=postMessage, the updated widgets will be loaded via Ajax, and the widgets will be re-ordered via DOM manipulation.

All core widgets and themes distributed with WordPress core are supported by default. For other themes, simply include add_theme_support('widget-customizer') in your theme’s functions.php to opt-in. If your theme does some dynamic layout for a sidebar (like Twenty Thirteen uses jQuery Masonry), you’ll also need to then enqueue some JavaScript to listen for changes to the sidebar and reflow them when that happens; see the bundled support for Twenty Thirteen to see an example of what is required.

Along with themes needing to indicate support for live-previewable sidebars, widgets must also indicate that they support being live-previewed with Widget Customizer. When updating a widget, an Ajax call is made to re-render the widget with the latest changes, and then the widget element is replaced in the sidebar inside the preview. If a widget is purely static HTML with no associated script behaviors or dynamic stylesheets (like all widgets in core), then they can right-away indicate support for live previews simply by including'customizer_support' => true in the array passed to WP_Widget::__construct(). As with sidebars, if a widget has dynamic behaviors which normally only get added when the page first loads (such as a widget which includes a carousel), then a script needs to be enqueued in the Customizer preview which will re-initialize the widget when a widget is changed.

The sidebar-updated and widget-updated events get triggered on wp.customize when sidebars and widgets get updated, each being passed the sidebar ID and the widget ID respectively as the first argument in the callbacks. For a full example demonstrating how to add theme support for live-previewing dynamic sidebars and how to add support for JS-initialized widgets, see this annotated Gist.

Core Tickets

A few Core tickets have been opened with patches to generally improve widgets and the customizer, and also to improve Widget Customizer itself:

User Tests

A coupleuser tests have been done, both of which went pretty well. More user testing is being queued up. Here’s the first user test video, though note it reflects an early rendition of the plugin:

[wpvideo tH9DTaey]

Remaining Issues

In addition to wrapping up the keyboard-accessible widget reordering (#21), there is the dilemma of how to handle wide widget form controls (#18); various solutions have been proposed for how to display a widget control which does not fit within the customizer panel.

The other open issues are enhancements or open questions which may or may not need actioning.

Share this:

This is really cool. Since all this widget refresh activity has been going on, I have seen the light on how great they are. It would be cool if we could find a way to rename the unfortunately base-named “sidebars.” I have no recommendation for something better, but it seems like widgets would really get their due if they were named appropriately as “one of many in a theme area” or “widget collection” or belong to a “module container.”

For what it’s worth (and it isn’t worth much), while this post uses the word “sidebar” repeatedly and while core code uses it extensively in the API, it’s nowhere in the UI. When we need to refer to one, we call it a “widget area” (such as in the help tabs).

Yes, we started actively saying widget area instead of sidebar when it was the controversy of the day several years back.

tomdryan
4:32 am on January 29, 2014

Scott I agree with you — the term “Sidebar” is outdated and should be retired, except when referring to containers that are actual (left/right) sidebars. The term that I’ve taken a liking to is “Container”. I’m hoping to see the entire widget functionality morphs into something more universal within WordPress, so you could have widgets, text, html, etc within a container. Page templates are made up of containers and containers can have widgets, media, text, html or other containers and other content within them.

If you look at it that way, a menu is essentially a container (with a menu widget), as is the page header, as is the login dialog, etc, etc. Eventually, everything that is displayed by a WP site could be easily accessible and modifiable by the user without the need to edit any code or text files (unless they want to of course).

@PeterRKnight: no, we were talking about it over Skype today some more. Still really challenged by this. @michael-arestad did some more mocks: https://cloudup.com/iqH4tGUbQPn

I think the idea I like the most is if wide widget controls opened over the preview as draggable areas. But it is a jarring user experience for some widgets to have controls sliding down within the panel, with others appearing in these floating windows.

Ah! Is there a reason why wide *and* normally sized controls couldn’t both enjoy the draggable-over-the-preview format? It would be consistent that way.

Nice mockup, is it pushing the width of the preview section into a smaller frame though or does it hover over the preview? Hard to tell from the mockup, but it looks like it pushed the page layout into a narrow tablet/mode layout, I think that might be less intuitive when configuring widgets.

2) If this gets into core, it seems that a bit more consistency between the backend admin and Customizer would be useful. Particularly, if the widget icons are used in the Customizer, I’d expect them to be used in core.

3) I think it’s important to consider how these would interact with the various “Widget Visibility” plugins (Jetpack’s Widget Visibility, Widget Logic, Widget Logic Visual, Conditional Widgets, Display Widgets, Dynamic Widgets, etc.). Right now, that can result to a widget appearing in the customizer but not in the preview.

4) My biggest concern about including this in core is that it shifts the purpose of the Customizer from one intended for modifying the visual presentation of every page on a site, to one that handles content that may change from page to page (based on widget visibility mentioned in #3 or sidebars only appearing on certain pages). The discussion over including this in core should start by clarifying the purpose of the Customizer and whether or how much it should address editing content.

5) If not all widgets can be supported when the feature is launched and not all themes can fully support the customizer, I worry that this will lead to further confusion for beginning users. What does it say if there are two places to administer widgets but some widgets can only be edited in one of the two? I think that segmentation could prove very very very confusing and frustrating to users.

6) An alternative, much simpler change to widget administration could be similar to the front-end module edit link added to Joomla 3.2. I made a pass at this in the WP Inline Access plugin as you can see in the first screenshot on the plugin’s page. I think this comes down to what the most important feature of this plugin is. Is it to show how a widget looks (advantage: Customizer) or is it to help users quickly administer widgets from the front end (advantage: Link to Admin, in my mind).

3) I think it’s important to consider how these would interact with the various “Widget Visibility” plugins (Jetpack’s Widget Visibility, Widget Logic, Widget Logic Visual, Conditional Widgets, Display Widgets, Dynamic Widgets, etc.). Right now, that can result to a widget appearing in the customizer but not in the preview.

5) If not all widgets can be supported when the feature is launched and not all themes can fully support the customizer, I worry that this will lead to further confusion for beginning users. What does it say if there are two places to administer widgets but some widgets can only be edited in one of the two? I think that segmentation could prove very very very confusing and frustrating to users.

@mrwweb actually, all widgets and themes should be supported already (except for widgets with wide controls, as noted above). The piece that widgets and themes have to explicitly opt-in support for is live previews. Without that support indicated, then changes to widgets and their areas will cause the preview to refresh. This is in-line with other settings exposed in the customizer: by default they cause a refresh. Themes already have to add explicit support for live previews of settings (transport=postMessage), and so too the widgets need to indicate they support being updated without a page refresh. So themes and widgets that don’t indicate support for Widget Customizer will get a less responsive preview experience, but it all should still work.

2) If this gets into core, it seems that a bit more consistency between the backend admin and Customizer would be useful. Particularly, if the widget icons are used in the Customizer, I’d expect them to be used in core.

1) The widget block should be lower in the set of customizer components
2) When selecting a sidebar, it would be nice if it was highlighted.
3) I think it might be nice to keep the highlighting of the selected widget so that the user can orient themselves when making adjustments
4) I wonder if it would be better if there weren’t update buttons and instead the preview auto-refreshed like the other settings do.

In terms of the customizer as a whole, it would be nice if we could deep link to a specific component and incorporated some pushState() functionality in so that a plugin could experiment with removing the corresponding /wp-admin/ pages and still provide menu items that pointed directly to the component.

That’s a great point. I had considered that, but the problem is that there is not guaranteed to be a single element container for the widgets in a sidebar widget area. I suppose the highlight could be added to the element that is the common parent element to all of the widgets. Or all widgets in the area could be highlighted together.

3) I think it might be nice to keep the highlighting of the selected widget so that the user can orient themselves when making adjustments

?

Agreed. The red glow is more of a placeholder. @shaunandrews has done some very interesting work on the widget highlighting front. There is an open pull request that needs to further build upon his prototype, which involves an innovative use of canvas to fade-out other parts of the page: https://github.com/x-team/wp-widget-customizer/pull/16

The problem with this is that widget controls may vary well have form validation in place (e.g. the RSS widget) which will cause a error message to appear in the form if it gets submitted before all of the fields are populated. Also, the widget update handlers may do some processing on the instance data (e.g. sanitizing or reformatting), so the content the user entered into the field may come back different when the form is submitted.

If such field-by-field live previews were to be supported, it would require an additional level of support from each of the widgets.