Split the resource tooltip into aligned production and consumption lines
This commit is contained in:
@@ -1362,6 +1362,24 @@ input:focus, select:focus { border-color: var(--accent); }
|
||||
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.6);
|
||||
}
|
||||
|
||||
/* A resource chip's tooltip: production above consumption, each row
|
||||
right-aligned. One grid holds both rows so the sign and figure columns line
|
||||
up; the figure column reserves the width of the largest pool figure
|
||||
(99 999 999 999), so the bubble never shifts as a stock moves. */
|
||||
.resource-tip {
|
||||
display: grid;
|
||||
grid-template-columns: auto auto auto;
|
||||
justify-content: end;
|
||||
column-gap: 0.35em;
|
||||
row-gap: 2px;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
.resource-tip .rt-sign { text-align: right; font-weight: 700; }
|
||||
.resource-tip .rt-figure { text-align: right; min-width: 14ch; }
|
||||
.resource-tip .rt-tail { text-align: left; }
|
||||
.resource-tip .rt-sign.produce, .resource-tip .rt-figure.produce { color: #6ee787; }
|
||||
.resource-tip .rt-sign.consume, .resource-tip .rt-figure.consume { color: #f27272; }
|
||||
|
||||
/* Right-click menu for the units sharing a tile. */
|
||||
.stack-menu {
|
||||
position: absolute;
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
// Generated by scripts/generate-devlog.js from `git log`; do not edit.
|
||||
// The pre-commit hook refreshes it so the main menu shows the latest commits.
|
||||
export const DEVLOG = [
|
||||
{
|
||||
"hash": "0a1c2d0",
|
||||
"date": "2026-09-25",
|
||||
"subject": "Guaranteed the 45-second starter build even on an unpowered map",
|
||||
"body": ""
|
||||
},
|
||||
{
|
||||
"hash": "80d2e22",
|
||||
"date": "2026-09-25",
|
||||
@@ -54,11 +60,5 @@ export const DEVLOG = [
|
||||
"date": "2026-09-24",
|
||||
"subject": "Grouped the unit stack by type and let ranged units pick a target",
|
||||
"body": ""
|
||||
},
|
||||
{
|
||||
"hash": "1c6f0ae",
|
||||
"date": "2026-09-24",
|
||||
"subject": "Cut the per-broadcast and per-frame cost on a full-sized map",
|
||||
"body": "The server sent the whole army on every snapshot and the client re-cloned\nthe whole icon layer whenever a unit moved, so a settled world with a\nstanding army drained the broadcast loop and the frame loop alike.\n\n- Ship only the units and city list that changed, keyed by a per-peer\n fingerprint and a serialised hash, and merge those deltas on the client.\n- Memoise the battlefield scan on a battle version bumped when a unit\n joins, leaves or changes side.\n- Skip the DOM writes for units whose snapshot object is unchanged, and\n cache the unit-view inner nodes.\n- Fold units, cities and tile markers onto the nearest world copy instead\n of mirroring the icon layers, which re-cloned thousands of views every\n frame; the small decoration layers still mirror, and only on a change.\n\nFrame work at full zoom-out with units moving fell from ~190ms to ~6.5ms."
|
||||
}
|
||||
];
|
||||
|
||||
@@ -163,11 +163,13 @@ export const panelMethods = {
|
||||
},
|
||||
|
||||
// A small hover tooltip anchored above a stat, fed by its data-tooltip text.
|
||||
// A top-panel resource chip is the exception: its tooltip is a two-line bill,
|
||||
// production above consumption, both right-aligned.
|
||||
_showStatTooltip($stat) {
|
||||
const text = $stat.attr("data-tooltip");
|
||||
if (!text) return;
|
||||
const content = this._statTooltipContent($stat);
|
||||
if (content === null) return;
|
||||
this._hoveredStat = $stat;
|
||||
this.$statTooltip.text(text).removeClass("hidden");
|
||||
this.$statTooltip.empty().append(content).removeClass("hidden");
|
||||
const offset = $stat.offset() || { left: 0, top: 0 };
|
||||
const width = this.$statTooltip.outerWidth() || 0;
|
||||
const height = this.$statTooltip.outerHeight() || 0;
|
||||
@@ -177,6 +179,50 @@ export const panelMethods = {
|
||||
});
|
||||
},
|
||||
|
||||
// The body of a stat tooltip: the resource bill for a pool chip, or the plain
|
||||
// text another stat carries. Null means the stat has no tooltip.
|
||||
_statTooltipContent($stat) {
|
||||
if ($stat.hasClass("top-resource")) {
|
||||
const proto = resourceById($stat.attr("data-resource"));
|
||||
const unit = proto ? proto.unit : "";
|
||||
return this._resourceTooltip(
|
||||
Number($stat.attr("data-produced")) || 0,
|
||||
Number($stat.attr("data-consumed")) || 0,
|
||||
unit
|
||||
);
|
||||
}
|
||||
const text = $stat.attr("data-tooltip");
|
||||
return text ? document.createTextNode(text) : null;
|
||||
},
|
||||
|
||||
// A resource's daily flows as two right-aligned rows: production first with a
|
||||
// plus, consumption second with a minus. One grid holds both rows, so the sign
|
||||
// and figure columns line up; the figure column reserves room for the largest
|
||||
// pool figure (99 999 999 999), so the bubble never shifts width as a stock
|
||||
// moves.
|
||||
_resourceTooltip(produced, consumed, unit) {
|
||||
const $tip = $("<div class='resource-tip'></div>");
|
||||
for (const row of [
|
||||
{ cls: "produce", sign: "+", amount: produced },
|
||||
{ cls: "consume", sign: "−", amount: consumed },
|
||||
]) {
|
||||
$tip.append(
|
||||
$("<span class='rt-sign'></span>").addClass(row.cls).text(row.sign),
|
||||
$("<span class='rt-figure'></span>").addClass(row.cls).text(groupDigits(row.amount)),
|
||||
$("<span class='rt-tail'></span>").addClass(row.cls).text(`${unit}/day`)
|
||||
);
|
||||
}
|
||||
return $tip;
|
||||
},
|
||||
|
||||
// Rebuilds the open stat tooltip in place, so a snapshot that changes the
|
||||
// figures under the pointer does not leave a stale bubble.
|
||||
_refreshStatTooltip() {
|
||||
if (!this._hoveredStat || this.$statTooltip.hasClass("hidden")) return;
|
||||
const content = this._statTooltipContent(this._hoveredStat);
|
||||
if (content !== null) this.$statTooltip.empty().append(content);
|
||||
},
|
||||
|
||||
_hideStatTooltip() {
|
||||
this._hoveredStat = null;
|
||||
this.$statTooltip.addClass("hidden");
|
||||
@@ -917,11 +963,9 @@ export const panelMethods = {
|
||||
if (Math.abs(net) <= 0.5) $arrow.text("=").addClass("equal");
|
||||
else $arrow.text(net > 0 ? "▲" : "▼").addClass(net > 0 ? "up" : "down");
|
||||
$value.after($arrow);
|
||||
$chip.attr(
|
||||
"data-tooltip",
|
||||
`Produced ${formatResourceAmount(id, made)}/day · ` +
|
||||
`Consumed ${formatResourceAmount(id, used)}/day`
|
||||
);
|
||||
// The hover tooltip pairs the two flows; the raw figures ride on the chip
|
||||
// so an open tooltip can be rebuilt in step with the next snapshot.
|
||||
$chip.attr("data-produced", made).attr("data-consumed", used);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -976,10 +1020,7 @@ export const panelMethods = {
|
||||
0.005
|
||||
);
|
||||
// Keep an open stat tooltip in step with the figures it describes.
|
||||
if (this._hoveredStat && !this.$statTooltip.hasClass("hidden")) {
|
||||
const text = this._hoveredStat.attr("data-tooltip");
|
||||
if (text) this.$statTooltip.text(text);
|
||||
}
|
||||
this._refreshStatTooltip();
|
||||
},
|
||||
|
||||
// Appends the month-on-month change marker inside a stat's value: a bold
|
||||
@@ -1366,8 +1407,7 @@ export const panelMethods = {
|
||||
.attr("data-tooltip", parts.join(", "));
|
||||
// Keep an open tooltip in step with the unit it describes across snapshots.
|
||||
if (this._hoveredStat && !this.$statTooltip.hasClass("hidden")) {
|
||||
const text = this._hoveredStat.attr("data-tooltip");
|
||||
if (text) this.$statTooltip.text(text);
|
||||
this._refreshStatTooltip();
|
||||
} else {
|
||||
this._hideStatTooltip();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user