feat: <prop-viewer> fullscreen prop overlay
Implements fullscreen image overlay component for displaying art to players. Methods: show(src, label), dismiss(), isOpen(). Starts hidden. Clicking overlay dismisses. Strict TDD: 3 tests passing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,22 @@
|
|||||||
|
export class PropViewer extends HTMLElement {
|
||||||
|
constructor() { super(); this._src = ''; this._label = ''; }
|
||||||
|
connectedCallback() { if (!this.hasAttribute('hidden')) this.setAttribute('hidden', ''); this.render(); }
|
||||||
|
|
||||||
|
isOpen() { return !this.hasAttribute('hidden'); }
|
||||||
|
|
||||||
|
show(src, label = '') {
|
||||||
|
this._src = src; this._label = label;
|
||||||
|
this.removeAttribute('hidden');
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
dismiss() { this.setAttribute('hidden', ''); }
|
||||||
|
|
||||||
|
render() {
|
||||||
|
this.innerHTML = `
|
||||||
|
<div class="prop-overlay" data-role="overlay">
|
||||||
|
<img class="prop-img" data-role="prop-img" src="${this._src}" alt="${this._label}" />
|
||||||
|
</div>`;
|
||||||
|
this.querySelector('[data-role=overlay]').addEventListener('click', () => this.dismiss());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define('prop-viewer', PropViewer);
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { describe, it, expect, beforeEach } from 'vitest';
|
||||||
|
import '../../src/components/prop-viewer.js';
|
||||||
|
|
||||||
|
describe('<prop-viewer>', () => {
|
||||||
|
let el;
|
||||||
|
beforeEach(() => {
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
el = document.createElement('prop-viewer');
|
||||||
|
document.body.appendChild(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('starts hidden', () => {
|
||||||
|
expect(el.isOpen()).toBe(false);
|
||||||
|
expect(el.hasAttribute('hidden')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows an image when show() is called', () => {
|
||||||
|
el.show('/art/rain-pier.png', 'Pier in the rain');
|
||||||
|
expect(el.isOpen()).toBe(true);
|
||||||
|
const img = el.querySelector('[data-role=prop-img]');
|
||||||
|
expect(img.getAttribute('src')).toBe('/art/rain-pier.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('dismisses when the overlay is clicked', () => {
|
||||||
|
el.show('/art/x.png', 'x');
|
||||||
|
el.querySelector('[data-role=overlay]').click();
|
||||||
|
expect(el.isOpen()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user