From 0fb2bd796db657cce2481325f53fb12059fa85e9 Mon Sep 17 00:00:00 2001 From: Oliver Date: Sun, 1 Feb 2026 15:28:41 -0700 Subject: [PATCH] Add a barebones list view implementation --- assets/LICENSES | 4 ++++ assets/icons/layout/grid.svg | 1 + assets/icons/layout/list.svg | 1 + module/apps/ArtBrowser.mjs | 36 ++++++++++++++++++++++++++++--- styles/elements/radio.css | 38 +++++++++++++++++++++++++++++++++ styles/main.css | 1 + templates/ArtBrowser/images.hbs | 28 +++++++++++++++++++++++- 7 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 assets/LICENSES create mode 100644 assets/icons/layout/grid.svg create mode 100644 assets/icons/layout/list.svg create mode 100644 styles/elements/radio.css diff --git a/assets/LICENSES b/assets/LICENSES new file mode 100644 index 0000000..2e0719f --- /dev/null +++ b/assets/LICENSES @@ -0,0 +1,4 @@ +Disclaimer: All icons have been optimized and scaled for the web unless otherwise noted. + +icons/layout/grid.svg (https://thenounproject.com/icon/grid-2442978/) +icons/layout/list.svg (https://thenounproject.com/icon/list-5060696/) diff --git a/assets/icons/layout/grid.svg b/assets/icons/layout/grid.svg new file mode 100644 index 0000000..42c19b9 --- /dev/null +++ b/assets/icons/layout/grid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/layout/list.svg b/assets/icons/layout/list.svg new file mode 100644 index 0000000..3f2ab8b --- /dev/null +++ b/assets/icons/layout/list.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/module/apps/ArtBrowser.mjs b/module/apps/ArtBrowser.mjs index c28f958..801f0a2 100644 --- a/module/apps/ArtBrowser.mjs +++ b/module/apps/ArtBrowser.mjs @@ -35,6 +35,7 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { template: filePath(`templates/ArtBrowser/images.hbs`), templates: [ filePath(`templates/ArtBrowser/image/grid.hbs`), + filePath(`templates/ArtBrowser/image/list.hbs`), ], }, }; @@ -44,16 +45,23 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { #page = 1; #selectCount = 0; #onSubmit = null; + #layout = `grid`; filters = { name: ``, tags: [], artists: [], }; - constructor({ selectCount = 0, onSubmit = null, ...opts } = {}) { + constructor({ + selectCount = 0, + onSubmit = null, + layout = `grid`, + ...opts + } = {}) { super(opts); this.#selectCount = selectCount; this.#onSubmit = onSubmit; + this.#layout = layout; }; async setPage(page) { @@ -65,6 +73,15 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { return; }; + async changeLayout(layout) { + console.log(`changing layout to:`, layout) + if (![`grid`, `list`].includes(layout)) { + throw `Cannot set layout to: ${layout}`; + }; + this.#layout = layout; + await this.render({ parts: [`images`] }); + }; + get selectMode() { if (this.#selectCount === 0) { return `view`; @@ -132,6 +149,11 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { if (options.parts?.includes(`images`)) { this._updateSelectedCount(); + + const layoutTypeInputs = this.element.querySelectorAll(`input[name="layoutType"]`); + for (const element of layoutTypeInputs) { + element.addEventListener(`change`, this.#onLayoutChange.bind(this)); + }; }; }; @@ -178,9 +200,10 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { idp: this.id, }, is: { - multi: this.selectMode === `multi`, - single: this.selectMode === `single`, + multi: this.#selectCount > 1, + single: this.#selectCount === 1, }, + layout: this.#layout, can: { upload: true, }, @@ -270,6 +293,13 @@ export class ArtBrowser extends HandlebarsApplicationMixin(ApplicationV2) { this.render({ parts: [`images`] }); }; + async #onLayoutChange(event) { + event.preventDefault(); + event.stopPropagation(); + const newLayout = event.target.value; + await this.changeLayout(newLayout); + }; + /** @this {ArtBrowser} */ static async #nextPage() { this.#page += 1; diff --git a/styles/elements/radio.css b/styles/elements/radio.css new file mode 100644 index 0000000..b77ce40 --- /dev/null +++ b/styles/elements/radio.css @@ -0,0 +1,38 @@ +.token-browser > .window-content { + .radio-group { + display: flex; + flex-direction: row; + + input[type="radio"] { + width: 0; + height: 0; + margin: 0; + + &::before, &::after { + display: none; + } + } + + label { + display: flex; + justify-content: center; + align-items: center; + border: 1px solid var(--color-light-5); + cursor: pointer; + height: 28px; + min-width: 28px; + + &:first-child { + border-radius: 4px 0 0 4px; + } + + &:last-child { + border-radius: 0 4px 4px 0; + } + + &:has(:checked) { + background: var(--color-cool-4); + } + } + } +} diff --git a/styles/main.css b/styles/main.css index 6dfb3c3..f1b65a3 100644 --- a/styles/main.css +++ b/styles/main.css @@ -8,6 +8,7 @@ @import url("./elements/utils.css") layer(elements); @import url("./elements/checkbox.css") layer(elements); @import url("./elements/lists.css") layer(elements); +@import url("./elements/radio.css") layer(elements); /* Apps */ @import url("./apps/common.css") layer(apps); diff --git a/templates/ArtBrowser/images.hbs b/templates/ArtBrowser/images.hbs index effff3d..5cf069b 100644 --- a/templates/ArtBrowser/images.hbs +++ b/templates/ArtBrowser/images.hbs @@ -1,5 +1,31 @@
+
+ + +
{{#if can.upload}} {{/if}} @@ -12,7 +38,7 @@
    {{#each images as | image |}} {{> - (tb-filePath "templates/ArtBrowser/image/grid.hbs") + (concat (tb-filePath "templates/ArtBrowser/image/") @root.layout ".hbs") image=image is=@root.is }}