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
`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
### Fixed
+17 -1
View File
@@ -1,6 +1,6 @@
# 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
@@ -628,6 +628,22 @@ compatibility, trust), which wasn't in scope here.
## 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
`class="card"`, colliding with WP core's `.card { max-width: 520px }`.
Fixed by renaming to `.aurora-card*` everywhere. Never use unprefixed
+46
View File
@@ -1,6 +1,8 @@
<?php
namespace AuroraAdmin\Notices;
use AuroraAdmin\Pages\DashboardTakeover;
defined("ABSPATH") || exit();
/**
@@ -57,7 +59,48 @@ class Notices
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()
{
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;
$user = wp_get_current_user();
@@ -83,6 +126,9 @@ class Notices
$type = in_array($row->type, ["success", "warning", "error", "info"], true) ? $row->type : "info";
$classes = "notice notice-{$type} aurora-native-notice";
if ($keep_in_place) {
$classes .= " below-h2";
}
if ($row->dismissible) {
$classes .= " is-dismissible";
}
+4
View File
@@ -3,6 +3,7 @@ namespace AuroraAdmin\Pages;
use AuroraAdmin\Utility\Assets;
use AuroraAdmin\Options\Settings;
use AuroraAdmin\Notices\Notices;
defined("ABSPATH") || exit();
@@ -80,6 +81,9 @@ class DashboardTakeover
"settings" => Settings::get_safe(),
];
?>
<div id="aurora-admin-dashboard-notices">
<?php Notices::render_for_dashboard(); ?>
</div>
<div
id="aurora-admin-dashboard-root"
data-aurora-admin="<?php echo esc_attr(wp_json_encode($data)); ?>"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "aurora-admin-app",
"version": "2.4.1",
"version": "2.4.2",
"private": true,
"type": "module",
"scripts": {
+15
View File
@@ -376,6 +376,21 @@ html.aurora-has-taskbar #site-editor {
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
send it, so minimize just collapses the frame down to the title bar in
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';
dashboardRoot.parentNode.insertBefore(frame, dashboardRoot);
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);
return;
}
+2 -2
View File
@@ -3,7 +3,7 @@
* Plugin Name: Aurora Admin
* Plugin URI: https://aurora.co
* Description: A modern, fast WordPress admin interface.
* Version: 2.4.1
* Version: 2.4.2
* Author: Aurora
* Text Domain: aurora-admin
* Domain Path: /languages/
@@ -14,7 +14,7 @@
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_URL", plugins_url("aurora-admin/"));