Fix persistent damage tag ordering and differentiate condition icons
All checks were successful
CI / check (push) Successful in 2m39s
CI / build-image (push) Successful in 18s

- Render persistent damage tags before the "+" button, not after
- Use insertion order for conditions on the row instead of definition order
- Differentiate Undetected condition (EyeClosed/slate) from Invisible (Ghost/violet)
- Use purple for void persistent damage to distinguish from violet conditions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-04-11 13:06:31 +02:00
parent 0f640601b6
commit 064af16f95
7 changed files with 29 additions and 28 deletions

View File

@@ -60,13 +60,13 @@ describe("toggleCondition", () => {
]);
});
it("maintains definition order when adding conditions", () => {
it("appends new conditions to the end (insertion order)", () => {
const e = enc([makeCombatant("A", [{ id: "poisoned" }])]);
const { encounter } = success(e, "A", "blinded");
expect(encounter.combatants[0].conditions).toEqual([
{ id: "blinded" },
{ id: "poisoned" },
{ id: "blinded" },
]);
});
@@ -109,15 +109,16 @@ describe("toggleCondition", () => {
expect(encounter.combatants[0].conditions).toBeUndefined();
});
it("preserves order across all conditions", () => {
it("preserves insertion order across all conditions", () => {
const order = CONDITION_DEFINITIONS.map((d) => d.id);
// Add in reverse order
// Add in reverse order — result should be reverse order (insertion order)
const reversed = [...order].reverse();
let e = enc([makeCombatant("A")]);
for (const cond of [...order].reverse()) {
for (const cond of reversed) {
const result = success(e, "A", cond);
e = result.encounter;
}
expect(e.combatants[0].conditions).toEqual(order.map((id) => ({ id })));
expect(e.combatants[0].conditions).toEqual(reversed.map((id) => ({ id })));
});
});

View File

@@ -500,8 +500,8 @@ export const CONDITION_DEFINITIONS: readonly ConditionDefinition[] = [
description5e: "",
descriptionPf2e:
"Location unknown. Must pick a square to target; DC 11 flat check. Attacker is off-guard against your attacks.",
iconName: "Ghost",
color: "violet",
iconName: "EyeClosed",
color: "slate",
systems: ["pf2e"],
},
{

View File

@@ -70,7 +70,7 @@ export const PERSISTENT_DAMAGE_DEFINITIONS: readonly PersistentDamageDefinition[
color: "pink",
},
{ type: "force", label: "Force", iconName: "Orbit", color: "indigo" },
{ type: "void", label: "Void", iconName: "Eclipse", color: "slate" },
{ type: "void", label: "Void", iconName: "Eclipse", color: "purple" },
{ type: "spirit", label: "Spirit", iconName: "Wind", color: "neutral" },
{
type: "vitality",

View File

@@ -14,12 +14,6 @@ export interface ToggleConditionSuccess {
readonly events: DomainEvent[];
}
function sortByDefinitionOrder(entries: ConditionEntry[]): ConditionEntry[] {
const order = CONDITION_DEFINITIONS.map((d) => d.id);
entries.sort((a, b) => order.indexOf(a.id) - order.indexOf(b.id));
return entries;
}
function validateConditionId(conditionId: ConditionId): DomainError | null {
if (!VALID_CONDITION_IDS.has(conditionId)) {
return {
@@ -67,8 +61,7 @@ export function toggleCondition(
newConditions = filtered.length > 0 ? filtered : undefined;
event = { type: "ConditionRemoved", combatantId, condition: conditionId };
} else {
const added = sortByDefinitionOrder([...current, { id: conditionId }]);
newConditions = added;
newConditions = [...current, { id: conditionId }];
event = { type: "ConditionAdded", combatantId, condition: conditionId };
}
@@ -125,10 +118,7 @@ export function setConditionValue(
};
}
const added = sortByDefinitionOrder([
...current,
{ id: conditionId, value: clampedValue },
]);
const added = [...current, { id: conditionId, value: clampedValue }];
return {
encounter: applyConditions(encounter, combatantId, added),
events: [