This commit is contained in:
Mateusz Gruszczyński committed 2026-11-09 11:42:46 +01:00
1 parent 992a1795af
commit b9d716d260
3 files changed
+105 -9

No files matched your search

+7 -2
View File
@@ -79,7 +79,8 @@ window.rustProxyInlineLayout = (() => {
const explicit = draft.heights?.[node.dataset.dashboardWidget] !== undefined;
const heightValue = node.querySelector(".overview-inline-height-value");
if (heightValue) {
heightValue.textContent = `↕${rows.span}${explicit ? "" : " A"}`;
heightValue.textContent = `↕${rows.span}`;
heightValue.classList.toggle("is-auto", !explicit);
heightValue.title = explicit ? t("overviewLayoutHeightFixed") : t("overviewLayoutHeightAuto");
}
const lower = node.querySelector(".overview-inline-lower");
@@ -161,7 +162,9 @@ window.rustProxyInlineLayout = (() => {
control("−", `${t("overviewLayoutLower")}: ${title}`, "overview-inline-lower", () => resizeHeight(id, -1)),
heightValue,
control("+", `${t("overviewLayoutTaller")}: ${title}`, "overview-inline-taller", () => resizeHeight(id, 1)));
bar.append(grip, dashboardWidgetTypeBadge(id), sizeControls, heightControls,
const name = el("span", title, "overview-inline-name");
name.title = title;
bar.append(grip, name, dashboardWidgetTypeBadge(id), sizeControls, heightControls,
control("←", `${t("moveUp")}: ${title}`, "overview-inline-up", () => nudge(id, -1)),
control("→", `${t("moveDown")}: ${title}`, "overview-inline-down", () => nudge(id, 1)),
control("×", `${t("overviewLayoutInlineHide")}: ${title}`, "overview-inline-hide", () => hide(id)));
@@ -197,6 +200,8 @@ window.rustProxyInlineLayout = (() => {
if (modalButton) modalButton.disabled = false;
if (!preserveSaved && original) applyDashboardLayout(original.order, [...original.hidden], original.sizes, original.heights);
draft = original = null;
// Recompute from scratch so the saved view is exactly what was arranged.
window.rustProxyOverviewRows?.flush?.();
}
async function begin() {
if (draft || opening || saving || $("overview-presets-dialog")?.open) return;
+6 -1
View File
@@ -35,12 +35,17 @@ window.rustProxyOverviewRows = (() => {
lastWidth = grid.clientWidth;
const items = cards().filter(node => !node.hidden && node.getClientRects().length);
if (!items.length) return;
grid.classList.add("is-measuring-rows");
// Measure as the saved (locked) dashboard: editing styles move a few
// controls inside cards, which must not change the layout being edited.
const editing = grid.classList.contains("is-unlocked");
if (editing) grid.classList.remove("is-unlocked");
grid.classList.add("has-row-units", "is-measuring-rows");
// Bounding boxes include CSS zoom (Settings → Interface scale); grid tracks,
// gaps and the row unit are in CSS pixels, so divide measurements by it.
const zoom = zoomOf();
const natural = items.map(node => node.getBoundingClientRect().height / zoom);
grid.classList.remove("is-measuring-rows");
if (editing) grid.classList.add("is-unlocked");
const gap = parseFloat(getComputedStyle(grid).rowGap) || 0;
const isStat = node => node.classList.contains("stat");
// The unit is half of the smallest stat card, so every card ends within a
+92 -6
View File
@@ -604,7 +604,7 @@ html[data-dashboard-density=ultra] #panel-overview .stat-cache-outcomes .cache-m
color: var(--text);
}
#panel-overview .dashboard-overview-grid.is-unlocked .stat-with-action .stat-corner-action {
#panel-overview .dashboard-overview-grid.is-unlocked:not(.has-row-units) .stat-with-action .stat-corner-action {
top: 44px;
}
@@ -626,7 +626,7 @@ html[data-dashboard-density=ultra] #panel-overview .stat-cache-outcomes .cache-m
white-space: nowrap;
}
#panel-overview .dashboard-overview-grid.is-unlocked .backend-latency-stat .backend-health-origins {
#panel-overview .dashboard-overview-grid.is-unlocked:not(.has-row-units) .backend-latency-stat .backend-health-origins {
top: 44px;
}
@@ -1243,9 +1243,95 @@ html[data-chart-style] :is(#workspace, dialog) svg polyline {
position: relative;
outline: 1px dashed var(--accent);
outline-offset: -2px;
}
/* Legacy grouped layout: reserve room for the editing toolbar. With row units the
toolbar overlays the card header instead, so the unlocked grid has exactly the
geometry of the saved one (what you arrange is what you get). */
#panel-overview .dashboard-overview-grid.is-unlocked:not(.has-row-units)>[data-dashboard-widget] {
padding-top: 40px !important;
}
/* Row-unit editing toolbar: a slim opaque header (handle, card name, hide) that
expands to a second line with width / height / move controls on hover or focus. */
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-toolbar {
top: 2px;
left: 2px;
right: 2px;
flex-wrap: wrap;
align-items: center;
gap: 3px;
padding: 3px;
overflow: visible;
background: var(--panel2, var(--panel));
border-bottom: 1px solid var(--line);
border-radius: var(--rp-radius-control, 0);
box-shadow: 0 4px 10px var(--shadow-mid, #0006);
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-toolbar button {
min-width: 22px;
min-height: 22px;
padding: 1px 5px;
font-size: 11px;
}
#panel-overview .overview-inline-name {
display: none;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-name {
display: block;
flex: 1 1 0;
min-width: 0;
overflow: hidden;
color: var(--text);
font: 600 11px var(--sans);
text-overflow: ellipsis;
white-space: nowrap;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-toolbar .overview-inline-hide {
order: 1;
margin-left: 0;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-toolbar :is(.overview-widget-type, .overview-inline-width, .overview-inline-up, .overview-inline-down) {
display: none;
order: 2;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units>[data-dashboard-widget]:is(:hover, :focus-within) .overview-inline-toolbar :is(.overview-inline-width, .overview-inline-up, .overview-inline-down) {
display: inline-flex;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units>[data-dashboard-widget]:is(:hover, :focus-within) .overview-inline-toolbar::after {
content: "";
order: 1;
flex-basis: 100%;
height: 0;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units>[data-dashboard-widget]:is(:hover, :focus-within) .overview-inline-toolbar .overview-inline-height[hidden] {
display: none;
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-width-value {
min-width: 28px;
font-size: 10px;
}
/* Automatic height (fits the content) is shown muted; a fixed height in full colour. */
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-height-value.is-auto {
color: var(--muted);
}
#panel-overview .dashboard-overview-grid.is-unlocked.has-row-units .overview-inline-width + .overview-inline-width {
margin-left: 4px;
padding-left: 6px;
border-left: 1px solid var(--line);
}
#panel-overview .dashboard-overview-grid.is-unlocked>[data-dashboard-widget]:hover,
#panel-overview .dashboard-overview-grid.is-unlocked>[data-dashboard-widget]:focus-within {
outline-style: solid;
@@ -2391,7 +2477,7 @@ html[data-dashboard-density] #panel-overview .stat :is(.stat-chart-legend, .over
/* Compact stat cards: a card made only of title, value and one secondary line shows that line
beside the value (right-aligned) instead of on a line of its own. */
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small))):has(>small)) {
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small, .overview-inline-toolbar))):has(>small)) {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
column-gap: 10px;
@@ -2399,16 +2485,16 @@ html[data-dashboard-density] #panel-overview .stat :is(.stat-chart-legend, .over
align-content: start;
}
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small))):has(>small))>span:first-child {
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small, .overview-inline-toolbar))):has(>small))>span:first-child {
grid-column: 1 / -1;
}
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small))):has(>small))>strong {
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small, .overview-inline-toolbar))):has(>small))>strong {
grid-column: 1;
min-width: 0;
}
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small))):has(>small))>small {
#panel-overview .stats-grid>.stat:is(:not(.stat-donut, .stat-meter, .stat-with-action, .stat-chart):not(:has(>:not(span, strong, small, .overview-inline-toolbar))):has(>small))>small {
grid-column: 2;
max-width: 14em;
margin: 0;