Restyle HP display as compact rounded pill

Group current HP, temp HP, and max HP into a single bordered
pill container with a subtle slash separator. Removes the
scattered layout with separate elements and gaps. Temp HP +N
only renders when present (no invisible spacer).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-23 13:11:28 +01:00
parent 8bf69fd47d
commit 9cdf004c15
3 changed files with 41 additions and 78 deletions

View File

@@ -12,9 +12,8 @@ import { PLAYER_COLOR_HEX } from "../player-icon-map.js";
const TEMP_HP_REGEX = /^\+\d/;
// Mock persistence — no localStorage interaction
const mockLoadEncounter = vi.fn<() => unknown>(() => null);
vi.mock("../../persistence/encounter-storage.js", () => ({
loadEncounter: () => mockLoadEncounter(),
loadEncounter: () => null,
saveEncounter: () => {},
}));
@@ -126,14 +125,14 @@ describe("CombatantRow", () => {
expect(nameContainer).not.toBeNull();
});
it("shows '--' for current HP when no maxHp is set", () => {
it("shows 'Max' placeholder when no maxHp is set", () => {
renderRow({
combatant: {
id: combatantId("1"),
name: "Goblin",
},
});
expect(screen.getByLabelText("No HP set")).toBeInTheDocument();
expect(screen.getByText("Max")).toBeInTheDocument();
});
it("shows concentration icon when isConcentrating is true", () => {
@@ -245,11 +244,6 @@ describe("CombatantRow", () => {
tempHp: 8,
isConcentrating: true,
};
mockLoadEncounter.mockReturnValueOnce({
combatants: [combatant],
activeIndex: 0,
roundNumber: 1,
});
const { rerender, container } = renderRow({ combatant });
// Temp HP absorbs all damage, currentHp unchanged
rerender(
@@ -265,20 +259,15 @@ describe("CombatantRow", () => {
describe("temp HP display", () => {
it("shows +N when combatant has temp HP", () => {
const combatant = {
id: combatantId("1"),
name: "Goblin",
maxHp: 20,
currentHp: 15,
tempHp: 5,
};
// Provide encounter with tempHp so hasTempHp is true
mockLoadEncounter.mockReturnValueOnce({
combatants: [combatant],
activeIndex: 0,
roundNumber: 1,
renderRow({
combatant: {
id: combatantId("1"),
name: "Goblin",
maxHp: 20,
currentHp: 15,
tempHp: 5,
},
});
renderRow({ combatant });
expect(screen.getByText("+5")).toBeInTheDocument();
});
@@ -295,19 +284,15 @@ describe("CombatantRow", () => {
});
it("temp HP display uses cyan color", () => {
const combatant = {
id: combatantId("1"),
name: "Goblin",
maxHp: 20,
currentHp: 15,
tempHp: 8,
};
mockLoadEncounter.mockReturnValueOnce({
combatants: [combatant],
activeIndex: 0,
roundNumber: 1,
renderRow({
combatant: {
id: combatantId("1"),
name: "Goblin",
maxHp: 20,
currentHp: 15,
tempHp: 8,
},
});
renderRow({ combatant });
const tempHpEl = screen.getByText("+8");
expect(tempHpEl.className).toContain("text-cyan-400");
});