feat(ui): F8-12 — map polish (zoom invariance, labels, selection, soft radius) (#55)
* Honest pixel-space sizing for `pointRadiusPx` / `strokeWidthPx`: the renderer divides by the current camera scale on every `viewport.zoomed` so thin lines / small markers stay the same on-screen size at any zoom. * Known-size planets switch to `pointRadiusWorld`, softened against the reference scale by `PLANET_SIZE_ZOOM_ALPHA = 0.33`; unidentified planets pin to a 3-px disc. * New planet label layer renders a two-line `name / #N` legend under each planet (`#N` only for unidentified or when the new `planetNames` toggle is off). Selection now paints an inverse-fill frame around the selected planet's label plus an outline on the disc; the old selection-ring primitive is retired. * Bombing markers swap the separate CirclePrim for a planet-outline overlay (damaged / wiped colour); the report deep-link moves to a "view bombing report" link in the planet inspector. * Docs + tests follow: `renderer.md` reflects the new sizing contract + label / outline layers, vitest covers the sizing math, label formatting, and the new toggle, and the map-toggles e2e adds a persistence case for `planetNames`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
<script lang="ts">
|
||||
import { getContext, tick } from "svelte";
|
||||
import type {
|
||||
ReportBombing,
|
||||
ReportLocalShipGroup,
|
||||
ReportOtherShipGroup,
|
||||
ReportPlanet,
|
||||
@@ -36,6 +37,8 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
type EntityNameInvalidReason,
|
||||
} from "$lib/util/entity-name";
|
||||
import { formatFloat } from "$lib/util/number-format";
|
||||
import { scrollToBombingRow } from "$lib/report-nav";
|
||||
import { activeView } from "$lib/app-nav.svelte";
|
||||
import CargoRoutes from "./planet/cargo-routes.svelte";
|
||||
import Production from "./planet/production.svelte";
|
||||
import ShipGroups from "./planet/ship-groups.svelte";
|
||||
@@ -52,6 +55,7 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
localShipGroups: ReportLocalShipGroup[];
|
||||
otherShipGroups: ReportOtherShipGroup[];
|
||||
localRace: string;
|
||||
bombing?: ReportBombing | null;
|
||||
};
|
||||
let {
|
||||
planet,
|
||||
@@ -65,8 +69,15 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
localShipGroups,
|
||||
otherShipGroups,
|
||||
localRace,
|
||||
bombing = null,
|
||||
}: Props = $props();
|
||||
|
||||
function openBombingReport(): void {
|
||||
if (bombing === null) return;
|
||||
activeView.select("report");
|
||||
scrollToBombingRow(bombing.planetNumber);
|
||||
}
|
||||
|
||||
const kindKeyMap: Record<ReportPlanet["kind"], TranslationKey> = {
|
||||
local: "game.inspector.planet.kind.local",
|
||||
other: "game.inspector.planet.kind.other",
|
||||
@@ -314,6 +325,23 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
{i18n.t("game.inspector.planet.unidentified_no_data")}
|
||||
</p>
|
||||
{/if}
|
||||
|
||||
{#if bombing !== null}
|
||||
<button
|
||||
type="button"
|
||||
class="bombing-link"
|
||||
class:bombing-link--wiped={bombing.wiped}
|
||||
data-testid="inspector-planet-view-bombing"
|
||||
data-bombing-wiped={bombing.wiped ? "true" : "false"}
|
||||
onclick={openBombingReport}
|
||||
>
|
||||
{i18n.t(
|
||||
bombing.wiped
|
||||
? "game.inspector.planet.view_bombing_wiped"
|
||||
: "game.inspector.planet.view_bombing",
|
||||
)}
|
||||
</button>
|
||||
{/if}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
@@ -432,4 +460,28 @@ the entry point, Escape (or unmounting the inspector) reverts.
|
||||
.icon-action--apply:not(:disabled) {
|
||||
color: var(--color-success);
|
||||
}
|
||||
.bombing-link {
|
||||
font: inherit;
|
||||
font-size: 0.85rem;
|
||||
padding: 0.4rem 0.6rem;
|
||||
background: var(--color-surface-hover);
|
||||
color: var(--color-text);
|
||||
border: 1px solid var(--color-border);
|
||||
border-left: 3px solid var(--color-warning, #f57f17);
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
text-align: left;
|
||||
}
|
||||
.bombing-link:hover,
|
||||
.bombing-link:focus-visible {
|
||||
border-color: var(--color-accent);
|
||||
border-left-color: var(--color-warning, #f57f17);
|
||||
}
|
||||
.bombing-link--wiped {
|
||||
border-left-color: var(--color-danger);
|
||||
}
|
||||
.bombing-link--wiped:hover,
|
||||
.bombing-link--wiped:focus-visible {
|
||||
border-left-color: var(--color-danger);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user