fix category images, gallery reset, scroll hint and orphan image cleanup

- category_nav pulls first product image per category from DB
- ProductImageScroll JS hook resets to index 0 on updated()
- collection filter bar gets CSS fade gradient scroll hint on mobile
- sync_product_images and delete_product_images now clean up orphaned
  Media.Image records to prevent DB bloat from repeated syncs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jamey
2026-02-16 08:20:55 +00:00
parent e226e64c0b
commit ccc14aa5e1
5 changed files with 149 additions and 69 deletions

View File

@@ -206,6 +206,22 @@
}
}
/* Horizontal scroll fade hint for collection category pills (mobile only) */
.collection-filter-scroll {
mask-image: linear-gradient(to right, black calc(100% - 2rem), transparent);
-webkit-mask-image: linear-gradient(to right, black calc(100% - 2rem), transparent);
scrollbar-width: none;
&::-webkit-scrollbar {
display: none;
}
@media (min-width: 640px) {
mask-image: none;
-webkit-mask-image: none;
}
}
/* Skip link for keyboard navigation */
.skip-link {
position: absolute;

View File

@@ -290,17 +290,10 @@ const Lightbox = {
const ProductImageScroll = {
mounted() {
const container = this.el.parentElement
const dots = container.querySelector('.product-image-dots')
const spans = dots ? dots.querySelectorAll('.product-image-dot') : []
const lightbox = container.parentElement.querySelector('dialog')
const thumbs = container.parentElement.querySelector('.pdp-gallery-thumbs')
const thumbButtons = thumbs ? thumbs.querySelectorAll('.pdp-thumbnail') : []
const imageCount = this.el.children.length
this.el.addEventListener('scroll', () => {
const {dots, thumbButtons, lightbox} = this._queryDom()
const index = Math.round(this.el.scrollLeft / this.el.offsetWidth)
spans.forEach((dot, i) => {
dots.forEach((dot, i) => {
dot.classList.toggle('product-image-dot-active', i === index)
})
thumbButtons.forEach((btn, i) => {
@@ -316,15 +309,32 @@ const ProductImageScroll = {
this.el.addEventListener('pdp:scroll-prev', () => {
const current = Math.round(this.el.scrollLeft / this.el.offsetWidth)
const target = (current - 1 + imageCount) % imageCount
const count = this.el.children.length
const target = (current - 1 + count) % count
this.el.scrollTo({left: target * this.el.offsetWidth, behavior: 'smooth'})
})
this.el.addEventListener('pdp:scroll-next', () => {
const current = Math.round(this.el.scrollLeft / this.el.offsetWidth)
const target = (current + 1) % imageCount
const count = this.el.children.length
const target = (current + 1) % count
this.el.scrollTo({left: target * this.el.offsetWidth, behavior: 'smooth'})
})
},
updated() {
this.el.scrollTo({left: 0, behavior: 'instant'})
},
_queryDom() {
const container = this.el.parentElement
const dotsEl = container.querySelector('.product-image-dots')
return {
dots: dotsEl ? dotsEl.querySelectorAll('.product-image-dot') : [],
thumbButtons: container.parentElement.querySelector('.pdp-gallery-thumbs')
?.querySelectorAll('.pdp-thumbnail') || [],
lightbox: container.parentElement.querySelector('dialog')
}
}
}