From 50d0d122e3b9e9918545a1ae30d7747abe6672d1 Mon Sep 17 00:00:00 2001
From: Mehul Gohil
Date: Tue, 11 Aug 2026 16:11:14 +0530
Subject: [PATCH 1/5] Polish settings navigation and icon hierarchy
---
assets/src/css/admin/settings.css | 188 ++++++++++++++++--
assets/src/js/admin/ActionSchedulerPanel.jsx | 17 +-
assets/src/js/admin/AdminAssetAuditPanel.jsx | 8 +-
.../js/admin/AdminPerformanceMonitorPanel.jsx | 8 +-
assets/src/js/admin/CacheStatsPanel.jsx | 16 +-
assets/src/js/admin/CronPressurePanel.jsx | 17 +-
assets/src/js/admin/DashboardPanel.jsx | 178 +++++++++++++----
assets/src/js/admin/DashboardPanel.test.jsx | 3 +-
assets/src/js/admin/DatabaseAuditPanel.jsx | 9 +-
assets/src/js/admin/PluginImpactPanel.jsx | 22 +-
assets/src/js/admin/SettingsHeader.jsx | 2 +-
assets/src/js/admin/SettingsNav.jsx | 100 ++++++++--
assets/src/js/admin/SettingsNav.test.jsx | 39 ++++
assets/src/js/admin/SiteInventoryPanel.jsx | 9 +-
.../js/admin/settings/SettingsFieldRow.jsx | 2 +-
languages/perform.pot | 2 +-
src/Includes/Helpers.php | 2 +-
17 files changed, 537 insertions(+), 85 deletions(-)
create mode 100644 assets/src/js/admin/SettingsNav.test.jsx
diff --git a/assets/src/css/admin/settings.css b/assets/src/css/admin/settings.css
index fdc8ff3..2f89994 100644
--- a/assets/src/css/admin/settings.css
+++ b/assets/src/css/admin/settings.css
@@ -1,15 +1,20 @@
.perform-settings-page {
--perform-color-brand: #0046d1;
+ --perform-color-primary: #0046d1;
--perform-color-brand-hover: #0037a8;
--perform-color-focus: #2271b1;
--perform-color-text: #1d2327;
--perform-color-text-muted: #50575e;
--perform-color-border: #dcdcde;
--perform-color-surface: #fff;
+ --perform-color-surface-subtle: #f7f8fa;
+ --perform-color-surface-accent: #f3f7ff;
--perform-color-canvas: #f0f0f1;
--perform-color-success: #008a20;
--perform-color-warning: #996800;
--perform-color-danger: #b32d2e;
+ --perform-radius-card: 10px;
+ --perform-shadow-card: 0 1px 2px rgba(16, 24, 40, 0.05), 0 1px 3px rgba(16, 24, 40, 0.08);
display: flex;
flex-direction: column;
min-height: calc(100vh - 32px);
@@ -18,6 +23,13 @@
background: var(--perform-color-surface);
}
+.perform-settings-page .perform-ui-icon {
+ flex: 0 0 auto;
+ width: 20px;
+ height: 20px;
+ stroke-width: 1.75;
+}
+
.perform-settings-page *,
.perform-settings-page *::before,
.perform-settings-page *::after {
@@ -87,8 +99,8 @@
min-height: 48px;
padding: 0 16px;
color: var(--perform-color-text-muted);
- font-size: 14px;
- font-weight: 600;
+ font-size: 13px;
+ font-weight: 500;
line-height: 1.4;
}
@@ -98,6 +110,7 @@
.perform-settings-tab-panel .components-tab-panel__tabs-item[aria-selected='true'] {
color: var(--perform-color-brand);
+ font-weight: 600;
}
.perform-settings-tab-panel .components-tab-panel__tabs-item[aria-selected='true']::after {
@@ -111,6 +124,48 @@
content: '';
}
+.perform-diagnostic-tabs {
+ display: flex;
+ gap: 4px;
+ overflow-x: auto;
+ padding: 12px clamp(20px, 3vw, 44px);
+ border-bottom: 1px solid var(--perform-color-border);
+ background: var(--perform-color-surface-subtle);
+ scrollbar-width: thin;
+}
+
+.perform-diagnostic-tabs__item {
+ flex: 0 0 auto;
+ min-height: 36px;
+ padding: 7px 12px;
+ border: 1px solid transparent;
+ border-radius: 7px;
+ color: var(--perform-color-text-muted);
+ background: transparent;
+ font-size: 12px;
+ font-weight: 500;
+ line-height: 1.4;
+ cursor: pointer;
+}
+
+.perform-diagnostic-tabs__item:hover {
+ color: var(--perform-color-text);
+ background: rgba(255, 255, 255, 0.72);
+}
+
+.perform-diagnostic-tabs__item[aria-selected='true'] {
+ border-color: var(--perform-color-border);
+ color: var(--perform-color-brand);
+ background: var(--perform-color-surface);
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
+ font-weight: 600;
+}
+
+.perform-diagnostic-tabs__item:focus-visible {
+ outline: 2px solid var(--perform-color-focus);
+ outline-offset: 1px;
+}
+
.perform-settings-tab-panel .components-tab-panel__tabs-item:focus-visible,
.perform-settings-page .components-button:focus-visible,
.perform-settings-page a:focus-visible {
@@ -278,6 +333,8 @@
.perform-savebar .components-button {
min-height: 40px;
+ font-size: 13px;
+ font-weight: 600;
}
.perform-cache-stats-container {
@@ -445,6 +502,19 @@
min-width: 0;
}
+.perform-dashboard .components-card,
+.perform-database-audit .components-card,
+.perform-site-inventory .components-card,
+.perform-admin-monitor .components-card,
+.perform-cron-pressure .components-card,
+.perform-admin-assets .components-card,
+.perform-plugin-impact .components-card,
+.perform-action-scheduler .components-card {
+ border: 1px solid var(--perform-color-border);
+ border-radius: var(--perform-radius-card);
+ box-shadow: var(--perform-shadow-card);
+}
+
.perform-dashboard-overview {
display: flex;
align-items: flex-start;
@@ -512,26 +582,68 @@
background: #f6f7f7;
}
+.perform-dashboard-stats .perform-dashboard-stat {
+ display: grid;
+ grid-template-columns: 42px minmax(0, 1fr);
+ align-items: center;
+ gap: 14px;
+ min-height: 104px;
+ padding: 16px;
+ border: 1px solid var(--perform-color-border);
+ border-left: 1px solid var(--perform-color-border);
+ border-radius: var(--perform-radius-card);
+ background: var(--perform-color-surface);
+ box-shadow: var(--perform-shadow-card);
+}
+
+.perform-dashboard-stat__icon {
+ display: inline-flex !important;
+ align-items: center;
+ justify-content: center;
+ width: 42px;
+ height: 42px;
+ border-radius: 10px;
+ color: var(--perform-color-brand) !important;
+ background: var(--perform-color-surface-accent);
+}
+
+.perform-dashboard-stat__icon[data-status='ready'] {
+ color: var(--perform-color-success) !important;
+ background: #edf8ef;
+}
+
+.perform-dashboard-stat__icon[data-status='review'] {
+ color: var(--perform-color-warning) !important;
+ background: #fff8e5;
+}
+
+.perform-dashboard-stat__content {
+ min-width: 0;
+}
+
.perform-health-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.perform-health-card {
- border-radius: 0;
- border-left: 4px solid var(--perform-color-border);
- box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
+ --perform-health-status: var(--perform-color-text-muted);
+ --perform-health-status-bg: #f1f2f3;
+ border-left: 1px solid var(--perform-color-border) !important;
}
.perform-health-card[data-status='ready'] {
- border-left-color: var(--perform-color-success);
+ --perform-health-status: var(--perform-color-success);
+ --perform-health-status-bg: #edf8ef;
}
.perform-health-card[data-status='review'] {
- border-left-color: var(--perform-color-warning);
+ --perform-health-status: var(--perform-color-warning);
+ --perform-health-status-bg: #fff8e5;
}
.perform-health-card[data-status='observe'] {
- border-left-color: var(--perform-color-brand);
+ --perform-health-status: var(--perform-color-brand);
+ --perform-health-status-bg: var(--perform-color-surface-accent);
}
.perform-health-card__heading {
@@ -547,20 +659,49 @@
line-height: 1.35;
}
-.perform-health-card__heading span {
+.perform-health-card__title {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ min-width: 0;
+}
+
+.perform-health-card__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 34px;
+ height: 34px;
+ border-radius: 8px;
+ color: var(--perform-health-status);
+ background: var(--perform-health-status-bg);
+}
+
+.perform-health-card__icon .perform-ui-icon {
+ width: 19px;
+ height: 19px;
+}
+
+.perform-health-card__status {
display: inline-flex;
flex-shrink: 0;
align-items: center;
+ gap: 5px;
min-height: 24px;
padding: 2px 8px;
border: 1px solid var(--perform-color-border);
border-radius: 12px;
- background: #f6f7f7;
- color: var(--perform-color-text-muted);
+ background: var(--perform-health-status-bg);
+ color: var(--perform-health-status);
font-size: 11px;
font-weight: 600;
}
+.perform-health-card__status .perform-ui-icon {
+ width: 14px;
+ height: 14px;
+}
+
.perform-health-card p {
min-height: 44px;
margin: 12px 0;
@@ -569,9 +710,18 @@
}
.perform-dashboard-measurement-note {
+ display: flex;
+ align-items: flex-start;
+ gap: 12px;
padding: 16px 20px;
- border-left: 4px solid var(--perform-color-brand);
- background: #f6f7f7;
+ border: 1px solid #c9d9ff;
+ border-radius: var(--perform-radius-card);
+ background: var(--perform-color-surface-accent);
+}
+
+.perform-dashboard-measurement-note > .perform-ui-icon {
+ margin-top: 1px;
+ color: var(--perform-color-brand);
}
.perform-dashboard-measurement-note p {
@@ -609,6 +759,17 @@
margin-bottom: 8px;
}
+.perform-card-heading {
+ display: flex;
+ align-items: flex-start;
+ gap: 10px;
+}
+
+.perform-card-heading > .perform-ui-icon {
+ margin-top: 1px;
+ color: var(--perform-color-brand);
+}
+
.perform-database-audit {
display: grid;
gap: 24px;
@@ -1688,6 +1849,7 @@
}
.perform-settings-tab-panel .components-tab-panel__tabs,
+ .perform-diagnostic-tabs,
.perform-settings-content,
.perform-savebar {
padding-right: 16px;
diff --git a/assets/src/js/admin/ActionSchedulerPanel.jsx b/assets/src/js/admin/ActionSchedulerPanel.jsx
index d337354..ff4bc7a 100644
--- a/assets/src/js/admin/ActionSchedulerPanel.jsx
+++ b/assets/src/js/admin/ActionSchedulerPanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
+import { ArrowPathIcon, TrashIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -133,11 +134,25 @@ const ActionSchedulerPanel = ( { initialAudit = SETTINGS.actionScheduler || {} }
onClick={ () => request( 'perform_refresh_action_scheduler_audit' ) }
disabled={ Boolean( working ) }
isBusy={ 'refresh' === working }
+ icon={
+ 'refresh' === working ? undefined : (
+
+ )
+ }
>
{ refreshLabel }
{ hasAudit && (
-
) }
diff --git a/assets/src/js/admin/AdminAssetAuditPanel.jsx b/assets/src/js/admin/AdminAssetAuditPanel.jsx
index d4f41e7..9191d73 100644
--- a/assets/src/js/admin/AdminAssetAuditPanel.jsx
+++ b/assets/src/js/admin/AdminAssetAuditPanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
+import { AdjustmentsHorizontalIcon, TrashIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -69,11 +70,16 @@ const AdminAssetAuditPanel = ( { initialSnapshot = SETTINGS.adminAssetAudit || {
onClick={ clearAudit }
disabled={ clearing || ! screens.length }
isBusy={ clearing }
+ icon={ clearing ? undefined : }
>
{ clearing ? __( 'Clearing…', 'perform' ) : __( 'Clear audit', 'perform' ) }
) : (
- onNavigate?.( 'advanced' ) }>
+ onNavigate?.( 'advanced' ) }
+ icon={ }
+ >
{ __( 'Enable in Advanced', 'perform' ) }
) }
diff --git a/assets/src/js/admin/AdminPerformanceMonitorPanel.jsx b/assets/src/js/admin/AdminPerformanceMonitorPanel.jsx
index 3fd48fd..4d687cb 100644
--- a/assets/src/js/admin/AdminPerformanceMonitorPanel.jsx
+++ b/assets/src/js/admin/AdminPerformanceMonitorPanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
+import { AdjustmentsHorizontalIcon, TrashIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -97,11 +98,16 @@ const AdminPerformanceMonitorPanel = ( { initialSnapshot = SETTINGS.adminPerform
onClick={ clearData }
disabled={ clearing || 0 === contexts.length }
isBusy={ clearing }
+ icon={ clearing ? undefined : }
>
{ clearing ? __( 'Clearing…', 'perform' ) : __( 'Clear collected data', 'perform' ) }
) : (
- onNavigate?.( 'advanced' ) }>
+ onNavigate?.( 'advanced' ) }
+ icon={ }
+ >
{ __( 'Enable in Advanced', 'perform' ) }
) }
diff --git a/assets/src/js/admin/CacheStatsPanel.jsx b/assets/src/js/admin/CacheStatsPanel.jsx
index 9f9dd91..1a90186 100644
--- a/assets/src/js/admin/CacheStatsPanel.jsx
+++ b/assets/src/js/admin/CacheStatsPanel.jsx
@@ -138,7 +138,13 @@ const CacheStatsPanel = ( { onClearSuccess = ( redirect ) => window.location.ass
: }
+ icon={
+ 'export' === activeAction ? (
+
+ ) : (
+
+ )
+ }
disabled={ isBusy }
onClick={ exportActivity }
>
@@ -149,7 +155,13 @@ const CacheStatsPanel = ( { onClearSuccess = ( redirect ) => window.location.ass
: }
+ icon={
+ 'clear' === activeAction ? (
+
+ ) : (
+
+ )
+ }
disabled={ isBusy }
onClick={ clearActivity }
>
diff --git a/assets/src/js/admin/CronPressurePanel.jsx b/assets/src/js/admin/CronPressurePanel.jsx
index df3c0cf..3f71f3a 100644
--- a/assets/src/js/admin/CronPressurePanel.jsx
+++ b/assets/src/js/admin/CronPressurePanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
+import { ArrowPathIcon, TrashIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -87,11 +88,25 @@ const CronPressurePanel = ( { initialAudit = SETTINGS.cronPressure || {} } ) =>
onClick={ () => request( 'perform_refresh_cron_pressure_audit' ) }
disabled={ Boolean( working ) }
isBusy={ 'refresh' === working }
+ icon={
+ 'refresh' === working ? undefined : (
+
+ )
+ }
>
{ refreshLabel }
{ hasAudit && (
-
+
+ )
+ }
+ >
{ 'clear' === working ? __( 'Clearing…', 'perform' ) : __( 'Clear snapshot', 'perform' ) }
) }
diff --git a/assets/src/js/admin/DashboardPanel.jsx b/assets/src/js/admin/DashboardPanel.jsx
index 9c2c4e8..ee7e789 100644
--- a/assets/src/js/admin/DashboardPanel.jsx
+++ b/assets/src/js/admin/DashboardPanel.jsx
@@ -1,5 +1,21 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { __, _n, sprintf } from '@wordpress/i18n';
+import {
+ ArrowTopRightOnSquareIcon,
+ BoltIcon,
+ CheckCircleIcon,
+ CircleStackIcon,
+ CodeBracketSquareIcon,
+ CpuChipIcon,
+ DocumentTextIcon,
+ EyeIcon,
+ ExclamationTriangleIcon,
+ InformationCircleIcon,
+ MinusCircleIcon,
+ ServerStackIcon,
+ ShoppingCartIcon,
+ Squares2X2Icon,
+} from '@heroicons/react/24/outline';
const STATUS_LABELS = {
ready: __( 'Ready', 'perform' ),
@@ -8,6 +24,22 @@ const STATUS_LABELS = {
'not-measured': __( 'Not measured', 'perform' ),
};
+const STATUS_ICONS = {
+ ready: CheckCircleIcon,
+ review: ExclamationTriangleIcon,
+ observe: EyeIcon,
+ 'not-measured': MinusCircleIcon,
+};
+
+const HEALTH_CARD_ICONS = {
+ inventory: Squares2X2Icon,
+ database: CircleStackIcon,
+ runtime: CpuChipIcon,
+ cache: BoltIcon,
+ server: ServerStackIcon,
+ store: ShoppingCartIcon,
+};
+
const formatBytes = ( bytes ) => {
const value = Number( bytes );
if ( ! Number.isFinite( value ) || value <= 0 ) {
@@ -187,28 +219,48 @@ const buildHealthCards = ( { dashboard, diagnostics, databaseAudit, siteInventor
return cards;
};
-const HealthCard = ( { card, onAction } ) => (
-
-
-
-
{ card.title }
- { STATUS_LABELS[ card.status ] || STATUS_LABELS[ 'not-measured' ] }
-
- { card.description }
- { card.action && (
- onAction( card.action ) }>
- { card.action.label }
-
- ) }
-
-
-);
+const HealthCard = ( { card, onAction } ) => {
+ const CardIcon = HEALTH_CARD_ICONS[ card.id ] || CpuChipIcon;
+ const StatusIcon = STATUS_ICONS[ card.status ] || STATUS_ICONS[ 'not-measured' ];
-const StatCard = ( { label, value, description } ) => (
+ return (
+
+
+
+
+
+
+
+
{ card.title }
+
+
+
+ { STATUS_LABELS[ card.status ] || STATUS_LABELS[ 'not-measured' ] }
+
+
+ { card.description }
+ { card.action && (
+ onAction( card.action ) }>
+ { card.action.label }
+
+ ) }
+
+
+ );
+};
+
+const StatCard = ( { label, value, description, icon: Icon, status } ) => (
-
{ label }
-
{ value }
- { description &&
{ description }
}
+ { Icon && (
+
+
+
+ ) }
+
+
{ label }
+
{ value }
+ { description &&
{ description }
}
+
);
@@ -258,10 +310,24 @@ const DashboardPanel = ( { dashboard, diagnostics, databaseAudit, siteInventory,
-
+ }
+ iconPosition="right"
+ >
{ __( 'View documentation', 'perform' ) }
-
+ }
+ iconPosition="right"
+ >
{ __( 'Get support', 'perform' ) }
@@ -272,16 +338,22 @@ const DashboardPanel = ( { dashboard, diagnostics, databaseAudit, siteInventory,
label={ __( 'Ready', 'perform' ) }
value={ readyCount }
description={ __( 'Measured local areas', 'perform' ) }
+ icon={ CheckCircleIcon }
+ status="ready"
/>
@@ -292,23 +364,32 @@ const DashboardPanel = ( { dashboard, diagnostics, databaseAudit, siteInventory,
-
{ __( 'Core Web Vitals need a separate test', 'perform' ) }
-
- { __(
- 'Local WordPress diagnostics cannot prove real-user LCP, INP, or CLS. Field data and lab testing remain separate evidence sources.',
- 'perform'
- ) }
-
+
+
+
{ __( 'Core Web Vitals need a separate test', 'perform' ) }
+
+ { __(
+ 'Local WordPress diagnostics cannot prove real-user LCP, INP, or CLS. Field data and lab testing remain separate evidence sources.',
+ 'perform'
+ ) }
+
+
-
-
{ __( 'Cache value observed', 'perform' ) }
-
- { __( 'Measured requests from this site, without estimated time savings.', 'perform' ) }
-
+
+
+
+
{ __( 'Cache value observed', 'perform' ) }
+
+ { __(
+ 'Measured requests from this site, without estimated time savings.',
+ 'perform'
+ ) }
+
+
@@ -335,11 +416,17 @@ const DashboardPanel = ( { dashboard, diagnostics, databaseAudit, siteInventory,
-
-
{ __( 'Configured asset coverage', 'perform' ) }
-
- { __( 'Configured rules only; no historical byte savings are claimed.', 'perform' ) }
-
+
+
+
+
{ __( 'Configured asset coverage', 'perform' ) }
+
+ { __(
+ 'Configured rules only; no historical byte savings are claimed.',
+ 'perform'
+ ) }
+
+
@@ -370,11 +457,14 @@ const DashboardPanel = ( { dashboard, diagnostics, databaseAudit, siteInventory,
-
-
{ __( 'What this build includes', 'perform' ) }
-
- { __( 'Evidence-bound product updates included in the current code.', 'perform' ) }
-
+
+
+
+
{ __( 'What this build includes', 'perform' ) }
+
+ { __( 'Evidence-bound product updates included in the current code.', 'perform' ) }
+
+
diff --git a/assets/src/js/admin/DashboardPanel.test.jsx b/assets/src/js/admin/DashboardPanel.test.jsx
index d9284cc..e36b940 100644
--- a/assets/src/js/admin/DashboardPanel.test.jsx
+++ b/assets/src/js/admin/DashboardPanel.test.jsx
@@ -53,7 +53,7 @@ describe( 'DashboardPanel', () => {
} );
it( 'uses measured local evidence for status and avoids an invented score', () => {
- render(
+ const { container } = render(
{
expect( screen.getByText( 'Core Web Vitals need a separate test' ) ).toBeInTheDocument();
expect( screen.getByText( /never turns these checks into an unverified speed score/i ) ).toBeInTheDocument();
expect( screen.getByText( /Response compression: needs a separate response test/ ) ).toBeInTheDocument();
+ expect( container.querySelectorAll( 'svg.perform-ui-icon[aria-hidden="true"]' ).length ).toBeGreaterThan( 8 );
} );
it( 'shows store-safety guidance only when a store pattern is measured', () => {
diff --git a/assets/src/js/admin/DatabaseAuditPanel.jsx b/assets/src/js/admin/DatabaseAuditPanel.jsx
index fabf7e6..5a54891 100644
--- a/assets/src/js/admin/DatabaseAuditPanel.jsx
+++ b/assets/src/js/admin/DatabaseAuditPanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
+import { ArrowPathIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -81,7 +82,13 @@ const DatabaseAuditPanel = ( { initialAudit = SETTINGS.databaseAudit || {} } ) =
) }
-
+ }
+ >
{ refreshLabel }
diff --git a/assets/src/js/admin/PluginImpactPanel.jsx b/assets/src/js/admin/PluginImpactPanel.jsx
index f2b30de..333e15e 100644
--- a/assets/src/js/admin/PluginImpactPanel.jsx
+++ b/assets/src/js/admin/PluginImpactPanel.jsx
@@ -1,5 +1,6 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
+import { ArrowRightIcon } from '@heroicons/react/24/outline';
const SETTINGS = window.performwpSettings || {};
@@ -8,19 +9,34 @@ const PluginImpactPanel = ( { report = SETTINGS.pluginImpact || {}, onNavigate }
const audit = report.adminAssetAudit || {};
const inventoryReady = 'ready' === report.status;
let primaryAction = (
- onNavigate?.( 'admin-assets' ) }>
+ onNavigate?.( 'admin-assets' ) }
+ icon={ }
+ iconPosition="right"
+ >
{ __( 'View admin asset evidence', 'perform' ) }
);
if ( ! inventoryReady ) {
primaryAction = (
- onNavigate?.( 'inventory' ) }>
+ onNavigate?.( 'inventory' ) }
+ icon={ }
+ iconPosition="right"
+ >
{ __( 'Generate site inventory', 'perform' ) }
);
} else if ( ! audit.enabled ) {
primaryAction = (
- onNavigate?.( 'advanced' ) }>
+ onNavigate?.( 'advanced' ) }
+ icon={ }
+ iconPosition="right"
+ >
{ __( 'Enable admin asset audit', 'perform' ) }
);
diff --git a/assets/src/js/admin/SettingsHeader.jsx b/assets/src/js/admin/SettingsHeader.jsx
index a6f7d6b..a9f8113 100644
--- a/assets/src/js/admin/SettingsHeader.jsx
+++ b/assets/src/js/admin/SettingsHeader.jsx
@@ -14,7 +14,7 @@ const SettingsHeader = () => (
href={ DOCS_URL }
target="_blank"
rel="noopener noreferrer"
- icon={ }
+ icon={ }
iconPosition="right"
>
View Documentation
diff --git a/assets/src/js/admin/SettingsNav.jsx b/assets/src/js/admin/SettingsNav.jsx
index fa2ceb3..48cea51 100644
--- a/assets/src/js/admin/SettingsNav.jsx
+++ b/assets/src/js/admin/SettingsNav.jsx
@@ -12,6 +12,16 @@ import ActionSchedulerPanel from './ActionSchedulerPanel';
import SettingsFieldRow from './settings/SettingsFieldRow';
const SETTINGS = window.performwpSettings || {};
+const DIAGNOSTIC_TAB_KEYS = [
+ 'inventory',
+ 'database',
+ 'admin-monitor',
+ 'admin-assets',
+ 'plugin-impact',
+ 'scheduled-tasks',
+ 'action-scheduler',
+ 'cache-stats',
+];
const SettingsNav = ( {
tabs: propTabs,
@@ -33,9 +43,23 @@ const SettingsNav = ( {
} ) => {
const tabs = useMemo( () => propTabs || SETTINGS.tabs || {}, [ propTabs ] );
const fields = useMemo( () => propFields || SETTINGS.fields || {}, [ propFields ] );
- const tabKeys = useMemo( () => [ 'dashboard', ...Object.keys( tabs ) ], [ tabs ] );
+ const diagnosticTabKeys = useMemo(
+ () => DIAGNOSTIC_TAB_KEYS.filter( ( slug ) => Object.prototype.hasOwnProperty.call( tabs, slug ) ),
+ [ tabs ]
+ );
+ const tabKeys = useMemo( () => {
+ const keys = [
+ 'dashboard',
+ ...Object.keys( tabs ).filter( ( slug ) => ! DIAGNOSTIC_TAB_KEYS.includes( slug ) ),
+ ];
+ if ( diagnosticTabKeys.length > 0 ) {
+ keys.push( 'diagnostics' );
+ }
+ return keys;
+ }, [ tabs, diagnosticTabKeys ] );
const [ internalActiveTab, setInternalActiveTab ] = useState( tabKeys[ 0 ] || '' );
const activeTab = propActiveTab ?? internalActiveTab;
+ const activePrimaryTab = diagnosticTabKeys.includes( activeTab ) ? 'diagnostics' : activeTab;
const onTabChange = propOnTabChange ?? setInternalActiveTab;
const [ internalFieldValues, setInternalFieldValues ] = useState( {} );
const fieldValues = propFieldValues ?? internalFieldValues;
@@ -47,18 +71,41 @@ const SettingsNav = ( {
[ id ]: value,
} ) ) );
const tabPanelRef = useRef( null );
+ const handleDiagnosticKeyDown = ( event, index ) => {
+ let nextIndex = index;
+ if ( 'ArrowRight' === event.key ) {
+ nextIndex = ( index + 1 ) % diagnosticTabKeys.length;
+ } else if ( 'ArrowLeft' === event.key ) {
+ nextIndex = ( index - 1 + diagnosticTabKeys.length ) % diagnosticTabKeys.length;
+ } else if ( 'Home' === event.key ) {
+ nextIndex = 0;
+ } else if ( 'End' === event.key ) {
+ nextIndex = diagnosticTabKeys.length - 1;
+ } else {
+ return;
+ }
+
+ event.preventDefault();
+ onTabChange( diagnosticTabKeys[ nextIndex ] );
+ event.currentTarget.parentElement?.querySelectorAll( '[role="tab"]' )[ nextIndex ]?.focus();
+ };
useEffect( () => {
const selectedTab = tabPanelRef.current?.querySelector( '[role="tab"][aria-selected="true"]' );
- selectedTab?.scrollIntoView( { block: 'nearest', inline: 'nearest' } );
+ selectedTab?.scrollIntoView?.( { block: 'nearest', inline: 'nearest' } );
}, [ activeTab ] );
const tabPanelTabs = useMemo(
() =>
- tabKeys.map( ( slug ) => ( {
- name: slug,
- title: 'dashboard' === slug ? 'Dashboard' : tabs[ slug ],
- } ) ),
+ tabKeys.map( ( slug ) => {
+ let title = tabs[ slug ];
+ if ( 'dashboard' === slug ) {
+ title = 'Dashboard';
+ } else if ( 'diagnostics' === slug ) {
+ title = 'Diagnostics';
+ }
+ return { name: slug, title };
+ } ),
[ tabKeys, tabs ]
);
@@ -69,18 +116,25 @@ const SettingsNav = ( {
return (
{
- if ( tabName !== activeTab ) {
- onTabChange( tabName );
+ let nextTab = tabName;
+ if ( 'diagnostics' === tabName ) {
+ nextTab = diagnosticTabKeys.includes( activeTab ) ? activeTab : diagnosticTabKeys[ 0 ];
+ }
+ if ( nextTab && nextTab !== activeTab ) {
+ onTabChange( nextTab );
}
} }
>
{ ( selectedTab ) => {
- const selectedTabName = selectedTab?.name || activeTab;
+ let selectedTabName = selectedTab?.name || activeTab;
+ if ( 'diagnostics' === selectedTab?.name ) {
+ selectedTabName = diagnosticTabKeys.includes( activeTab ) ? activeTab : diagnosticTabKeys[ 0 ];
+ }
const sections = fields[ selectedTabName ] || [];
let content = (
@@ -148,7 +202,29 @@ const SettingsNav = ( {
content =
;
}
- return
{ content }
;
+ return (
+ <>
+ { diagnosticTabKeys.includes( selectedTabName ) && (
+
+ { diagnosticTabKeys.map( ( slug, index ) => (
+ onTabChange( slug ) }
+ onKeyDown={ ( event ) => handleDiagnosticKeyDown( event, index ) }
+ >
+ { tabs[ slug ] }
+
+ ) ) }
+
+ ) }
+
{ content }
+ >
+ );
} }
diff --git a/assets/src/js/admin/SettingsNav.test.jsx b/assets/src/js/admin/SettingsNav.test.jsx
new file mode 100644
index 0000000..25eb877
--- /dev/null
+++ b/assets/src/js/admin/SettingsNav.test.jsx
@@ -0,0 +1,39 @@
+/* eslint-env jest */
+
+import '@testing-library/jest-dom';
+import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
+import SettingsNav from './SettingsNav';
+
+describe( 'SettingsNav', () => {
+ it( 'groups advanced diagnostics behind one primary tab and supports arrow-key navigation', async () => {
+ render(
+
+ );
+
+ expect( screen.getByRole( 'tab', { name: 'Diagnostics' } ) ).toBeInTheDocument();
+ expect( screen.queryByRole( 'tab', { name: 'Site Inventory' } ) ).not.toBeInTheDocument();
+
+ await act( async () => {
+ fireEvent.click( screen.getByRole( 'tab', { name: 'Diagnostics' } ) );
+ } );
+ const inventoryTab = screen.getByRole( 'tab', { name: 'Site Inventory' } );
+ expect( inventoryTab ).toHaveAttribute( 'aria-selected', 'true' );
+
+ inventoryTab.focus();
+ await act( async () => {
+ fireEvent.keyDown( inventoryTab, { key: 'ArrowRight' } );
+ } );
+ await waitFor( () => {
+ expect( screen.getByRole( 'tab', { name: 'Database' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ } );
+ } );
+} );
diff --git a/assets/src/js/admin/SiteInventoryPanel.jsx b/assets/src/js/admin/SiteInventoryPanel.jsx
index f479c05..600eb9e 100644
--- a/assets/src/js/admin/SiteInventoryPanel.jsx
+++ b/assets/src/js/admin/SiteInventoryPanel.jsx
@@ -1,6 +1,7 @@
import { Button, Card, CardBody, CardHeader } from '@wordpress/components';
import { useState } from '@wordpress/element';
import { __, sprintf } from '@wordpress/i18n';
+import { ArrowPathIcon } from '@heroicons/react/24/outline';
import SystemHealthPanel from './SystemHealthPanel';
const SETTINGS = window.performwpSettings || {};
@@ -105,7 +106,13 @@ const SiteInventoryPanel = ( {
) }
-
+ }
+ >
{ refreshLabel }
diff --git a/assets/src/js/admin/settings/SettingsFieldRow.jsx b/assets/src/js/admin/settings/SettingsFieldRow.jsx
index c6bc634..0853d50 100644
--- a/assets/src/js/admin/settings/SettingsFieldRow.jsx
+++ b/assets/src/js/admin/settings/SettingsFieldRow.jsx
@@ -128,7 +128,7 @@ const SettingsFieldRow = ( { field, value, onChange } ) => {
className="perform-settings-field__learn-more"
>
Learn more
-
+
) }
diff --git a/languages/perform.pot b/languages/perform.pot
index 5538ee0..21da56c 100644
--- a/languages/perform.pot
+++ b/languages/perform.pot
@@ -165,7 +165,7 @@ msgid "Remove unnecessary frontend scripts and tags that add extra requests or b
msgstr ""
#: src/Includes/Helpers.php:347
-msgid "Disable Emoji's"
+msgid "Disable Emojis"
msgstr ""
#: src/Includes/Helpers.php:348
diff --git a/src/Includes/Helpers.php b/src/Includes/Helpers.php
index 0ead8d9..819dba6 100644
--- a/src/Includes/Helpers.php
+++ b/src/Includes/Helpers.php
@@ -344,7 +344,7 @@ public static function get_settings_fields() {
[
'id' => 'disable_emojis',
'type' => 'toggle',
- 'name' => __( 'Disable Emoji\'s', 'perform' ),
+ 'name' => __( 'Disable Emojis', 'perform' ),
'desc' => __( 'Prevents WordPress from loading the emoji detection script and related styles, reducing one extra HTTP request.', 'perform' ),
'help_link' => esc_url(
add_query_arg(
From 802ee328f284d3f71e07b0ecf4195984cb2d90a3 Mon Sep 17 00:00:00 2001
From: Mehul Gohil
Date: Tue, 11 Aug 2026 16:18:38 +0530
Subject: [PATCH 2/5] Update settings smoke navigation
---
tests/e2e/perform-smoke.spec.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/e2e/perform-smoke.spec.js b/tests/e2e/perform-smoke.spec.js
index 57e64a0..937fd09 100644
--- a/tests/e2e/perform-smoke.spec.js
+++ b/tests/e2e/perform-smoke.spec.js
@@ -343,6 +343,7 @@ test( 'Cache Stats tab preserves legacy routing, actions, and keyboard access',
await login( page );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings' );
+ await page.getByRole( 'tab', { name: 'Diagnostics' } ).click();
const cacheStatsTab = page.getByRole( 'tab', { name: 'Cache Stats' } );
await cacheStatsTab.focus();
await expect( cacheStatsTab ).toBeFocused();
From f6610002d5aba358e6ccc29f64fd6c9909cd3c89 Mon Sep 17 00:00:00 2001
From: Mehul Gohil
Date: Tue, 11 Aug 2026 16:25:06 +0530
Subject: [PATCH 3/5] Restore visible diagnostic tab focus
---
assets/src/css/admin/settings.css | 1 +
1 file changed, 1 insertion(+)
diff --git a/assets/src/css/admin/settings.css b/assets/src/css/admin/settings.css
index 2f89994..9ce980e 100644
--- a/assets/src/css/admin/settings.css
+++ b/assets/src/css/admin/settings.css
@@ -161,6 +161,7 @@
font-weight: 600;
}
+.perform-diagnostic-tabs__item:focus,
.perform-diagnostic-tabs__item:focus-visible {
outline: 2px solid var(--perform-color-focus);
outline-offset: 1px;
From 11ad3270dfccee895cdc3e8376cc1884273c8387 Mon Sep 17 00:00:00 2001
From: Mehul Gohil
Date: Tue, 11 Aug 2026 19:42:45 +0530
Subject: [PATCH 4/5] Replace nested diagnostic tabs with report selector
---
assets/src/css/admin/settings.css | 101 +++++++++++++++++------
assets/src/js/admin/SettingsNav.jsx | 63 +++++++-------
assets/src/js/admin/SettingsNav.test.jsx | 17 ++--
tests/e2e/perform-smoke.spec.js | 24 +++---
4 files changed, 126 insertions(+), 79 deletions(-)
diff --git a/assets/src/css/admin/settings.css b/assets/src/css/admin/settings.css
index 9ce980e..01b0756 100644
--- a/assets/src/css/admin/settings.css
+++ b/assets/src/css/admin/settings.css
@@ -124,47 +124,83 @@
content: '';
}
-.perform-diagnostic-tabs {
+.perform-diagnostic-switcher {
display: flex;
- gap: 4px;
- overflow-x: auto;
- padding: 12px clamp(20px, 3vw, 44px);
+ align-items: center;
+ justify-content: space-between;
+ gap: 24px;
+ padding: 16px clamp(20px, 3vw, 44px);
border-bottom: 1px solid var(--perform-color-border);
background: var(--perform-color-surface-subtle);
- scrollbar-width: thin;
}
-.perform-diagnostic-tabs__item {
+.perform-diagnostic-switcher__context {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ min-width: 0;
+}
+
+.perform-diagnostic-switcher__icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
flex: 0 0 auto;
- min-height: 36px;
- padding: 7px 12px;
- border: 1px solid transparent;
- border-radius: 7px;
+ width: 40px;
+ height: 40px;
+ border: 1px solid #d7e3fb;
+ border-radius: 9px;
+ color: var(--perform-color-brand);
+ background: var(--perform-color-surface-accent);
+}
+
+.perform-diagnostic-switcher__context > span:last-child {
+ display: grid;
+ gap: 2px;
+}
+
+.perform-diagnostic-switcher__context strong {
+ font-size: 13px;
+ font-weight: 600;
+ line-height: 1.35;
+}
+
+.perform-diagnostic-switcher__context small {
color: var(--perform-color-text-muted);
- background: transparent;
font-size: 12px;
- font-weight: 500;
line-height: 1.4;
- cursor: pointer;
}
-.perform-diagnostic-tabs__item:hover {
- color: var(--perform-color-text);
- background: rgba(255, 255, 255, 0.72);
+.perform-diagnostic-switcher__control {
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ flex: 0 0 auto;
}
-.perform-diagnostic-tabs__item[aria-selected='true'] {
+.perform-diagnostic-switcher__control > span {
+ color: var(--perform-color-text-muted);
+ font-size: 12px;
+ font-weight: 600;
+}
+
+.perform-diagnostic-switcher__control select {
+ min-width: 220px;
+ height: 40px;
+ margin: 0;
border-color: var(--perform-color-border);
- color: var(--perform-color-brand);
- background: var(--perform-color-surface);
- box-shadow: 0 1px 2px rgba(16, 24, 40, 0.06);
+ border-radius: 7px;
+ color: var(--perform-color-text);
+ background-color: var(--perform-color-surface);
+ font-size: 13px;
font-weight: 600;
}
-.perform-diagnostic-tabs__item:focus,
-.perform-diagnostic-tabs__item:focus-visible {
+.perform-diagnostic-switcher__control select:focus {
+ border-color: var(--perform-color-focus);
outline: 2px solid var(--perform-color-focus);
- outline-offset: 1px;
+ outline-offset: 2px;
+ box-shadow: none;
}
.perform-settings-tab-panel .components-tab-panel__tabs-item:focus-visible,
@@ -1850,7 +1886,7 @@
}
.perform-settings-tab-panel .components-tab-panel__tabs,
- .perform-diagnostic-tabs,
+ .perform-diagnostic-switcher,
.perform-settings-content,
.perform-savebar {
padding-right: 16px;
@@ -1862,6 +1898,23 @@
padding-bottom: 40px;
}
+ .perform-diagnostic-switcher {
+ align-items: stretch;
+ flex-direction: column;
+ gap: 14px;
+ }
+
+ .perform-diagnostic-switcher__control {
+ align-items: stretch;
+ flex-direction: column;
+ gap: 6px;
+ }
+
+ .perform-diagnostic-switcher__control select {
+ width: 100%;
+ max-width: none;
+ }
+
.perform-settings-field {
grid-template-columns: minmax(0, 1fr);
gap: 16px;
diff --git a/assets/src/js/admin/SettingsNav.jsx b/assets/src/js/admin/SettingsNav.jsx
index 48cea51..a42bf99 100644
--- a/assets/src/js/admin/SettingsNav.jsx
+++ b/assets/src/js/admin/SettingsNav.jsx
@@ -1,4 +1,5 @@
import { TabPanel } from '@wordpress/components';
+import { WrenchScrewdriverIcon } from '@heroicons/react/24/outline';
import { useEffect, useMemo, useRef, useState } from '@wordpress/element';
import CacheStatsPanel from './CacheStatsPanel';
import AdminPerformanceMonitorPanel from './AdminPerformanceMonitorPanel';
@@ -71,25 +72,6 @@ const SettingsNav = ( {
[ id ]: value,
} ) ) );
const tabPanelRef = useRef( null );
- const handleDiagnosticKeyDown = ( event, index ) => {
- let nextIndex = index;
- if ( 'ArrowRight' === event.key ) {
- nextIndex = ( index + 1 ) % diagnosticTabKeys.length;
- } else if ( 'ArrowLeft' === event.key ) {
- nextIndex = ( index - 1 + diagnosticTabKeys.length ) % diagnosticTabKeys.length;
- } else if ( 'Home' === event.key ) {
- nextIndex = 0;
- } else if ( 'End' === event.key ) {
- nextIndex = diagnosticTabKeys.length - 1;
- } else {
- return;
- }
-
- event.preventDefault();
- onTabChange( diagnosticTabKeys[ nextIndex ] );
- event.currentTarget.parentElement?.querySelectorAll( '[role="tab"]' )[ nextIndex ]?.focus();
- };
-
useEffect( () => {
const selectedTab = tabPanelRef.current?.querySelector( '[role="tab"][aria-selected="true"]' );
selectedTab?.scrollIntoView?.( { block: 'nearest', inline: 'nearest' } );
@@ -205,22 +187,35 @@ const SettingsNav = ( {
return (
<>
{ diagnosticTabKeys.includes( selectedTabName ) && (
-
- { diagnosticTabKeys.map( ( slug, index ) => (
-
onTabChange( slug ) }
- onKeyDown={ ( event ) => handleDiagnosticKeyDown( event, index ) }
+
+
+
+
+
+
+ Diagnostics workspace
+ Private, local reports for this WordPress site
+
+
+
- ) ) }
-
+ { diagnosticTabKeys.map( ( slug ) => (
+
+ ) ) }
+
+
+
) }
{ content }
>
diff --git a/assets/src/js/admin/SettingsNav.test.jsx b/assets/src/js/admin/SettingsNav.test.jsx
index 25eb877..29444cd 100644
--- a/assets/src/js/admin/SettingsNav.test.jsx
+++ b/assets/src/js/admin/SettingsNav.test.jsx
@@ -1,11 +1,11 @@
/* eslint-env jest */
import '@testing-library/jest-dom';
-import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
+import { act, fireEvent, render, screen } from '@testing-library/react';
import SettingsNav from './SettingsNav';
describe( 'SettingsNav', () => {
- it( 'groups advanced diagnostics behind one primary tab and supports arrow-key navigation', async () => {
+ it( 'groups advanced diagnostics behind one primary tab and a report selector', async () => {
render(
{
await act( async () => {
fireEvent.click( screen.getByRole( 'tab', { name: 'Diagnostics' } ) );
} );
- const inventoryTab = screen.getByRole( 'tab', { name: 'Site Inventory' } );
- expect( inventoryTab ).toHaveAttribute( 'aria-selected', 'true' );
+ const reportSelector = screen.getByRole( 'combobox', { name: 'Diagnostic report' } );
+ expect( reportSelector ).toHaveValue( 'inventory' );
+ expect( screen.getByText( 'Private, local reports for this WordPress site' ) ).toBeInTheDocument();
+ expect( screen.queryByRole( 'tablist', { name: 'Diagnostic tools' } ) ).not.toBeInTheDocument();
- inventoryTab.focus();
await act( async () => {
- fireEvent.keyDown( inventoryTab, { key: 'ArrowRight' } );
- } );
- await waitFor( () => {
- expect( screen.getByRole( 'tab', { name: 'Database' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ fireEvent.change( reportSelector, { target: { value: 'database' } } );
} );
+ expect( reportSelector ).toHaveValue( 'database' );
} );
} );
diff --git a/tests/e2e/perform-smoke.spec.js b/tests/e2e/perform-smoke.spec.js
index 937fd09..383574a 100644
--- a/tests/e2e/perform-smoke.spec.js
+++ b/tests/e2e/perform-smoke.spec.js
@@ -120,7 +120,7 @@ test( 'Site Inventory refresh is private, bounded, and responsive', async ( { pa
await login( page );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=inventory' );
- await expect( page.getByRole( 'tab', { name: 'Site Inventory' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'inventory' );
await expect( page.getByText( 'Private and local' ) ).toBeVisible();
await expect( page.getByText( /no post content, option values, private URLs/i ) ).toBeVisible();
await expect( page.getByRole( 'heading', { name: 'System health' } ) ).toBeVisible();
@@ -153,7 +153,7 @@ test( 'Scheduled-task pressure is bounded, private, resettable, and responsive',
await login( page );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=scheduled-tasks' );
- await expect( page.getByRole( 'tab', { name: 'Scheduled Tasks' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'scheduled-tasks' );
await expect( page.getByText( 'Read-only and bounded' ) ).toBeVisible();
await expect( page.getByText( /excludes hook arguments, payloads, URLs, and user data/ ) ).toBeVisible();
await page.getByRole( 'button', { name: /Run check|Refresh check/ } ).click();
@@ -181,7 +181,7 @@ test( 'Action Scheduler diagnostic handles an absent queue without mutation', as
await login( page );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=action-scheduler' );
- await expect( page.getByRole( 'tab', { name: 'Action Scheduler' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'action-scheduler' );
await expect( page.getByText( 'Read-only and private' ) ).toBeVisible();
await expect( page.getByText( /never runs, cancels, or deletes queued work/ ) ).toBeVisible();
await page.getByRole( 'button', { name: /Run check|Refresh check/ } ).click();
@@ -216,7 +216,7 @@ test( 'Admin Performance Monitor is opt-in, bounded, private, clearable, and res
await page.goto( '/wp-admin/edit.php' );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=admin-monitor' );
- await expect( page.getByRole( 'tab', { name: 'Admin Monitor' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'admin-monitor' );
await expect( page.getByText( 'Aggregate-only and per site' ) ).toBeVisible();
await expect( page.getByText( /does not store full URLs, query arguments, request payloads/ ) ).toBeVisible();
await expect( page.getByText( 'edit-post' ) ).toBeVisible();
@@ -339,18 +339,18 @@ test( 'Classic menu cache stays functional across unrelated query variables', as
expect( await page.locator( '#perform-test-navigation' ).innerHTML() ).toBe( firstMarkup );
} );
-test( 'Cache Stats tab preserves legacy routing, actions, and keyboard access', async ( { page } ) => {
+test( 'Cache Stats report preserves legacy routing, actions, and keyboard access', async ( { page } ) => {
await login( page );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings' );
await page.getByRole( 'tab', { name: 'Diagnostics' } ).click();
- const cacheStatsTab = page.getByRole( 'tab', { name: 'Cache Stats' } );
- await cacheStatsTab.focus();
- await expect( cacheStatsTab ).toBeFocused();
- await expect( cacheStatsTab ).toHaveCSS( 'outline-style', 'solid' );
- await page.keyboard.press( 'Enter' );
+ const reportSelector = page.getByLabel( 'Diagnostic report' );
+ await reportSelector.focus();
+ await expect( reportSelector ).toBeFocused();
+ await expect( reportSelector ).toHaveCSS( 'outline-style', 'solid' );
+ await reportSelector.selectOption( 'cache-stats' );
- await expect( cacheStatsTab ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( reportSelector ).toHaveValue( 'cache-stats' );
await expect( page ).toHaveURL( /[?&]tab=cache-stats(?:&|$)/ );
await expect( page.getByRole( 'heading', { name: 'Perform Cache Observability' } ) ).toBeVisible();
await expect( page.getByRole( 'button', { name: 'Purge Site Page Cache' } ) ).toBeVisible();
@@ -427,7 +427,7 @@ test( 'lower-privilege users cannot access the legacy or canonical Cache Stats r
expect( canonicalResponse.status() ).not.toBe( 302 );
await expect( page ).toHaveURL( /page=perform_settings&tab=cache-stats$/ );
await expect( page.getByText( 'Sorry, you are not allowed to access this page.' ) ).toBeVisible();
- await expect( page.getByRole( 'tab', { name: 'Cache Stats' } ) ).toHaveCount( 0 );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveCount( 0 );
const protectedActions = [
[ 'perform_purge_page_cache', 'You are not allowed to purge the page cache.' ],
From 261429e98afba95e1a9e6784cb6de0b40b381144 Mon Sep 17 00:00:00 2001
From: Mehul Gohil
Date: Tue, 11 Aug 2026 19:52:37 +0530
Subject: [PATCH 5/5] Update diagnostic smoke coverage
---
tests/e2e/perform-smoke.spec.js | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/e2e/perform-smoke.spec.js b/tests/e2e/perform-smoke.spec.js
index 383574a..b15c79a 100644
--- a/tests/e2e/perform-smoke.spec.js
+++ b/tests/e2e/perform-smoke.spec.js
@@ -249,16 +249,16 @@ test( 'Admin asset audit is opt-in, bounded, private, clearable, and responsive'
const auditToggle = page.getByRole( 'checkbox', { name: 'Admin Asset Audit' } );
if ( ! ( await auditToggle.isChecked() ) ) {
await auditToggle.check();
+ await page.getByRole( 'button', { name: 'Save Settings' } ).click();
+ await expect( page.getByText( /Settings saved/ ) ).toBeVisible();
}
- await page.getByRole( 'button', { name: 'Save Settings' } ).click();
- await expect( page.getByText( /Settings saved/ ) ).toBeVisible();
await page.goto( '/wp-admin/index.php' );
await page.goto( '/wp-admin/edit.php' );
await page.goto( '/wp-admin/plugins.php' );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=admin-assets' );
- await expect( page.getByRole( 'tab', { name: 'Admin Assets' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'admin-assets' );
await expect( page.getByText( 'Inventory only — nothing is disabled' ) ).toBeVisible();
await expect( page.getByText( /URLs, query strings, nonces, and user data are not stored/ ) ).toBeVisible();
await expect( page.getByText( 'Repeated across admin screens' ) ).toBeVisible();
@@ -291,13 +291,13 @@ test( 'Plugin impact report separates measured local evidence from unavailable a
const auditToggle = page.getByRole( 'checkbox', { name: 'Admin Asset Audit' } );
if ( ! ( await auditToggle.isChecked() ) ) {
await auditToggle.check();
+ await page.getByRole( 'button', { name: 'Save Settings' } ).click();
+ await expect( page.getByText( /Settings saved/ ) ).toBeVisible();
}
- await page.getByRole( 'button', { name: 'Save Settings' } ).click();
- await expect( page.getByText( /Settings saved/ ) ).toBeVisible();
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=general' );
await openAdminPage( page, '/wp-admin/options-general.php?page=perform_settings&tab=plugin-impact' );
- await expect( page.getByRole( 'tab', { name: 'Plugin Impact' } ) ).toHaveAttribute( 'aria-selected', 'true' );
+ await expect( page.getByLabel( 'Diagnostic report' ) ).toHaveValue( 'plugin-impact' );
await expect( page.getByText( 'Evidence, not a plugin ranking' ) ).toBeVisible();
await expect( page.getByText( /does not attribute query, callback, or memory cost/ ) ).toBeVisible();
await expect( page.getByText( /Zero means not observed in this sample/ ) ).toBeVisible();