Admin UI

Last updatedView as Markdown

The Mantle admin interface is a single-page React application mounted on one WordPress admin page. Routing is query-parameter based and driven entirely by a filtered array of tab objects, so adding a view never means editing a switch statement.

Rendering pipeline

Flow

From URL to rendered view

7 relationships
Layouts decides the shell; ViewWrapper resolves and renders the view.
Reference

The four moving parts

4 fields
src/constants/routes.js string
Declares the core TABS object and the helper functions that resolve tabs from an ID, a path, or the query string. Applies the mantle.navigation_tabs filter.
src/components/ViewWrapper.js string
Reads the view query parameter, resolves the tab, and renders its component inside a Card whose heading is the tab title.
src/layouts/index.js string
Loads settings and setup data, decides between DashboardLayout and SetupLayout, and shows a loading state while fetching.
src/modules/*/register.js string
Where each module adds its tab via the filter and its panel via a SlotFill.

Core tabs

TABS in src/constants/routes.js declares only two entries. Everything else arrives through the filter.

javascript src/constants/routes.js
export const TABS = {	DASHBOARD: {		id: 'dashboard',		path: '/dashboard',		title: __( 'Dashboard', 'mantle' ),		component: Dashboard,		icon: DashboardIcon,		order: 10,		requiredCapability: 'mantle_view_dashboard',	},	SETTINGS: {		id: 'settings',		path: '/settings',		title: __( 'Settings', 'mantle' ),		component: Settings,		icon: SettingsIcon,		order: 100,		requiredCapability: 'mantle_edit_settings',	},};export const getTabs = () => {	const filteredTabs = Object.values( TABS );	return applyFilters( 'mantle.navigation_tabs', filteredTabs );};
Verbatim structure from src/constants/routes.js.

Route resolution helpers

routes.js exports several resolvers. All of them call getTabs() internally, so they see filtered tabs including third-party ones.

Reference

Exported helpers

From src/constants/routes.js.
8 fields
getTabs() array
Returns the filtered array of tab objects.
getTabIdFromQuery(url?) string
Reads the view query parameter and validates it against the tabs. Falls back to the Dashboard ID when absent or unrecognised.
getTabIdFromLocation(location) string
Resolves a tab from a React Router location’s first path segment.
getTabIdFromPath(path) string
Resolves a tab ID from a path such as /settings.
getPathFromTabId(tabId) string
The inverse: path for a given tab ID.
updateRouteQuery(tabId, replace?) any
Pushes or replaces history state. Deletes the view parameter entirely for the Dashboard tab, since it is the default.
getViewComponent(viewId) any
Returns the component for a tab ID, or null.
getDefaultViewComponent() any
Always returns the Dashboard component.

Dashboard is special-cased in updateRouteQuery(): navigating to it removes the view parameter instead of setting view=dashboard, keeping the canonical URL clean.

Settings subtabs

The Settings view has its own nested tab system, filtered separately and gated by module state.

Flow

Settings subtab resolution

6 relationships
A subtab named after a module ID is hidden automatically when that module is inactive.

The filter receives a second argument of { settings, modules }, so a callback can decide what to add based on current state rather than relying on the automatic gating.

Capability gating is presentational

requiredCapability controls whether a tab is shown. It does not protect anything.

Data layer

The admin app reads and writes through WordPress data stores in src/stores/, and the Settings view consumes a useMantleSettings() hook that exposes settings, modules, invalidate, and saveSite. Preloaded REST responses are supplied from PHP through the mantle_admin_preload_paths filter, so the first render does not wait on network requests.

Reference

PHP filters that shape the admin app

Applied in Controller\Admin.
4 fields
mantle_admin_data array
The data object handed to the JavaScript application, including REST paths.
mantle_admin_preload_paths array
REST paths preloaded into the page so the first render is instant. Add your module’s route here.
mantle_admin_strings array
Localised strings passed to the application.
mantle.admin_submenus array
WordPress admin submenu entries. Abstract_Module::init() hooks each enabled module’s add_menu_item() into this.

Stale documentation warning

See also

Have a question about this page?

Linchpin assistant

Was this helpful?