feat(ui): hide modifier tooltip on pieces with no active modifiers
The hover tooltip previously rendered on every piece regardless of whether it had any modifier facts, showing just a piece-type header and 'No active modifiers' — noise with zero information the user can't already see on the board. Now returns null when there are no modifier rows. The pinned panel (click-to-pin) keeps its empty-state copy because an explicit pin is a deliberate inspect action where confirming 'nothing here' is valid. Tests: - Inverted the two T24 hover tests to assert the tooltip does NOT render on unmodified pieces (b1 knight, e2 pawn on a vanilla solo game). - Added a positive test: hover a modified pawn (HP +1 from a seeded profile) and assert the tooltip + at least one row are visible.
This commit is contained in:
parent
ce6b2c1816
commit
7bee3cbaa9
2 changed files with 79 additions and 22 deletions
|
|
@ -165,29 +165,85 @@ test.describe('Modifier Profiles — hover tooltip (T24)', () => {
|
|||
await page.waitForURL('**/game');
|
||||
});
|
||||
|
||||
test('hover piece shows modifier tooltip', async ({ page }) => {
|
||||
// Hover white knight at b1 (standard opening position).
|
||||
test('hover unmodified piece does NOT show tooltip', async ({ page }) => {
|
||||
// Standard solo game — no modifier profile active, so b1 knight
|
||||
// has no modifier facts. The tooltip only renders when the piece
|
||||
// actually has modifiers; showing an empty card on every hover was
|
||||
// noisy and unhelpful.
|
||||
await page.hover('[data-square="b1"]');
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Tooltip must appear and identify the piece.
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip"]'),
|
||||
).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('hover unmodified pawn does NOT show tooltip', async ({ page }) => {
|
||||
// Same invariant, second fixture piece. Guards the "no noise on
|
||||
// unmodified pieces" behaviour in case a future change accidentally
|
||||
// re-enables the always-render path.
|
||||
await page.hover('[data-square="e2"]'); // white pawn
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip-row"]'),
|
||||
).toHaveCount(0);
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip"]'),
|
||||
).toHaveCount(0);
|
||||
});
|
||||
|
||||
test('hover modified piece DOES show tooltip with rows', async ({ page }) => {
|
||||
// Seed a profile that puts HP +1 on every white pawn, apply it to
|
||||
// a fresh solo game via the lobby picker, then hover e2. The
|
||||
// tooltip should render and surface the HP Bonus row.
|
||||
await page.goto('/');
|
||||
const LIBRARY_KEY = 'houserules:modifier-profiles:v1';
|
||||
const entry = {
|
||||
id: 't24-hover-positive',
|
||||
name: 'Hover Positive',
|
||||
profile: {
|
||||
id: 't24-hover-positive',
|
||||
name: 'Hover Positive',
|
||||
description: '',
|
||||
layoutId: 'classic',
|
||||
perType: [
|
||||
{ kind: 'hp-bonus', pieceType: 'pawn', color: 'white', value: 1 },
|
||||
],
|
||||
perInstance: [],
|
||||
version: 1,
|
||||
source: 'custom',
|
||||
},
|
||||
starred: false,
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
await page.evaluate(
|
||||
({ key, e }) => localStorage.setItem(key, JSON.stringify([e])),
|
||||
{ key: LIBRARY_KEY, e: entry },
|
||||
);
|
||||
await page.reload();
|
||||
const picker = page.getByTestId('profile-picker');
|
||||
if (!(await picker.isVisible())) {
|
||||
await page.locator('[data-action="open-rules-drawer"]').click();
|
||||
}
|
||||
await expect(picker).toBeVisible();
|
||||
await picker.selectOption('t24-hover-positive');
|
||||
await page.locator('[data-action="play-solo"]').click();
|
||||
await page.waitForURL('**/game');
|
||||
|
||||
// Hover e2 — white pawn with HpBonus +1 from the profile.
|
||||
await page.hover('[data-square="e2"]');
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip"]'),
|
||||
).toBeVisible({ timeout: 1000 });
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip"]'),
|
||||
).toContainText(/knight/i);
|
||||
});
|
||||
|
||||
test('hover unmodified piece shows no modifier rows', async ({ page }) => {
|
||||
// Standard solo game — no modifier profile active.
|
||||
await page.hover('[data-square="e2"]'); // white pawn
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Tooltip appears (header always shows) but no modifier rows.
|
||||
).toContainText(/pawn/i);
|
||||
await expect(
|
||||
page.locator('[data-testid="modifier-tooltip-row"]'),
|
||||
).toHaveCount(0);
|
||||
page.locator('[data-testid="modifier-tooltip-row"]').first(),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,10 @@
|
|||
* the engine session. Renders as an absolute-positioned card; the parent is
|
||||
* responsible for placement (positioned within a `relative` container).
|
||||
*
|
||||
* Source attribution is simplified for T24: any fact that matches a
|
||||
* MODIFIER_REGISTRY attribute is shown without distinguishing per-type /
|
||||
* per-instance / preset origin (T26 can refine this).
|
||||
* Renders nothing when the piece has no modifier facts — the tooltip exists
|
||||
* to surface modifier state, and showing an empty card on every unmodified
|
||||
* piece is noisy. The pinned panel (click-to-pin) carries the "no modifiers"
|
||||
* empty state instead, since an explicit pin is a deliberate inspect action.
|
||||
*/
|
||||
import { asEntityId } from '@paratype/rete';
|
||||
import { MODIFIER_REGISTRY } from '../modifiers/index.js';
|
||||
|
|
@ -40,6 +41,11 @@ export function ModifierTooltip({ pieceId, engine }: Props) {
|
|||
return [{ id: descriptor.id, label: descriptor.label, description }];
|
||||
});
|
||||
|
||||
// No modifiers on this piece → don't render the tooltip at all. A card
|
||||
// that just says "White Knight" with an empty-state line adds noise
|
||||
// without carrying information the user can't already see on the board.
|
||||
if (modifierRows.length === 0) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="modifier-tooltip"
|
||||
|
|
@ -63,11 +69,6 @@ export function ModifierTooltip({ pieceId, engine }: Props) {
|
|||
</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Empty state */}
|
||||
{modifierRows.length === 0 && (
|
||||
<p className="text-[11px] text-neutral-400 italic">No active modifiers</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue