The [](../reference/contrib/settings) app now allows permission over site settings to be granted on a per-site basis. This makes it possible to give non-superuser accounts full control over the configuration of an individual site. This feature was developed by Matt Westcott.
### Previews support for generic and site settings
The [](../reference/contrib/settings) app now allows previews to be enabled for generic and site setting models through `PreviewableMixin`. This makes it possible to preview your site while editing the settings. For more details, see [](enabling_previews_for_settings). This feature was developed by Sébastien Corbin and Sage Abdullah.
Image listings now support both grid and list layouts, with a simple toggle for users to switch between the two. This helps CMS users manage larger collections of images, and makes it possible to display more metadata about images in the future.
Thank you to Joel William for implementing this as part of the [Google Summer of Code program](https://wagtail.org/blog/four-contributors-for-gsoc-2025/), with support from Coen van der Kamp, Sage Abdullah, Thibaud Colas, Ben Enright.
To make it easier to navigate complex structured content, blocks created with `StructBlock` can now be collapsed and expanded like other structured block types. A common need for this is block settings, where the block supports a lot of optional fields:
attribute_name = CharBlock(blank=True, required=False, label="e.g. Mary Berry")
# Fields within the settings block will be available but hidden by default.
settings = ThemeSettingsBlock(collapsed=True)
```
For more information, see [](custom_editing_interfaces_for_structblock) and [](streamfield_block_reference). This feature was implemented by Sage Abdullah, with support from the Wagtail UI team.
The live preview and user bar features have been improved to work better in headless setups. The preview panel can now load a cross-domain headless frontend (provided by the wagtail-headless-preview package). The Wagtail user bar has been refactored into a template component, allowing it to be rendered independently and loaded by the headless frontend. Incorporating the user bar into the frontend enables features in the page editor, such as:
For more details, see the documentation on [enabling the user bar](headless_user_bar) and [accessibility checker](headless_accessibility_checker) in headless setups. This feature was developed by Sage Abdullah.
* Extract separate `background_position_x` and `background_position_y` properties from `AbstractRendition.background_position_style` (Chiemezuo Akujobi)
* Add support for translated string concatenation in the locale selector when switching between a model's language in the admin (Matt Westcott, Ellie Walsh-O'Neill)
* Add support for `preview_value` and `default` in `Block` meta options as callables for [dynamic previews within StreamField](configuring_block_previews) (Ziyao Yan, Sage Abdullah)
* Update the start project template to align with Django's recommendation to have the `django.middleware.security.SecurityMiddleware` first (Brylie Christopher Oxley)
### Deprecation of `PageListingButton`, `SnippetListingButton`, and `UserListingButton`
The `PageListingButton`, `SnippetListingButton`, and `UserListingButton` classes have been deprecated in favour of the generic `ListingButton` and `Button` classes.
The `PageListingButton` class was previously documented as part of the [`register_page_listing_buttons`](register_page_listing_buttons) hook. If you used this hook to add buttons to the page listing, you should now replace `wagtail.admin.widgets.PageListingButton` with `wagtail.admin.widgets.ListingButton`. Using the `PageListingButton` class will continue to work for now, but will raise a deprecation warning.
The `SnippetListingButton` and `UserListingButton` classes were previously documented as part of the [`register_snippet_listing_buttons`](register_snippet_listing_buttons) and [`register_user_listing_buttons`](register_user_listing_buttons) hooks, respectively. If you used these hooks to add buttons to the snippet or user listing, you should now replace `wagtail.snippets.widgets.SnippetListingButton` and `wagtail.users.widgets.UserListingButton` with one of the following:
- Use `wagtail.admin.widgets.Button` if you want the button to appear as an item inside the "More" actions dropdown in the listing.
- Use `wagtail.admin.widgets.ListingButton` if you want the button to appear as a top-level button in the listing.
Using the `SnippetListingButton` or `UserListingButton` classes will continue to work for now, but will raise a deprecation warning.
The `PageListingButton`, `SnippetListingButton`, and `UserListingButton` classes will be removed in a future release.
### Using `ListingButton` in `IndexView.get_list_more_buttons` now renders the button as a top-level button
If you have overridden the undocumented `get_list_more_buttons` method on a generic `IndexView` subclass (e.g. for a `ModelViewSet`) and used the `ListingButton` class to add buttons to the "More" actions dropdown, these buttons will now be rendered as top-level buttons in the listing. If you want the buttons to appear inside the "More" actions dropdown, you should use the `Button` class instead.
The [](init_new_page_signal) signal, previously defined in `wagtail.admin.signals`, has now been moved to `wagtail.signals`. Any import lines referencing the old location need to be updated.
### `AccessibilityItem` now accepts an `in_editor` argument
The `AccessibilityItem` user bar item now accepts an {attr}`~wagtail.admin.userbar.AccessibilityItem.in_editor` argument, which is set to `True` when it is instantiated within the page editor. If you [customized the accessibility checker](built_in_accessibility_checker), you should update your code to pass this argument when creating an instance of your `AccessibilityItem` subclass.
If you do not update your code, the `AccessibilityItem` will continue to work, but the `in_editor` argument will always be `False`. Wagtail does not currently use this argument, but it may do so in the future. It may also be utilized by users for [cross-domain headless setups](headless_accessibility_checker).
The `wagtail.telepath` module has now been moved to `wagtail.admin.telepath`, and `wagtail.widget_adapters` has been moved to `wagtail.admin.telepath.widgets`. Any import lines referencing the old locations need to be updated.
The `wagtailimages` listing view templates have been adapted to support both list and grid layout. Those adaptations should be replicated for any overrides or reuse of those templates.
### Removal of `wagtailadmin/js/telepath/telepath.js`
The JavaScript file `wagtailadmin/js/telepath/telepath.js` is no longer required, as Telepath initialization is now handled within `wagtailadmin/js/core.js`. Any templates used within the Wagtail admin should remove imports of this file; any front-end code using Telepath outside of the Wagtail admin should use the `telepath.js` supplied with [the `telepath` package](https://wagtail.github.io/telepath/) or [`telepath-unpack`](https://www.npmjs.com/package/telepath-unpack).
The frontend implementation of the Tabs component (used in `TabbedInterface` and elsewhere) has been rewritten using Stimulus.
Any existing usage of the component via the `data-tabs` attribute will no longer work. Here is a summary of the new approach.
These are subject to change and are still not officially documented, please add a thumbs up or comment to [the feature request](https://github.com/wagtail/wagtail/issues/8408) if you would like a formalised Python or JavaScript API for the Tabs component.
| Attribute | Add a class when a panel becomes active | `data-tabs-animate` (hard-coded 'animate-in' class) | `data-w-tabs-active-class="animate-in"` |
| Event | A tab is selected | `'switch'` (dispatched on the `role=tablist`, does not bubble) | `'w-tabs:selected'` (dispatched on the triggers for the tab, does bubble) |
| Event | A change to the active panel | `'wagtail:tab-changed'` (dispatched on `document`, does not bubble) | `'w-tabs:changed'` (dispatched on the tabs container, does bubble) |
For a full HTML example, install the [](styleguide) and see the tabs examples there.