mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-23 20:25:56 +00:00
style(portal): compact operator shell chrome
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"source_hash": "640380cc9fd2cd2036a3ac2a9f949e018d3adfb7a6953cc3aa46c8d799980740",
|
||||
"source_hash": "4b50b53b4369c0b8f2a17ddf8868a1eb8739772cb7a500616a2ba36f1449199d",
|
||||
"build_inputs": [
|
||||
"package.json",
|
||||
"tsconfig.json",
|
||||
|
||||
+26
-41
@@ -161,18 +161,14 @@ header .logout-btn:hover,
|
||||
display: block;
|
||||
}
|
||||
.portal-shell-head {
|
||||
padding: 20px 22px 18px;
|
||||
padding: 16px 22px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background:
|
||||
linear-gradient(
|
||||
180deg,
|
||||
rgba(248, 250, 252, 0.98),
|
||||
rgba(245, 248, 250, 0.96));
|
||||
background: rgba(246, 248, 251, 0.96);
|
||||
}
|
||||
.portal-shell-head-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
.portal-shell-head-kicker,
|
||||
.account-panel-kicker,
|
||||
@@ -195,24 +191,20 @@ header .logout-btn:hover,
|
||||
.intro-card p {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
line-height: 1.5;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.portal-shell-head p strong {
|
||||
color: var(--ink);
|
||||
font-weight: 700;
|
||||
}
|
||||
.portal-shell-head-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 16px;
|
||||
align-items: end;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
}
|
||||
.portal-shell-head-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
max-width: 860px;
|
||||
gap: 4px;
|
||||
max-width: 760px;
|
||||
}
|
||||
.portal-shell-head-brand-row {
|
||||
display: flex;
|
||||
@@ -222,8 +214,8 @@ header .logout-btn:hover,
|
||||
}
|
||||
.portal-shell-head-title {
|
||||
margin: 0;
|
||||
font-size: 32px;
|
||||
line-height: 0.98;
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.06em;
|
||||
font-weight: 800;
|
||||
color: var(--ink);
|
||||
@@ -241,35 +233,31 @@ header .logout-btn:hover,
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.portal-shell-head-stats {
|
||||
.portal-shell-head-summary {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
align-self: start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.portal-shell-head-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 132px;
|
||||
min-height: 0;
|
||||
padding: 10px 12px;
|
||||
.portal-shell-summary-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
font-size: 12px;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
.portal-shell-head-stat-label {
|
||||
.portal-shell-summary-pill strong {
|
||||
color: var(--ink);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: var(--ink-muted);
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.portal-shell-head-stat-value {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.04em;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.portal-command-strip,
|
||||
.intro-card,
|
||||
@@ -1796,9 +1784,6 @@ header .logout-btn:hover,
|
||||
.portal-account-bar-row {
|
||||
align-items: start;
|
||||
}
|
||||
.portal-shell-head-stats {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.workspace-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
+1
-2
@@ -1764,9 +1764,8 @@
|
||||
function renderOverviewBand(accounts) {
|
||||
var hosted = hasHostedAccounts(accounts);
|
||||
var workspaceTotal = countWorkspaces(accounts);
|
||||
var statusText = hosted ? "Hosted access is active on this account." : "No hosted workspace access is attached to this account yet.";
|
||||
var summary = hosted ? "Hosted operations, operator access, and commercial account services." : "Billing, license recovery, refunds, and privacy actions until hosted access is attached.";
|
||||
return '<section class="portal-shell-head"><div class="portal-shell-head-main"><div class="portal-shell-head-kicker">Pulse Account</div><div class="portal-shell-head-row"><div class="portal-shell-head-copy"><div class="portal-shell-head-brand-row"><h1 class="portal-shell-head-title">' + (hosted ? "Operator console" : "Account console") + '</h1><span class="portal-shell-head-chip">' + (hosted ? "Operator ready" : "Self-hosted only") + "</span></div><p><strong>" + statusText + "</strong> " + summary + '</p></div><div class="portal-shell-head-stats"><div class="portal-shell-head-stat"><span class="portal-shell-head-stat-label">Hosted access</span><span class="portal-shell-head-stat-value">' + (hosted ? "Active" : "Not attached") + '</span></div><div class="portal-shell-head-stat"><span class="portal-shell-head-stat-label">Accounts</span><span class="portal-shell-head-stat-value">' + (accounts.length === 1 ? "1 account" : String(accounts.length) + " accounts") + '</span></div><div class="portal-shell-head-stat"><span class="portal-shell-head-stat-label">Workspace fleet</span><span class="portal-shell-head-stat-value">' + (workspaceTotal ? workspaceCountLabel(workspaceTotal) : "0 workspaces") + "</span></div></div></div></div></section>";
|
||||
return '<section class="portal-shell-head"><div class="portal-shell-head-main"><div class="portal-shell-head-kicker">Pulse Account</div><div class="portal-shell-head-row"><div class="portal-shell-head-copy"><div class="portal-shell-head-brand-row"><h1 class="portal-shell-head-title">' + (hosted ? "Operator console" : "Account console") + '</h1><span class="portal-shell-head-chip">' + (hosted ? "Operator ready" : "Self-hosted only") + "</span></div><p>" + summary + '</p></div><div class="portal-shell-head-summary"><span class="portal-shell-summary-pill"><strong>Hosted access</strong>' + (hosted ? "Active" : "Not attached") + '</span><span class="portal-shell-summary-pill"><strong>Accounts</strong>' + (accounts.length === 1 ? "1 account" : String(accounts.length) + " accounts") + '</span><span class="portal-shell-summary-pill"><strong>Workspace fleet</strong>' + (workspaceTotal ? workspaceCountLabel(workspaceTotal) : "0 workspaces") + "</span></div></div></div></section>";
|
||||
}
|
||||
function renderPrimaryAccountBar(account) {
|
||||
var workspaceLabel = workspaceCountLabel((account.workspaces || []).length);
|
||||
|
||||
@@ -127,7 +127,7 @@ describe('shell view', function() {
|
||||
|
||||
expect(html).toContain('portal-shell-head-kicker">Pulse Account</div>');
|
||||
expect(html).toContain('portal-shell-head-title">Operator console</h1>');
|
||||
expect(html).toContain('Hosted access is active on this account.');
|
||||
expect(html).toContain('Hosted operations, operator access, and commercial account services.');
|
||||
expect(html).toContain('portal-shell-nav');
|
||||
expect(html).toContain('Overview');
|
||||
expect(html).toContain('Workspaces');
|
||||
@@ -198,7 +198,7 @@ describe('shell view', function() {
|
||||
expect(html).toContain('Pulse Account');
|
||||
expect(html).toContain('Self-hosted only');
|
||||
expect(html).toContain('portal-shell-head-title">Account console</h1>');
|
||||
expect(html).toContain('No hosted workspace access is attached to this account yet.');
|
||||
expect(html).toContain('Billing, license recovery, refunds, and privacy actions until hosted access is attached.');
|
||||
expect(html).toContain('Use these tools for self-hosted billing, license recovery, refunds, and privacy.');
|
||||
expect(html).toContain('Account services');
|
||||
expect(html).not.toContain('Self-hosted licenses and billing');
|
||||
|
||||
@@ -196,7 +196,6 @@ function renderAttentionPanel(workspaces: PortalWorkspaceSummary[]): string {
|
||||
function renderOverviewBand(accounts: PortalAccountSummary[]): string {
|
||||
var hosted = hasHostedAccounts(accounts);
|
||||
var workspaceTotal = countWorkspaces(accounts);
|
||||
var statusText = hosted ? 'Hosted access is active on this account.' : 'No hosted workspace access is attached to this account yet.';
|
||||
var summary = hosted
|
||||
? 'Hosted operations, operator access, and commercial account services.'
|
||||
: 'Billing, license recovery, refunds, and privacy actions until hosted access is attached.';
|
||||
@@ -211,21 +210,12 @@ function renderOverviewBand(accounts: PortalAccountSummary[]): string {
|
||||
'<h1 class="portal-shell-head-title">' + (hosted ? 'Operator console' : 'Account console') + '</h1>' +
|
||||
'<span class="portal-shell-head-chip">' + (hosted ? 'Operator ready' : 'Self-hosted only') + '</span>' +
|
||||
'</div>' +
|
||||
'<p><strong>' + statusText + '</strong> ' + summary + '</p>' +
|
||||
'<p>' + summary + '</p>' +
|
||||
'</div>' +
|
||||
'<div class="portal-shell-head-stats">' +
|
||||
'<div class="portal-shell-head-stat">' +
|
||||
'<span class="portal-shell-head-stat-label">Hosted access</span>' +
|
||||
'<span class="portal-shell-head-stat-value">' + (hosted ? 'Active' : 'Not attached') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="portal-shell-head-stat">' +
|
||||
'<span class="portal-shell-head-stat-label">Accounts</span>' +
|
||||
'<span class="portal-shell-head-stat-value">' + (accounts.length === 1 ? '1 account' : String(accounts.length) + ' accounts') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="portal-shell-head-stat">' +
|
||||
'<span class="portal-shell-head-stat-label">Workspace fleet</span>' +
|
||||
'<span class="portal-shell-head-stat-value">' + (workspaceTotal ? workspaceCountLabel(workspaceTotal) : '0 workspaces') + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="portal-shell-head-summary">' +
|
||||
'<span class="portal-shell-summary-pill"><strong>Hosted access</strong>' + (hosted ? 'Active' : 'Not attached') + '</span>' +
|
||||
'<span class="portal-shell-summary-pill"><strong>Accounts</strong>' + (accounts.length === 1 ? '1 account' : String(accounts.length) + ' accounts') + '</span>' +
|
||||
'<span class="portal-shell-summary-pill"><strong>Workspace fleet</strong>' + (workspaceTotal ? workspaceCountLabel(workspaceTotal) : '0 workspaces') + '</span>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
|
||||
@@ -159,16 +159,15 @@ header .logout-btn:hover,
|
||||
}
|
||||
|
||||
.portal-shell-head {
|
||||
padding: 20px 22px 18px;
|
||||
padding: 16px 22px 14px;
|
||||
border-bottom: 1px solid var(--line);
|
||||
background:
|
||||
linear-gradient(180deg, rgba(248, 250, 252, 0.98), rgba(245, 248, 250, 0.96));
|
||||
background: rgba(246, 248, 251, 0.96);
|
||||
}
|
||||
|
||||
.portal-shell-head-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.portal-shell-head-kicker,
|
||||
@@ -195,27 +194,22 @@ header .logout-btn:hover,
|
||||
.intro-card p {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
line-height: 1.45;
|
||||
line-height: 1.5;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.portal-shell-head p strong {
|
||||
color: var(--ink);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.portal-shell-head-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: 16px;
|
||||
align-items: end;
|
||||
gap: 14px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.portal-shell-head-copy {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
max-width: 860px;
|
||||
gap: 4px;
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
.portal-shell-head-brand-row {
|
||||
@@ -227,8 +221,8 @@ header .logout-btn:hover,
|
||||
|
||||
.portal-shell-head-title {
|
||||
margin: 0;
|
||||
font-size: 32px;
|
||||
line-height: 0.98;
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.06em;
|
||||
font-weight: 800;
|
||||
color: var(--ink);
|
||||
@@ -248,38 +242,33 @@ header .logout-btn:hover,
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.portal-shell-head-stats {
|
||||
.portal-shell-head-summary {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
align-self: start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.portal-shell-head-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
min-width: 132px;
|
||||
min-height: 0;
|
||||
padding: 10px 12px;
|
||||
.portal-shell-summary-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 32px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 12px;
|
||||
border-radius: 999px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
font-size: 12px;
|
||||
color: var(--ink-soft);
|
||||
}
|
||||
|
||||
.portal-shell-head-stat-label {
|
||||
.portal-shell-summary-pill strong {
|
||||
color: var(--ink);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: var(--ink-muted);
|
||||
letter-spacing: 0.06em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.portal-shell-head-stat-value {
|
||||
font-size: 14px;
|
||||
font-weight: 800;
|
||||
line-height: 1.25;
|
||||
letter-spacing: -0.04em;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.portal-command-strip,
|
||||
@@ -2037,10 +2026,6 @@ header .logout-btn:hover,
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.portal-shell-head-stats {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.workspace-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user