Add support for the tabs in the two contentful Actor sheets

This commit is contained in:
Oliver 2026-03-15 15:35:57 -06:00
parent 76d8f3675c
commit 40f0e1ea2c
11 changed files with 120 additions and 5 deletions

View file

@ -79,7 +79,11 @@
"PlayerSheet": { "PlayerSheet": {
"manage-attributes": "Manage Attributes", "manage-attributes": "Manage Attributes",
"current-value": "Current value", "current-value": "Current value",
"max-value": "Maximum value" "max-value": "Maximum value",
"tab-names": {
"content": "Content",
"items": "Items"
}
}, },
"QueryStatus": { "QueryStatus": {
"title": "Information Request Status", "title": "Information Request Status",

View file

@ -14,6 +14,7 @@ const propertyToParts = {
"system.attr.value": [`attributes`, `content`], "system.attr.value": [`attributes`, `content`],
"system.attr.max": [`attributes`, `content`], "system.attr.max": [`attributes`, `content`],
"system.content": [`content`], "system.content": [`content`],
"system.carryCapacity": [`items`],
}; };
export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) { export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
@ -44,7 +45,26 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
static PARTS = { static PARTS = {
header: { template: filePath(`templates/PlayerSheet/header.hbs`) }, header: { template: filePath(`templates/PlayerSheet/header.hbs`) },
attributes: { template: filePath(`templates/PlayerSheet/attributes.hbs`) }, attributes: { template: filePath(`templates/PlayerSheet/attributes.hbs`) },
tabs: { template: filePath(`templates/generic/tabs.hbs`) },
content: { template: filePath(`templates/PlayerSheet/content.hbs`) }, content: { template: filePath(`templates/PlayerSheet/content.hbs`) },
items: {
template: filePath(`templates/PlayerSheet/item-lists.hbs`),
scrollable: [``],
templates: [
filePath(`templates/PlayerSheet/item.hbs`),
],
},
};
static TABS = {
primary: {
initial: `content`,
labelPrefix: `taf.Apps.PlayerSheet.tab-names`,
tabs: [
{ id: `content` },
{ id: `items` },
],
}
}; };
// #endregion Options // #endregion Options
@ -127,22 +147,38 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
// #endregion Lifecycle // #endregion Lifecycle
// #region Data Prep // #region Data Prep
async _preparePartContext(partID) { async _prepareContext() {
let ctx = { return {
meta: {
idp: this.id,
editable: this.isEditable,
},
actor: this.actor, actor: this.actor,
system: this.actor.system, system: this.actor.system,
editable: this.isEditable, editable: this.isEditable,
}; };
};
async _preparePartContext(partID, ctx) {
switch (partID) { switch (partID) {
case `attributes`: { case `attributes`: {
await this._prepareAttributes(ctx); await this._prepareAttributes(ctx);
break; break;
}; };
case `tabs`: {
ctx.hideTabs = this.actor.items.size <= 0;
ctx.tabs = await this._prepareTabs(`primary`);
break;
};
case `content`: { case `content`: {
await this._prepareContent(ctx); await this._prepareContent(ctx);
break; break;
}; };
case `items`: {
await this._prepareItems(ctx);
break;
};
}; };
return ctx; return ctx;
@ -165,6 +201,7 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
async _prepareContent(ctx) { async _prepareContent(ctx) {
// Whether or not the prose-mirror is toggled or always-edit // Whether or not the prose-mirror is toggled or always-edit
ctx.toggled = true; ctx.toggled = true;
ctx.tabActive = this.tabGroups.primary === `content` || this.actor.items.size === 0;
const TextEditor = foundry.applications.ux.TextEditor.implementation; const TextEditor = foundry.applications.ux.TextEditor.implementation;
ctx.enriched = { ctx.enriched = {
@ -173,6 +210,12 @@ export class PlayerSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
}, },
}; };
}; };
async _prepareItems(ctx) {
ctx.tabActive = this.tabGroups.primary === `items`;
};
async _prepareItem(item) {};
// #endregion Data Prep // #endregion Data Prep
// #region Actions // #region Actions

View file

@ -6,4 +6,26 @@
gap: 0.5rem; gap: 0.5rem;
overflow: auto; overflow: auto;
} }
> .window-content nav.system-tabs {
display: flex;
flex-direction: row;
justify-content: left;
align-items: center;
gap: 8px;
button {
border: none;
text-shadow: none;
box-shadow: none;
&.active {
outline: 1px solid var(--tab-button-active-border);
}
&:hover {
background: var(--tab-button-hover-bg);
}
}
}
} }

View file

@ -1,9 +1,10 @@
@layer resets, themes, elements, components, partials, apps, exceptions; @layer resets, themes, elements, components, partials, apps, exceptions;
/* Resets */ /* Resets */
@import url("./resets/button.css") layer(resets);
@import url("./resets/hr.css") layer(resets); @import url("./resets/hr.css") layer(resets);
@import url("./resets/inputs.css") layer(resets); @import url("./resets/inputs.css") layer(resets);
@import url("./resets/button.css") layer(resets); @import url("./resets/tabs.css") layer(resets);
/* Themes */ /* Themes */
@import url("./themes/dark.css") layer(themes); @import url("./themes/dark.css") layer(themes);

10
styles/resets/tabs.css Normal file
View file

@ -0,0 +1,10 @@
.taf > .window-content {
nav.tabs.system-tabs {
all: initial;
}
nav.sheet-tabs.top-tabs {
margin-inline: 0;
margin-top: calc(var(--spacer-8) * -1);
}
}

View file

@ -4,6 +4,9 @@
--spinner-outer-colour: white; --spinner-outer-colour: white;
--spinner-inner-colour: #FF3D00; --spinner-inner-colour: #FF3D00;
--tab-button-active-border: rebeccapurple;
--tab-button-hover-bg: var(--color-cool-3);
/* Chip Variables */ /* Chip Variables */
--chip-color: #fff7ed; --chip-color: #fff7ed;
--chip-background: #2b3642; --chip-background: #2b3642;

View file

@ -4,6 +4,9 @@
--spinner-outer-colour: black; --spinner-outer-colour: black;
--spinner-inner-colour: #FF3D00; --spinner-inner-colour: #FF3D00;
--tab-button-active: rebeccapurple;
--tab-button-hover-bg: var(--color-light-3);
/* Chip Variables */ /* Chip Variables */
--chip-color: #18181b; --chip-color: #18181b;
--chip-background: #fafafa; --chip-background: #fafafa;

View file

@ -1,4 +1,8 @@
<div class="content"> <div
class="content tab {{ifThen tabActive "active" ""}}"
data-group="primary"
data-tab="content"
>
{{#if editable}} {{#if editable}}
<prose-mirror <prose-mirror
class="actor-text" class="actor-text"

View file

@ -0,0 +1,7 @@
<div
class="tab {{ifThen tabActive "active" ""}}"
data-group="primary"
data-tab="items"
>
Item Tab Content Here
</div>

View file

@ -0,0 +1 @@
<div></div>

View file

@ -0,0 +1,17 @@
{{#if hideTabs}}
<template></template>
{{else}}
<nav class="tabs system-tabs">
{{#each tabs as |tab|}}
<button
type="button"
class="{{tab.cssClass}}"
data-action="tab"
data-group="{{tab.group}}"
data-tab="{{tab.id}}"
>
{{localize tab.label}}
</button>
{{/each}}
</nav>
{{/if}}