Saved Filters
")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -140,7 +140,7 @@ func BookShelf(
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(uuidToString(filter.ID))
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 275, Col: 173}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 277, Col: 173}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
@@ -153,7 +153,7 @@ func BookShelf(
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(filter.Name)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 277, Col: 27}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 279, Col: 27}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
@@ -194,7 +194,7 @@ func BookShelf(
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(errorMessage)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 311, Col: 59}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 313, Col: 59}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
@@ -227,7 +227,7 @@ func BookShelf(
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(offset/limit + 1)
if templ_7745c5c3_Err != nil {
- return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 330, Col: 32}
+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `templates/bookshelf.templ`, Line: 332, Col: 32}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
diff --git a/web/src/bookshelf.ts b/web/src/bookshelf.ts
index 3412db4..d76b17c 100644
--- a/web/src/bookshelf.ts
+++ b/web/src/bookshelf.ts
@@ -80,6 +80,8 @@ Alpine.data("bookshelf", () => ({
showSaveModal: false,
showFiltersDropdown: false,
hasCoverState: null as boolean | null,
+ dropdownAlign: "right" as "left" | "right",
+ resizeTimeout: null as number | null,
// Standalone function references (don't access component state)
clearFilters,
@@ -89,9 +91,52 @@ Alpine.data("bookshelf", () => ({
showSaveFilterModal() {
this.showSaveModal = true;
},
- // Toggle the filters dropdown
+ // Helper method to calculate alignment
+ calculateAlignment() {
+ const button = document.querySelector("[data-load-filter-btn]");
+ if (!button) return;
+
+ const rect = button.getBoundingClientRect();
+ const viewportWidth = window.innerWidth;
+ const dropdownWidth = 320;
+
+ const spaceOnLeft = rect.left;
+ const spaceOnRight = viewportWidth - rect.right;
+
+ if (spaceOnRight >= dropdownWidth) {
+ this.dropdownAlign = "left";
+ } else if (spaceOnLeft >= dropdownWidth) {
+ this.dropdownAlign = "right";
+ } else {
+ this.dropdownAlign = spaceOnLeft > spaceOnRight ? "right" : "left";
+ }
+ },
+
toggleFiltersDropdown() {
this.showFiltersDropdown = !this.showFiltersDropdown;
+
+ if (this.showFiltersDropdown) {
+ this.$nextTick(() => {
+ this.calculateAlignment();
+ });
+ }
+ },
+ // Alpine lifecycle hook - runs when component initializes
+ init() {
+ let rafId: number | null = null;
+
+ window.addEventListener("resize", () => {
+ if (rafId !== null) {
+ cancelAnimationFrame(rafId);
+ }
+
+ rafId = requestAnimationFrame(() => {
+ if (this.showFiltersDropdown) {
+ this.calculateAlignment();
+ }
+ rafId = null;
+ });
+ });
},
// Cycle through has_cover states: null -> true -> false -> null
cycleHasCover(): void {