diff --git a/public/scripts/components/DrawerComponent.js b/public/scripts/components/DrawerComponent.js
index 1bcef9d..e0d171e 100644
--- a/public/scripts/components/DrawerComponent.js
+++ b/public/scripts/components/DrawerComponent.js
@@ -130,10 +130,17 @@ class DrawerComponent {
// Open drawer
this.detailsDrawer.classList.add('open');
+ // Inform terminal container that the drawer is open for alignment
+ if (this.terminalPanelContainer) {
+ this.terminalPanelContainer.classList.add('drawer-open');
+ }
}
closeDrawer() {
if (this.detailsDrawer) this.detailsDrawer.classList.remove('open');
+ if (this.terminalPanelContainer) {
+ this.terminalPanelContainer.classList.remove('drawer-open');
+ }
// Call close callback if provided
if (this.onCloseCallback) {
diff --git a/public/scripts/components/MonitoringViewComponent.js b/public/scripts/components/MonitoringViewComponent.js
index a829bd0..f0d7808 100644
--- a/public/scripts/components/MonitoringViewComponent.js
+++ b/public/scripts/components/MonitoringViewComponent.js
@@ -354,10 +354,11 @@ class MonitoringViewComponent extends Component {
return this.renderNodeCard(nodeData);
}).join('');
+ const nodeCount = nodeResources.size;
container.innerHTML = `
🖥️ Node Resource Details
-
diff --git a/public/styles/main.css b/public/styles/main.css
index 68b7ba0..7b4089c 100644
--- a/public/styles/main.css
+++ b/public/styles/main.css
@@ -3374,27 +3374,66 @@ select.param-input:focus {
inset: 0;
display: flex;
align-items: flex-end;
- justify-content: center;
+ justify-content: center; /* bottom-centered by default */
z-index: 1001;
pointer-events: none;
}
+/* When the right drawer is open, dock the terminal to the right and offset by drawer width */
+.terminal-panel-container.drawer-open {
+ /* Bottom-aligned; keep panel centered while reserving space for drawer */
+ align-items: flex-end;
+ justify-content: center;
+ /* reserve space equal to drawer width */
+ margin-right: clamp(33.333vw, 650px, 90vw);
+}
+
.terminal-panel {
- position: relative;
- width: min(720px, 90vw);
+ position: fixed; /* lock to viewport to avoid container reflow */
+ left: 50%;
+ bottom: 1.5rem;
+ width: 33.333vw; /* 1/3 of the screen by default */
height: min(45vh, 520px);
max-height: 65vh;
background: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-primary);
box-shadow: 0 18px 40px rgba(0,0,0,0.35);
- transform: translateY(32px);
+ transform: translateX(-50%);
opacity: 0;
transition: transform 0.25s ease, opacity 0.25s ease;
border-radius: 12px;
pointer-events: auto;
display: flex;
flex-direction: column;
+ z-index: 1002;
+}
+
+/* Desktop layout: terminal takes 1/3 of the screen and fills height when docked */
+@media (min-width: 1024px) {
+ .terminal-panel-container.drawer-open .terminal-panel {
+ /* Keep terminal width EXACTLY the same as non-drawer state */
+ width: 33.333vw;
+ max-width: none;
+ /* Keep terminal height consistent with non-docked state */
+ height: min(45vh, 520px);
+ max-height: 65vh;
+ border-radius: 12px;
+ /* Keep same centering transform to avoid jump */
+ }
+}
+
+/* Mobile layout: terminal spans full width */
+@media (max-width: 1023px) {
+ .terminal-panel-container {
+ margin-right: 0;
+ justify-content: center;
+ align-items: flex-end;
+ }
+ .terminal-panel {
+ width: 100vw;
+ max-width: 100vw;
+ }
}
.terminal-panel.minimized {
@@ -3402,7 +3441,7 @@ select.param-input:focus {
}
.terminal-panel.visible {
- transform: translateY(0);
+ transform: translateX(-50%);
opacity: 1;
}
@@ -4342,6 +4381,8 @@ html {
display: flex;
flex-direction: column;
gap: 1.5rem;
+ flex: 1;
+ min-height: 0;
}
/* Cluster Summary Styles */
@@ -4463,17 +4504,90 @@ html {
}
/* Nodes Monitoring Styles */
+.nodes-monitoring {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+
+.nodes-monitoring-content {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+}
+
.nodes-monitoring-content h3 {
color: var(--text-primary);
margin: 0 0 1rem 0;
font-size: 1.25rem;
font-weight: 600;
+ flex-shrink: 0;
}
.nodes-grid {
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 1rem;
+ /* Default desktop grid shows 5 items per row */
+ grid-template-columns: repeat(5, 1fr);
+ flex: 1;
+ min-height: 0;
+ overflow-y: auto;
+}
+
+/* Dynamic grid layouts based on number of items */
+.nodes-grid[data-item-count="1"] {
+ grid-template-columns: 1fr;
+ grid-template-rows: 1fr;
+ justify-items: center;
+}
+
+.nodes-grid[data-item-count="2"] {
+ grid-template-columns: repeat(2, 1fr);
+ grid-template-rows: 1fr;
+}
+
+.nodes-grid[data-item-count="3"] {
+ grid-template-columns: repeat(3, 1fr);
+ grid-template-rows: 1fr;
+}
+
+.nodes-grid[data-item-count="4"] {
+ grid-template-columns: repeat(2, 1fr);
+ grid-template-rows: repeat(2, 1fr);
+}
+
+.nodes-grid[data-item-count="5"],
+.nodes-grid[data-item-count="6"] {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+.nodes-grid[data-item-count="7"],
+.nodes-grid[data-item-count="8"] {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+.nodes-grid[data-item-count="9"] {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+.nodes-grid[data-item-count="10"],
+.nodes-grid[data-item-count="11"],
+.nodes-grid[data-item-count="12"] {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+/* For more than 12 items, use auto-fit with reasonable minimum */
+.nodes-grid[data-item-count="13"],
+.nodes-grid[data-item-count="14"],
+.nodes-grid[data-item-count="15"],
+.nodes-grid[data-item-count="16"] {
+ grid-template-columns: repeat(5, 1fr);
+}
+
+.nodes-grid[data-item-count="17"] {
+ grid-template-columns: repeat(5, 1fr);
}
.node-card {
@@ -4762,16 +4876,84 @@ html {
border-bottom: 1px solid var(--border-primary);
}
+/* Themed Scrollbars (Global and Components) */
+/* Firefox */
+* {
+ scrollbar-width: thin; /* auto | thin | none */
+ scrollbar-color: var(--border-secondary) var(--bg-tertiary); /* thumb track */
+}
+
+/* WebKit (Chrome, Edge, Safari) */
+/* Global default */
+::-webkit-scrollbar {
+ width: 10px;
+ height: 10px;
+}
+::-webkit-scrollbar-track {
+ background: var(--bg-tertiary);
+ border-radius: 8px;
+}
+::-webkit-scrollbar-thumb {
+ background: var(--border-secondary);
+ border-radius: 8px;
+ border: 2px solid var(--bg-tertiary); /* creates padding and rounded effect */
+}
+::-webkit-scrollbar-thumb:hover {
+ background: var(--border-hover);
+}
+
+/* Terminal panel body - slightly thinner */
+.terminal-body {
+ scrollbar-width: thin;
+}
+.terminal-body::-webkit-scrollbar {
+ width: 8px;
+}
+.terminal-body::-webkit-scrollbar-thumb {
+ background: var(--border-secondary);
+}
+
+/* Drawer content area */
+.details-drawer-content {
+ scrollbar-width: thin;
+}
+.details-drawer-content::-webkit-scrollbar {
+ width: 10px;
+}
+.details-drawer-content::-webkit-scrollbar-thumb {
+ background: var(--border-secondary);
+}
+
/* Responsive Design */
@media (max-width: 768px) {
.summary-stats {
grid-template-columns: 1fr;
}
- .nodes-grid {
+ /* Mobile grid layouts - simplified for smaller screens but still maximize vertical space */
+ .nodes-grid[data-item-count="1"] {
grid-template-columns: 1fr;
+ grid-template-rows: 1fr;
+ justify-items: center;
}
+ .nodes-grid[data-item-count="2"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: 1fr; }
+ .nodes-grid[data-item-count="3"],
+ .nodes-grid[data-item-count="4"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(2, 1fr); }
+ .nodes-grid[data-item-count="5"],
+ .nodes-grid[data-item-count="6"],
+ .nodes-grid[data-item-count="7"],
+ .nodes-grid[data-item-count="8"],
+ .nodes-grid[data-item-count="9"],
+ .nodes-grid[data-item-count="10"],
+ .nodes-grid[data-item-count="11"],
+ .nodes-grid[data-item-count="12"],
+ .nodes-grid[data-item-count="13"],
+ .nodes-grid[data-item-count="14"],
+ .nodes-grid[data-item-count="15"],
+ .nodes-grid[data-item-count="16"],
+ .nodes-grid[data-item-count="17"] { grid-template-columns: repeat(2, 1fr); grid-template-rows: repeat(auto-fit, 1fr); }
+
.monitoring-header {
flex-direction: column;
gap: 1rem;