Media: Add a settings dialog to the Media Library toolbar. - #12932
Media: Add a settings dialog to the Media Library toolbar.#12932t-hamano wants to merge 31 commits into
Conversation
The "Infinite Scrolling" personal option could only be reached from the user profile screen, far from the grid it affects. This adds a toggle next to the search field in the attachments browser toolbar that opens a modal dialog with that option, in both the grid and the media modal. The dialog is a native `dialog` element opened with `showModal()`, so the focus trap, the Escape handling, the backdrop and the focus restore on close come from the platform rather than from a hand-rolled implementation. Keyboard events are kept from reaching the media modal, whose own Escape handler and focus manager would otherwise fight the dialog. Toggling the checkbox saves the preference over Ajax and applies it in place: `wp.media.view.Attachments` can now bind and unbind its scroll handler after creation, and `wp.media.view.AttachmentsBrowser` swaps the Load more view in and out, so no page reload is needed. Both views now read the setting at creation time instead of capturing it when the module loads. The toggle is not rendered when a `media_library_infinite_scrolling` filter callback overrides the user preference, since the control would have no effect. Co-Authored-By: Claude <noreply@anthropic.com>
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Allows space for the media library settings toggle.
Improves experience for voice control
|
I pushed a few minor visual tweaks and changed the I noticed that the modal is not actually restricting focus, so that will need to be adjusted, but this is going in a direction that I think is viable. |
There was a problem hiding this comment.
Pull request overview
Adds a Media Library toolbar control that opens a native HTML <dialog> for editing per-user Media Library preferences (starting with infinite scrolling), and wires those preference changes through AJAX to update behavior immediately in the attachments browser.
Changes:
- Adds a toolbar “settings” toggle and
<dialog>templates for Media Library settings. - Introduces a new core AJAX action to persist the user’s infinite scrolling preference.
- Updates media views (Attachments/AttachmentsBrowser) and CSS to support toggling between infinite scrolling and “Load more” without a reload.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/wp-includes/media.php | Exposes filtered vs user preference values and passes dialog config (nonce, state) to JS. |
| src/wp-includes/media-template.php | Adds Underscore templates for the settings toggle and <dialog> UI. |
| src/wp-includes/css/media-views.css | Styles the settings toggle/dialog and adjusts load-more visibility behavior. |
| src/wp-admin/includes/ajax-actions.php | Adds wp_ajax_set_media_library_settings() handler to save the preference. |
| src/wp-admin/css/media.css | Adjusts grid toolbar layout to accommodate the new toggle in narrow viewports. |
| src/wp-admin/admin-ajax.php | Registers set-media-library-settings as a core POST AJAX action. |
| src/js/media/views/library-settings.js | Implements the toolbar control, dialog open/close behavior, and AJAX save. |
| src/js/media/views/attachments/browser.js | Listens for preference changes and swaps infinite-scroll vs load-more UI live. |
| src/js/media/views/attachments.js | Makes infinite scrolling togglable after initialization; cleans up scroll bindings. |
| src/js/_enqueues/wp/media/views.js | Registers the new LibrarySettings view in the media views bundle. |
| Gruntfile.js | Adds build mapping for the new library-settings.js file. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Ensures isFiltered compares like types when a callback returns 0/1.
Covers nonce failure, missing capability, the missing value and the stored preference.
…log from resizing
|
I believe I've addressed all the issues I could think of. We should be ready for review now. |
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
|
Pushed two changes on narrower viewports - the button position below 782px and the button size between 782px and 900px. |
joedolson
left a comment
There was a problem hiding this comment.
I have two items that I think are non-blocking changes, and can be iterated based on feedback.
| </label> | ||
| </p> | ||
| <p class="description" id="{{ data.infiniteScrollingId }}-description"><?php _e( 'Load more media items automatically when scrolling, instead of using a Load more button.' ); ?></p> | ||
| <p class="media-library-settings__status" role="status"></p> |
There was a problem hiding this comment.
The role of 'status' is equivalent to aria-live="polite", and I don't think that's quite right here. Mostly because of the extended aria-description, which means that when you toggle the control, you have to wait for the full label & description to finish reading before the status announcement occurs. For that reason, I'd be more inclined to use role="alert".
@afercia Do you have an opinion here?
| /** | ||
| * Media Library settings | ||
| */ | ||
| .wp-core-ui .button.media-library-settings__toggle { |
There was a problem hiding this comment.
Having the button visually embedded in the search field is something I'm not really sure about. It somewhat conveys the idea that this is specifically search options, rather than general media library options.
|
I don’t think this is very discoverable or well connected to the media library. As Joe notes above, it feels more about search options. I’m not comfortable right now proceeding with this, especially with where we are in the release cycle too. |
|
@annezazu Honestly, the positioning of the button is a relatively trivial part of this; relocating that is very doable. The more important part, in my opinion, is:
But I'm not convinced by the location; I think it was better when it wasn't directly inlined with the search field, however, and think it probably should be even earlier in the modal. |
… modal. Co-Authored-By: Claude <noreply@anthropic.com>
|
The button location shown in @t-hamano's message above looks good to me. The layout is similar to that in DataViews (Picker) and the media upload UX. |
|
@jasmussen I just requested review from you here but saw @fcoveram's feedback late. Thank you both! |
|
Happy to ship this as well! Thanks all. |
To be honest, I'm hesitant to make major CSS changes around the media view and media toolbar right now because the CSS is overly complex 😅 While we might refactor the media-related UI with modern CSS in the future, I don't want to do that right before the final RC release. Let's find an acceptable compromise for the 7.1 release. |
tyxla
left a comment
There was a problem hiding this comment.
Thanks for working on this @t-hamano 🙌 The feature is a nice quality-of-life win.
My main hesitation is timing rather than the code. We're at RC2, and this adds a new public JS API, a new AJAX endpoint, and runtime layout changes to one of the most-exercised screens in the admin, one that a lot of plugins hook into. The issues I highlight in review are in runtime the happy path, which makes me suspect there's more we haven't found yet.
Could we get some broad manual testing before this lands? Toggling the setting mid-session in both grid mode and the modal, across browsers, with filters and search active, and with at least one plugin that customises the media views. If that comes back clean, great. But if it feels like it needs more than a quick pass it could very well be a 7.2 item.
| $( this.options.scrollElement ).on( 'scroll', this.scroll ); | ||
|
|
||
| // The list may already be scrolled past the point where more are loaded. | ||
| this.scroll(); |
There was a problem hiding this comment.
Noting that this.scroll() never checks this.options.infiniteScrolling so if there's already a queued throttled callback or pending collection.more(), they might call scroll() again, which will run unchecked. We might want to add a this.options.infiniteScrolling check to scroll() itself.
| * @type {boolean} | ||
| */ | ||
| isFiltered: !! settings.librarySettings && | ||
| Boolean( settings.infiniteScrolling ) !== Boolean( settings.librarySettings.infiniteScrolling ), |
There was a problem hiding this comment.
Hmm, aren't we risking losing the filter precedence here? Disabling the checkbox here changes the UI to "Load More" despite the filter requiring infinite scrolling.
There was a problem hiding this comment.
Fixed in cf528d3. I made it explicit whether a filter exists using has_filter.
|
|
||
| this.setStatus( __( 'Saving…' ) ); | ||
|
|
||
| wp.ajax.post( 'set-media-library-settings', { |
There was a problem hiding this comment.
Multiple concurrent saves can result in saving the wrong value. Might need some throttling or disabling if a request is in progress here.
| view.setStatus( enabled ? | ||
| __( 'Infinite scrolling is on.' ) : | ||
| __( 'Infinite scrolling is off.' ) | ||
| ); |
There was a problem hiding this comment.
Is this yet another place that might be out of sync with isFiltered? Looks like we're not covering the case when a filter has forced that infinite scroll is "on".
There was a problem hiding this comment.
I am considering this, and I have two proposals.
- Notify that the filter is enabled when settings are updated. For example,
Setting saved. Infinite scrolling is currently controlled by a plugin or theme. - When filtered, the toggle button should not be displayed at all.
There was a problem hiding this comment.
To me, the first option is more clear.
| } | ||
|
|
||
| this.attachments.setInfiniteScrolling( enabled ); | ||
| this.$el.toggleClass( 'has-load-more', ! enabled ); |
There was a problem hiding this comment.
We might need to cover a few more items/classes based on this logic, like .more-loaded, .found-media, and .new-media for example.
| * A toolbar control opening a modal dialog with the personal options for the | ||
| * Media Library. | ||
| * | ||
| * @since 7.1.0 |
There was a problem hiding this comment.
Considering the 7.1 branch is only for bug fixes at this point, I doubt if this will make it. Should we consider it for 7.2?
There was a problem hiding this comment.
This will need to be agreed upon and decided among the release leads.
| } | ||
|
|
||
| .wp-core-ui .media-toolbar-primary > .media-library-settings__toggle { | ||
| margin-left: 8px; |
There was a problem hiding this comment.
Isn't the toggle absolute? Why use margins?
There was a problem hiding this comment.
Nice catch, this is something I forgot to remove when I absolutely positioned the toggle. Removed in cd6074a
| } | ||
|
|
||
| .wp-core-ui .mode-grid .media-toolbar-primary > .media-library-settings__toggle { | ||
| margin-left: 0; |
| this.attachments.setInfiniteScrolling( enabled ); | ||
| this.$el.toggleClass( 'has-load-more', ! enabled ); |
There was a problem hiding this comment.
Wouldn't enabling infinite scrolling in the modal always flash the spinner and fetch an extra page? Should we swap those 2 lines to address that?
…ling is off Co-Authored-By: Claude <noreply@anthropic.com>
…akes precedence Co-Authored-By: Claude <noreply@anthropic.com>
…he checkbox Co-Authored-By: Claude <noreply@anthropic.com>
…rolling Co-Authored-By: Claude <noreply@anthropic.com>
…absolutely positioned Co-Authored-By: Claude <noreply@anthropic.com>
…g so it does not fetch an extra page Co-Authored-By: Claude <noreply@anthropic.com>
|
@tyxla Thanks for the review!
I agree with this. While I understand the importance of improving accessibility, there is also a risk of causing problems by introducing new APIs. This might go against the decision, but personally I propose punting this PR to 7.2. There is too little time to prepare. |
I tested the layout changes when the Media Library Assistant plugin, which extends the media toolbar, was enabled. |
|
Test in Playground I tested PR #12932 for the first time, and I don't think it would be immediately obvious to users that they need to click the gear icon. I think the “Enable infinite scrolling” checkbox could be placed somewhere more visible and intuitive, so users can discover the setting more easily.
|
|
Coming here to say that I agree we need to punt this from the 7.1 release. I am just uncomfortable with these kinds of changes at this stage of the release process when we need utmost stability. I also think this is worthy of being considered for a point release for 7.1 and that's something we can pursue without waiting months until 7.2. |











Overview
WordPress core does not yet seem to have an API for rendering what are known as popovers. This PR instead attempts to render a settings dialog for the media library using the HTML native
dialogelement. The only concern is that this PR is the first to introduce a UI using the dialog element.New APIs
wp_ajax_set_media_library_settings()wp.media.view.LibrarySettingswp.media.view.settings.librarySettingsUse of AI Tools
Note
This PR is a prototype. Almost all of the code in this PR was generated by Claude. If we find the approach taken in this PR to be reasonable, I would like to review all of the code.
Screenshots