/** * Adds a macOS-style traffic-light title bar to the top of the page content. * Three cases, in priority order: * 1. The Dashboard — DashboardTakeover.php renders it into a separate * #aurora-admin-dashboard-root sibling, above #wpbody (which it hides), * to fully replace the native dashboard. Gets wrapped in a new * .aurora-dashboard-frame div to match the card treatment * #wpbody-content already has everywhere else. * 2. The block editor — gets only the traffic-light controls, overlaid on * the editor frame without a full-width titlebar surface. * 3. Everything else — native WP pages and all of Aurora's own Vue pages, * since each mounts its root div inside #wpbody-content. The bar is * inserted as its first child. * * Red closes (navigates back to the Aurora dashboard). Yellow minimizes — * on any page other than the dashboard, that means "save where I am and * send me home", with SiteShell.vue's taskbar offering a way back; on the * dashboard itself (already home) it just collapses in place instead, * since there's nowhere further back to send it. Green hides Aurora's own * sidebar/toolbar so the content fills the browser window. Minimized pages * are tracked as a list (taskbar.js), not a single slot, so minimizing * more than one shows up as separate taskbar items rather than the latest * silently replacing the previous one. */ import { addMinimizedWindow, currentPageTitle } from './taskbar.js'; function buildBar(adminUrl, isDashboard) { const bar = document.createElement('div'); bar.className = 'aurora-winbar'; const makeDot = (variant, label, onClick) => { const dot = document.createElement('button'); dot.type = 'button'; dot.className = 'aurora-winbar__dot aurora-winbar__dot--' + variant; dot.setAttribute('aria-label', label); dot.title = label; dot.addEventListener('click', onClick); return dot; }; const root = document.documentElement; bar.appendChild( makeDot('close', 'Close', () => { window.location.href = adminUrl || '/wp-admin/'; }) ); bar.appendChild( makeDot('minimize', 'Minimize', () => { if (isDashboard) { root.classList.toggle('aurora-minimized'); root.classList.remove('aurora-maximized'); } else { addMinimizedWindow(currentPageTitle(), window.location.href); window.location.href = adminUrl || '/wp-admin/'; } }) ); bar.appendChild( makeDot('maximize', 'Maximize', () => { root.classList.toggle('aurora-maximized'); root.classList.remove('aurora-minimized'); }) ); return bar; } function isBlockEditorPage() { const path = window.location.pathname; return ( document.body.classList.contains('block-editor-page') || path.endsWith('/post-new.php') || path.endsWith('/post.php') ); } export function initWindowChrome(adminUrl) { if (document.querySelector('.aurora-winbar')) { return; } const dashboardRoot = document.getElementById('aurora-admin-dashboard-root'); if (dashboardRoot) { const bar = buildBar(adminUrl, true); const frame = document.createElement('div'); 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; } if (isBlockEditorPage()) { const bar = buildBar(adminUrl, false); bar.classList.add('aurora-winbar--editor'); document.body.appendChild(bar); return; } const wpbodyContent = document.getElementById('wpbody-content'); if (wpbodyContent) { const bar = buildBar(adminUrl, false); wpbodyContent.insertBefore(bar, wpbodyContent.firstChild); } }