Add a component that handles displaying the person silhouette with some content inside of it

This commit is contained in:
Oliver-Akins 2025-07-20 21:32:46 -06:00
parent 26a2e0f3ff
commit 2b88bcc2ef
4 changed files with 146 additions and 0 deletions

View file

@ -0,0 +1,56 @@
import { filePath } from "../../consts.mjs";
import { StyledShadowElement } from "./mixins/StyledShadowElement.mjs";
const { renderTemplate } = foundry.applications.handlebars;
export class ArmourSummary extends StyledShadowElement(HTMLElement) {
static elementName = `armour-summary`;
static formAssociated = false;
/* Stuff for the mixin to use */
static _stylePath = `css/components/armour-summary.css`;
#container;
get type() {
return this.getAttribute(`type`) ?? `hero`;
};
set type(newValue) {
this.setAttribute(`type`, newValue);
};
_mounted = false;
async connectedCallback() {
super.connectedCallback();
if (this._mounted) { return };
/*
This converts all of the double-dash prefixed properties on the element to
CSS variables so that they don't all need to be provided by doing style=""
*/
for (const attrVar of this.attributes) {
if (attrVar.name?.startsWith(`var:`)) {
const prop = attrVar.name.replace(`var:`, ``);
this.style.setProperty(`--` + prop, attrVar.value);
};
};
this.#container = document.createElement(`div`);
this.#container.classList = `person`;
this.#container.innerHTML = await renderTemplate(
filePath(`templates/components/armour-summary.hbs`),
{ type: this.type },
);
this._shadow.appendChild(this.#container);
this._mounted = true;
};
disconnectedCallback() {
super.disconnectedCallback();
if (!this._mounted) { return };
this._mounted = false;
};
};

View file

@ -1,9 +1,11 @@
import { ArmourSummary } from "./ArmourSummary.mjs";
import { Logger } from "../../utils/Logger.mjs"; import { Logger } from "../../utils/Logger.mjs";
import { RipCryptBorder } from "./RipCryptBorder.mjs"; import { RipCryptBorder } from "./RipCryptBorder.mjs";
import { RipCryptIcon } from "./Icon.mjs"; import { RipCryptIcon } from "./Icon.mjs";
import { RipCryptSVGLoader } from "./svgLoader.mjs"; import { RipCryptSVGLoader } from "./svgLoader.mjs";
const components = [ const components = [
ArmourSummary,
RipCryptIcon, RipCryptIcon,
RipCryptSVGLoader, RipCryptSVGLoader,
RipCryptBorder, RipCryptBorder,

View file

@ -0,0 +1,54 @@
{{#if (eq type "hero")}}
<rc-svg
var:fill="var(--section-header-background)"
var:stroke="var(--base-background)"
var:stroke-width="2"
var:stroke-linejoin="rounded"
class="silhouette"
name="hero-silhouette"
></rc-svg>
{{else}}
<rc-svg
var:fill="var(--section-header-background)"
var:stroke="var(--base-background)"
var:stroke-width="2"
var:stroke-linejoin="rounded"
class="silhouette"
name="geist-silhouette.v2"
></rc-svg>
{{/if}}
{{!-- {{#each armours as | slot |}}
<div slot="{{@key}}" class="compass small">
<span class="value">
{{ slot.defense }}
</span>
{{#if slot.shielded}}
<rc-icon
class="shield"
name="icons/shield-solid"
data-tooltip="{{ rc-i18n "RipCrypt.tooltips.shield-bonus" value=@root.shield.bonus }}"
data-tooltip-direction="UP"
var:size="20px"
var:fill="var(--accent-3)"
var:stroke="black"
var:stroke-width="8px"
></rc-icon>
{{/if}}
</div>
{{/each}} --}}
<div class="head">
<slot name="head"></slot>
<span class="label">{{ rc-i18n "RipCrypt.common.anatomy.head" }}</span>
</div>
<div class="body">
<slot name="body"></slot>
<span class="label">{{ rc-i18n "RipCrypt.common.anatomy.body" }}</span>
</div>
<div class="arms">
<slot name="arms"></slot>
<span class="label">{{ rc-i18n "RipCrypt.common.anatomy.arms" }}</span>
</div>
<div class="legs">
<slot name="legs"></slot>
<span class="label">{{ rc-i18n "RipCrypt.common.anatomy.legs" }}</span>
</div>

View file

@ -0,0 +1,34 @@
:host {
display: inline-block;
}
.person {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
grid-template-rows: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.2fr);
justify-items: center;
align-items: center;
position: relative;
row-gap: var(--row-gap);
> div {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 1;
}
> rc-svg {
position: absolute;
bottom: 0;
left: 0;
width: 58%;
}
.head, .body, .legs { grid-column: 1; }
.arms { grid-column: 2; }
.head { grid-row: 1; }
.body, .arms { grid-row: 2; }
.legs { grid-row: 3; }
}