Fix Admin Notices not showing on the Dashboard (v2.4.2)

admin_notices fires everywhere, but prints inside #wpbody, which
DashboardTakeover hides entirely on the Dashboard (to hide the *native*
dashboard, not ours) — notices went down with it as collateral damage.
Notices::render_for_dashboard() now renders directly inside the visible
dashboard frame instead, called from DashboardTakeover::render_mount();
the normal admin_notices path bails on the Dashboard so it isn't
rendered twice.

Second, independent bug found along the way: wp-admin/js/common.js
unconditionally relocates every .notice element on the page to right
after the page's <h1>, regardless of where it was placed server-side —
without opting out, it would've silently moved our notice right back
into the hidden #wpbody. Used core's own documented `below-h2` class to
opt out, only for the dashboard render path.

Verified live: notice now shows correctly inside the dashboard frame
with proper dark styling, and dismisses correctly.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
nixpanel
2026-07-04 10:27:58 -05:00
co-authored by Claude Sonnet 5
parent 03c3c4fc89
commit d8bf1ae049
8 changed files with 110 additions and 4 deletions
+16
View File
@@ -5,6 +5,22 @@ version bump. Starts at 2.1.0 — earlier history (the theming rebuild,
window chrome/taskbar, Site Editor support, etc.) lives in `git log` and window chrome/taskbar, Site Editor support, etc.) lives in `git log` and
`PROJECT_STATUS.md`, not reconstructed here. `PROJECT_STATUS.md`, not reconstructed here.
## [2.4.2] - 2026-07-04
### Fixed
- Admin Notices only ever showed on the Aurora Dashboard — everywhere
else, `admin_notices` fired normally, but on the Dashboard specifically
the notice was invisible: `DashboardTakeover` hides `#wpbody` entirely
there (to hide the *native* dashboard, not our own), and that's exactly
where WordPress prints `admin_notices` output. Notices now render
directly inside the Aurora dashboard frame instead on that one page.
Along the way, also worked around a separate WordPress core behavior
(`common.js` unconditionally relocates every `.notice` element to right
after the page's `<h1>`) using core's own documented `below-h2` opt-out
class, since without it the notice would've just been silently moved
back into the hidden `#wpbody` by that script regardless of where it
was placed server-side.
## [2.4.1] - 2026-07-04 ## [2.4.1] - 2026-07-04
### Fixed ### Fixed
+17 -1
View File
@@ -1,6 +1,6 @@
# Aurora Admin v2 — Project Status # Aurora Admin v2 — Project Status
_Last updated: 2026-07-04 (latest session — file-integrity tamper protection for the license gate)_ _Last updated: 2026-07-04 (latest session — remaining placeholder settings wired up, dashboard scrolling and admin notices fixed)_
## What this project is ## What this project is
@@ -628,6 +628,22 @@ compatibility, trust), which wasn't in scope here.
## Key bugs fixed (root causes, in case they resurface) ## Key bugs fixed (root causes, in case they resurface)
- **Admin Notices invisible on the Dashboard**: `admin_notices` prints
inside `#wpbody`, which `DashboardTakeover::hide_native()` hides
entirely (to hide the *native* dashboard, not ours) — collateral damage
for anything else relying on that hook there. Fixed with
`Notices::render_for_dashboard()`, called directly inside the visible
dashboard frame (`DashboardTakeover::render_mount()`), with `render()`
(the normal `admin_notices` hook) bailing on the Dashboard so it isn't
rendered twice. **Second, independent bug surfaced by the same fix**:
`wp-admin/js/common.js` unconditionally relocates every `.notice`
element on the page to right after the page's `<h1>`
(`$('.notice').not('.inline, .below-h2').insertAfter($headerEnd)`) —
regardless of where it was placed server-side, it would've moved right
back into the hidden `#wpbody` on its own. Core's own `.below-h2` class
is the documented opt-out; added only for the dashboard render path
(`render_notices($keep_in_place)`), not the normal one, where the
relocation is harmless/expected.
- **`.card` global class collision**: original Dashboard cards used - **`.card` global class collision**: original Dashboard cards used
`class="card"`, colliding with WP core's `.card { max-width: 520px }`. `class="card"`, colliding with WP core's `.card { max-width: 520px }`.
Fixed by renaming to `.aurora-card*` everywhere. Never use unprefixed Fixed by renaming to `.aurora-card*` everywhere. Never use unprefixed
+46
View File
@@ -1,6 +1,8 @@
<?php <?php
namespace AuroraAdmin\Notices; namespace AuroraAdmin\Notices;
use AuroraAdmin\Pages\DashboardTakeover;
defined("ABSPATH") || exit(); defined("ABSPATH") || exit();
/** /**
@@ -57,7 +59,48 @@ class Notices
update_option(self::DB_OPTION, self::DB_VERSION); update_option(self::DB_OPTION, self::DB_VERSION);
} }
/**
* Hooked to admin_notices, which fires everywhere EXCEPT it doesn't
* actually reach the user on the Dashboard: admin_notices normally
* prints inside #wpbody, and DashboardTakeover hides #wpbody entirely
* there to hide the *native* dashboard widgets, taking custom notices
* down with it as collateral damage. render_for_dashboard() (called
* directly by DashboardTakeover, inside its own visible mount point) is
* the fix for that one case — skip the normal path here so it isn't
* rendered (invisibly) twice.
*/
public static function render() public static function render()
{
if (DashboardTakeover::is_dashboard()) {
return;
}
self::render_notices(false);
}
/**
* Called directly by DashboardTakeover::render_mount(), inside the
* visible dashboard frame, since the normal admin_notices hook never
* reaches the user there (see render()).
*/
public static function render_for_dashboard()
{
self::render_notices(true);
}
/**
* $keep_in_place matters because of a WP core behavior, not a bug of
* ours: wp-admin/js/common.js unconditionally relocates every
* `.notice`/`.updated`/`.error` element on the page to right after the
* page's <h1> ($('div.notice').not('.inline, .below-h2').insertAfter(...)),
* regardless of where it was originally placed in the DOM. On every
* other page that's harmless (it's already heading there anyway); on
* the Dashboard it silently moves our notice into the native #wpbody,
* which is hidden entirely by DashboardTakeover — invisible, not gone.
* `below-h2` is core's own documented opt-out class for exactly this
* "leave this notice exactly where I put it" case.
*/
private static function render_notices($keep_in_place)
{ {
global $wpdb; global $wpdb;
$user = wp_get_current_user(); $user = wp_get_current_user();
@@ -83,6 +126,9 @@ class Notices
$type = in_array($row->type, ["success", "warning", "error", "info"], true) ? $row->type : "info"; $type = in_array($row->type, ["success", "warning", "error", "info"], true) ? $row->type : "info";
$classes = "notice notice-{$type} aurora-native-notice"; $classes = "notice notice-{$type} aurora-native-notice";
if ($keep_in_place) {
$classes .= " below-h2";
}
if ($row->dismissible) { if ($row->dismissible) {
$classes .= " is-dismissible"; $classes .= " is-dismissible";
} }
+4
View File
@@ -3,6 +3,7 @@ namespace AuroraAdmin\Pages;
use AuroraAdmin\Utility\Assets; use AuroraAdmin\Utility\Assets;
use AuroraAdmin\Options\Settings; use AuroraAdmin\Options\Settings;
use AuroraAdmin\Notices\Notices;
defined("ABSPATH") || exit(); defined("ABSPATH") || exit();
@@ -80,6 +81,9 @@ class DashboardTakeover
"settings" => Settings::get_safe(), "settings" => Settings::get_safe(),
]; ];
?> ?>
<div id="aurora-admin-dashboard-notices">
<?php Notices::render_for_dashboard(); ?>
</div>
<div <div
id="aurora-admin-dashboard-root" id="aurora-admin-dashboard-root"
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>" data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "aurora-admin-app", "name": "aurora-admin-app",
"version": "2.4.1", "version": "2.4.2",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {
+15
View File
@@ -376,6 +376,21 @@ html.aurora-has-taskbar #site-editor {
border-top-right-radius: var(--aurora-radius-lg); border-top-right-radius: var(--aurora-radius-lg);
} }
/* Custom admin notices (Notices::render_for_dashboard(), reparented in
here by windowChrome.js) — native-dark.css already themes .notice
elsewhere via #wpbody-content, but that stylesheet isn't loaded on the
Dashboard at all (Shell::is_own_page() treats index.php as one of
Aurora's own pages), so it needs its own copy of the same treatment
here instead. */
#aurora-admin-dashboard-notices:empty {
display: none;
}
#aurora-admin-dashboard-notices .notice {
background: var(--aurora-card-bg);
color: var(--aurora-text);
margin: 16px 20px 0;
}
/* Yellow dot: on the Dashboard itself there's nowhere further "home" to /* Yellow dot: on the Dashboard itself there's nowhere further "home" to
send it, so minimize just collapses the frame down to the title bar in send it, so minimize just collapses the frame down to the title bar in
place — everywhere else, minimize navigates to the dashboard instead place — everywhere else, minimize navigates to the dashboard instead
+9
View File
@@ -87,6 +87,15 @@ export function initWindowChrome(adminUrl) {
frame.className = 'aurora-dashboard-frame'; frame.className = 'aurora-dashboard-frame';
dashboardRoot.parentNode.insertBefore(frame, dashboardRoot); dashboardRoot.parentNode.insertBefore(frame, dashboardRoot);
frame.appendChild(bar); frame.appendChild(bar);
// Custom admin notices (Notices::render_for_dashboard(), printed as a
// sibling right before the mount point) — reparented into the frame
// here too, so they render as part of the dashboard's own card
// instead of sitting outside it unstyled. Normally these reach the
// user via the plain admin_notices hook, but that renders inside
// #wpbody, which the Dashboard hides entirely to hide the *native*
// dashboard widgets — this is the replacement path for that one page.
const notices = document.getElementById('aurora-admin-dashboard-notices');
if (notices) frame.appendChild(notices);
frame.appendChild(dashboardRoot); frame.appendChild(dashboardRoot);
return; return;
} }
+2 -2
View File
@@ -3,7 +3,7 @@
* Plugin Name: Aurora Admin * Plugin Name: Aurora Admin
* Plugin URI: https://aurora.co * Plugin URI: https://aurora.co
* Description: A modern, fast WordPress admin interface. * Description: A modern, fast WordPress admin interface.
* Version: 2.4.1 * Version: 2.4.2
* Author: Aurora * Author: Aurora
* Text Domain: aurora-admin * Text Domain: aurora-admin
* Domain Path: /languages/ * Domain Path: /languages/
@@ -14,7 +14,7 @@
defined("ABSPATH") || exit(); defined("ABSPATH") || exit();
define("AURORA_ADMIN_VERSION", "2.4.1"); define("AURORA_ADMIN_VERSION", "2.4.2");
define("AURORA_ADMIN_PATH", plugin_dir_path(__FILE__)); define("AURORA_ADMIN_PATH", plugin_dir_path(__FILE__));
define("AURORA_ADMIN_URL", plugins_url("aurora-admin/")); define("AURORA_ADMIN_URL", plugins_url("aurora-admin/"));