Fix titlebar pear-ctrl overlap; route status into job tray
CI / test (push) Successful in 9m53s

Reserve space for window controls and split the titlebar clusters so brand and chrome no longer collide. Replace the full-screen status spinner with lightweight activity jobs in the event tray.
This commit is contained in:
2026-07-10 21:48:11 -04:00
parent 25ba70cce8
commit 2cccb8a04e
7 changed files with 348 additions and 146 deletions
+84 -12
View File
@@ -66,17 +66,96 @@ body {
border-bottom: 1px solid var(--border-color);
backdrop-filter: blur(16px) saturate(1.4);
-webkit-backdrop-filter: blur(16px) saturate(1.4);
padding: 0 14px 0 10px;
gap: 12px;
padding: 0 12px 0 8px;
gap: 0;
display: flex;
align-items: center;
justify-content: space-between;
-webkit-app-region: drag;
overflow: visible;
z-index: 1100;
}
#titlebar > * {
-webkit-app-region: no-drag;
}
/* Left cluster: window controls + brand (never overlap) */
#titlebar .titlebar-left {
display: flex;
align-items: center;
gap: 10px;
flex: 0 1 auto;
min-width: 0;
max-width: 55%;
z-index: 2;
}
/* Pear window controls — reserve space so brand never sits under traffic lights */
#titlebar pear-ctrl {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
justify-content: flex-start;
position: relative;
z-index: 5;
line-height: 0;
min-width: 54px;
min-height: 28px;
margin: 0;
padding: 0 4px;
overflow: visible;
-webkit-app-region: no-drag;
}
#titlebar pear-ctrl[data-platform='darwin'] {
min-width: 78px;
margin: 0 8px 0 8px;
margin-top: 0 !important;
margin-left: 8px !important;
}
#titlebar pear-ctrl[data-platform='linux'],
#titlebar pear-ctrl[data-platform='win32'] {
min-width: 110px;
}
#titlebar .app-brand {
display: flex;
align-items: center;
gap: 10px;
gap: 8px;
pointer-events: none;
-webkit-app-region: no-drag;
margin-left: 8px;
margin-left: 4px;
min-width: 0;
flex-shrink: 1;
position: relative;
z-index: 1;
}
#titlebar .titlebar-right {
display: flex;
align-items: center;
gap: 10px;
flex: 0 0 auto;
margin-left: auto;
max-width: 50%;
z-index: 2;
}
#titlebar .notification-tray {
margin-left: 0;
position: relative;
flex-shrink: 0;
}
#titlebar .connection-health-badge,
#titlebar #active-peer-chip {
flex-shrink: 1;
min-width: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
#titlebar .app-brand-mark {
@@ -685,14 +764,7 @@ textarea::placeholder {
background: var(--bg-elevated);
}
#status-indicator {
background: rgba(10, 12, 16, 0.78);
}
#status-indicator .spinner-border {
border-color: var(--accent-primary);
border-right-color: transparent;
}
/* Legacy full-screen status spinner removed — activity uses #job-drawer */
/* Alerts */
#alert-container {
+35 -1
View File
@@ -4,7 +4,16 @@
*/
import { manager, Methods } from '../client/manager.js'
import { presentError, explainError } from '../client/errors.js'
import { runJob, renderJobPanel, subscribeJobs, listJobs } from '../client/jobs.js'
import {
runJob,
renderJobPanel,
subscribeJobs,
listJobs,
showActivity as jobsShowActivity,
updateActivity as jobsUpdateActivity,
completeActivity as jobsCompleteActivity,
getJob,
} from '../client/jobs.js'
import {
warmSnapshot,
clearSnapshotCache,
@@ -144,6 +153,28 @@ export function dismissJobDrawer(drawer) {
}, JOB_EXIT_ANIM_MS)
}
/** Activity helpers for uiUtils (replace full-screen spinners) */
export function showActivity(message) {
const job = jobsShowActivity(message)
showJob(job)
return job
}
export function updateActivity(message) {
const job = jobsUpdateActivity(message)
if (job) showJob(job)
return job
}
/**
* @param {boolean} [ok=true]
*/
export function completeActivity(ok = true) {
const job = jobsCompleteActivity(ok)
if (job) showJob(job)
return job
}
/**
* Deploy container with step visibility (uses deployContainer RPC).
*/
@@ -575,6 +606,9 @@ export function initOpsApp({ navigateToView, sendCommand }) {
appendLiveEvent,
dismissJobDrawer,
showJob,
showActivity,
updateActivity,
completeActivity,
explainError,
presentError: (err, method) => presentError(err, method, { showAlert, notificationManager }),
statusBadge,
+71 -34
View File
@@ -76,25 +76,89 @@
right: 0;
background: linear-gradient(180deg, var(--bg-elevated) 0%, var(--bg-tertiary) 100%);
border-bottom: 1px solid var(--border-color);
z-index: 1000;
z-index: 1100;
backdrop-filter: blur(10px);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--spacing-md);
padding: 0 12px 0 8px;
gap: 0;
overflow: visible;
}
#titlebar > * {
#titlebar > *,
#titlebar .titlebar-left,
#titlebar .titlebar-right,
#titlebar pear-ctrl,
#titlebar .app-brand,
#titlebar .notification-tray,
#titlebar .connection-health-badge,
#titlebar #active-peer-chip {
-webkit-app-region: no-drag;
}
#titlebar .notification-tray {
#titlebar .titlebar-left {
display: flex;
align-items: center;
gap: 10px;
min-width: 0;
z-index: 2;
}
#titlebar .titlebar-right {
display: flex;
align-items: center;
gap: 10px;
margin-left: auto;
flex-shrink: 0;
z-index: 2;
}
#titlebar .notification-tray {
margin-left: 0;
}
/* Window controls: keep brand clear of pear-ctrl hit targets */
#titlebar pear-ctrl {
flex: 0 0 auto;
position: relative;
z-index: 5;
display: inline-flex;
align-items: center;
justify-content: flex-start;
min-width: 54px;
min-height: 28px;
padding: 0 4px;
overflow: visible;
-webkit-app-region: no-drag;
}
#titlebar pear-ctrl[data-platform="darwin"] {
min-width: 78px;
margin: 0 8px 0 8px !important;
margin-top: 0 !important;
}
#titlebar pear-ctrl[data-platform="linux"],
#titlebar pear-ctrl[data-platform="win32"] {
min-width: 110px;
}
pear-ctrl[data-platform="darwin"] {
margin-top: 6px;
margin-left: 12px;
margin-top: 0;
margin-left: 0;
}
#titlebar .app-brand {
display: flex;
align-items: center;
gap: 8px;
margin-left: 4px;
min-width: 0;
flex-shrink: 1;
position: relative;
z-index: 1;
pointer-events: none;
}
#sidebar {
@@ -272,34 +336,7 @@
box-shadow: var(--shadow-md);
}
#status-indicator {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
align-items: center;
justify-content: center;
background: rgba(15, 17, 23, 0.85);
backdrop-filter: blur(8px);
z-index: 1050;
}
#status-indicator .spinner-border {
width: 3.5rem;
height: 3.5rem;
border-width: 0.3rem;
border-color: var(--accent-primary);
border-right-color: transparent;
}
#status-indicator p {
margin-top: var(--spacing-lg);
color: var(--text-primary);
font-size: 1.125rem;
font-weight: 500;
}
/* Legacy full-screen status spinner removed — activity uses #job-drawer */
/* Sidebar Content Styling */
#sidebar .content {