News
Layers MYSTO
“You don't know where you're going, but you know what closer feels like." - Mysto
"Mysto" is an intimate look into the life and inner workings of Chris Miyashiro; artist, professional surfer and skater, alaia shaper, sailor, storyteller, and student of life. A visual snapshot of the inspirations that make the fabric of Chris' life; a life filled with curiosity, navigation, and providence.
Presented by OluKai
Shop The Story
{"id":5156404789383,
"handle":"ohana-womens-beach-sandals-black",
"title":"‘Ohana - Black",
"available":true,
"tags":["'ohanna","2024-gift-guide","arch:high","beach sandals","Beach\/Boat","beachbum","best sellers","best selling","best:beach_boat","best:everday_wear","black fliflps","cat:sandals","collection:chief-home-officer","collection:HGG-Slider-W","collection:tide-tracker","color:Black","enhanced traction outsole","Everyday Wear","EXP_REC_WOMEN","extra-colors","fit:wide","flip flops","gender:women","labor day","likes:beach","material:synthetic","mothers-day","nature-inspired","o hana","o hanas","obama","oha","Ohana","ohana w","ohanaflip flops","ohanaohana women","ohsna","omaha","prime","RGroup_20110","size:true","SP-19-COLOR","SP19-Style","split_color","style:20110","synthetic","vacation:tropical","vegan","vegan friendly","water-friendly","wide sizes","wide width","widewidh","women","womens","womensflip flop","women’s","YGroup_20110","‘ohani"],
"type":"Women’s Water-Friendly Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Black"]},{"name":"Size","position":2,"values":["5","6","7","8","9","10","11","12"]}],
"price":10000,
"price_min":10000,
"price_max":10000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_001_W_Ohana_BlkBlk_41e6f1b8-ca5c-4d05-94b5-8f99b86192d1.png?v=1762441470",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34400636043399,
"featured_image_alt": "Black",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_102_W_OHANA_BlackBlack_29477e0f-6d55-47ce-a8a2-5d3cc7b3e441.jpg?v=1746734998",
"hover_image_alt": "Black",
"images": [{
"id": 34400636043399,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_001_W_Ohana_BlkBlk_41e6f1b8-ca5c-4d05-94b5-8f99b86192d1.png?v=1762441470",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636076167,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_102_W_OHANA_BlackBlack_29477e0f-6d55-47ce-a8a2-5d3cc7b3e441.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636108935,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_201_3d4a23f2-2dc2-4377-b783-2facd28f27cc.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636141703,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_105_W_OHANA_BlackBlack_9583fbfc-e266-4f84-8cb7-6bea1e1d83ea.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636174471,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_103_W_OHANA_BlackBlack_544bdd54-9555-4ff7-8502-0d553b48c511.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636207239,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_202_c9aea4c7-0925-4de5-8e8c-6ddc4cb76f70.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636240007,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_004_W_Ohana_BlkBlk.png?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636272775,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_203_3b915de6-8cff-43d6-b402-12306bad97cf.jpg?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
},{
"id": 34400636305543,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20110_4040_005_W_Ohana_BlkBlk.png?v=1746734998",
"alt": "Black",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "20110-4040-5"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":5156404396167,
"handle":"ohana-mens-beach-sandals-dark-java-ray",
"title":"‘Ohana - Dark Java \/ Ray",
"available":true,
"tags":["'oahni","2024-gift-guide","arch:high","beach sandals","Beach\/Boat","beachbum","best sellers","best selling","best:beach_boat","best:everday_wear","best:post_workout","cat:sandals","collection:tide-tracker","collection:wfh","color:brown","color:Dark Java \/ Ray","dk java","enhanced traction outsole","Everyday Wear","EXP_REC_MEN","extra-colors","Father’s Day Gifts","fit:wide","flip flops","flipfops","gender:men","gifts","hana","labor day","likes:beach","material:synthetic","men","mens","mens flipflops","men’s","o hana","obama","Oh","oha","ohan","ohana men s sandals","ohanaa","ohanaflip flops","ohanna","ohano","ohanu","ohona","Post-Workout","prime","RGroup_10110","size:true","SP-19-COLOR","SP19-Style","split_color","style:10110","synthetic","tempstandard","vacation:tropical","vegan","water reistant","water-friendly","wide width","widewidh","YGroup_10110","‘ohana"],
"type":"Men’s Water-Friendly Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Dark Java \/ Ray"]},{"name":"Size","position":2,"values":["7","8","9","10","11","12","13","14","15","16","17","18"]}],
"price":10000,
"price_min":10000,
"price_max":10000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_001_M_Ohana_DarkJava_f6321f63-1b0b-446f-a607-5f8e3d241990.png?v=1762441465",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34400638435463,
"featured_image_alt": "Dark Java \/ Ray",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/Ohana-DarkJava-galleryimage-01.jpg?v=1746734340",
"hover_image_alt": "Dark Java \/ Ray",
"images": [{
"id": 34400638435463,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_001_M_Ohana_DarkJava_f6321f63-1b0b-446f-a607-5f8e3d241990.png?v=1762441465",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34587117027463,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/Ohana-DarkJava-galleryimage-01.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34587117060231,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_201.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34587117092999,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_101_M_OHANA_DarkJavaRay.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34587117125767,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_103_bdd18907-7a8d-42b4-bc9b-bf1bea50e003.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34400638664839,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_102_M_OHANA_DarkJavaRay_1ca47e3c-3fa6-4062-9e87-8ec31f3772c9.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34400638697607,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_101_6dd8d973-9fda-457b-a6b8-aaa9a390a1f3.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34400638730375,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_203_3eaf126b-c4dc-4d8f-ac5b-2f56b10bd4de.jpg?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
},{
"id": 34400638763143,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10110_4827_005_M_Ohana_DarkJava.png?v=1746734340",
"alt": "Dark Java \/ Ray",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10110-4827-7"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":8017380966535,
"handle":"lai-slide-womens-slide-sandals-tan",
"title":"La‘i Slide - Tan",
"available":true,
"tags":["arch:standard","beach","beach sandals","Beach\/Boat","best seller","best:beach_boat","best:everday_wear","buckle","cat:sandals","cross sandal","Everyday Wear","fit:narrow","fit:standard","fliflops","flip flops","flip ops","flipflop men","fliplops","gender:women","La'iSlide","lai","lai slide","la‘i slide","material:synthetic","RGroup_20511","sandals","size:true","slide","slide sandals","slides","split_color","style:20511","synthetic","tortoise","tortoise shell","vegan","vegan friendly","water-friendly","Woman flipflops","women","women's","womens sldes","womenslides","Womenssandal","Womenssandals","Women’s Sandler"],
"type":"Women’s Versatile Slide Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Tan"]},{"name":"Size","position":2,"values":["5","6","7","8","9","10","11"]}],
"price":11000,
"price_min":11000,
"price_max":11000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_001_W_LAISLIDE_TanTan.png?v=1736453186",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 33380104536199,
"featured_image_alt": "Tan",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_101.jpg?v=1739558256",
"hover_image_alt": "Tan",
"images": [{
"id": 33380104536199,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_001_W_LAISLIDE_TanTan.png?v=1736453186",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33402882850951,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_101.jpg?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33402883047559,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511-3434_203.jpg?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33402883080327,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511-3434_1.jpg?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33402883113095,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_202.jpg?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33380104568967,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_003_W_LAISLIDE_TanTan.png?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33380104634503,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_004_W_LAISLIDE_TanTan.png?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
},{
"id": 33380104667271,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20511_3434_005_W_LAISLIDE_TanTan.png?v=1739558256",
"alt": "Tan",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "20511-3434-5"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":5271019520135,
"handle":"tuahine-mens-leather-beach-sandals-toffee",
"title":"Tuahine - Toffee",
"available":true,
"tags":["2024-gift-guide","alania","arch:standard","beach sandals","Beach\/Boat","best sellers","best selling","best:beach_boat","best:everday_wear","best:travel","BF2025","bundle|2|3|0|2","cat:sandals","collection:HGG-Slider-M","color:brown","Everyday Wear","Father’s Day Gifts","fit:standard","flip flops","flipfops","gender:men","gifts","highest rated flip flop","island resort","labor day","landleather","leather","Liahei Ili","likes:beach","likes:exercising","likes:friends","likes:hiking","likes:relaxing","likes:urban-exploring","material:leather","men s flipslops","mens","mens flipflops","Mens sansandals","nui","nui sandals","pikoi","prime","RGroup_10465","sandals","size:true","splashproof","split_color","style:10465","tauhine","tehohin","tihuine","Travel","tua","tua hine","tuahaine","tuahani","tuahine","tuakine","tuane","tuihine","twoawhie","water poof","water-friendly","waterproof","waterproof leather","weatherproof","ygroup_10465"],
"type":"Men’s Waterproof Leather Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Toffee"]},{"name":"Size","position":2,"values":["7","8","9","10","11","12","13","14","15"]}],
"price":13000,
"price_min":13000,
"price_max":13000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_001_M_Tuahine_TofTof_b5222a80-3d21-4a3d-b1bb-0761d6983ab4.png?v=1762442558",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34400638795911,
"featured_image_alt": "Toffee",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_101_b2299d2b-e11b-46dc-bb63-799ad4e17201.jpg?v=1746706343",
"hover_image_alt": "Toffee",
"images": [{
"id": 34400638795911,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_001_M_Tuahine_TofTof_b5222a80-3d21-4a3d-b1bb-0761d6983ab4.png?v=1762442558",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400638828679,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_101_b2299d2b-e11b-46dc-bb63-799ad4e17201.jpg?v=1746706343",
"alt": "Toffee",
"width": 4000,
"height": 4000
},{
"id": 43638638542983,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/Tuahine_Toffee.jpg?v=1778270435",
"alt": "Tuahine - Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400638861447,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_201_f5016eaf-4e76-4b10-9f72-27b605ee4008.jpg?v=1746706343",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400638926983,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_101_4fbe907a-88c7-4d48-9605-82300310bc85.jpg?v=1746706343",
"alt": "Toffee",
"width": 1080,
"height": 1080
},{
"id": 34400638959751,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_102_b07d7dde-910a-41ab-a31b-9b020fd5ffb4.jpg?v=1746706343",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400639058055,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_104_6323bac4-3ccf-4910-b3da-4c37f1b0bf47.jpg?v=1746706343",
"alt": "Toffee",
"width": 1080,
"height": 1080
},{
"id": 34400639090823,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_203_3b58eb84-9908-41b2-b595-77f470cceddd.jpg?v=1746706343",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400639123591,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_3333_005_M_Tuahine_TofTof.png?v=1746706343",
"alt": "Toffee",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10465-3333-7"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":8017381064839,
"handle":"lai-t-bar-womens-strappy-sandals-tan",
"title":"La‘i T–Bar - Tan \/ Tan",
"available":true,
"tags":["arch:standard","back strap","backstrap","beach","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","buckle","Everyday Wear","fit:standard","fliflops","flip flops","flip ops","fliplops","gender:women","lai","lai tbar","la‘i t-bar","material:synthetic","mothersday_2026","RGroup_20510","size:true","split_color","srappy","strappy","strappy sandals","strappywater-friendly","style:20510","synthetic","tstrap","vegan","vegan friendly","water-friendly","Woman flipflops","women","Women fliplflop","women's","Womenssandal","Womenssandals","Women’s Sandler"],
"type":"Women’s Strappy Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Tan \/ Tan"]},{"name":"Size","position":2,"values":["5","6","7","8","9","10","11"]}],
"price":13000,
"price_min":13000,
"price_max":13000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_001_W_LAITBAR_TanTan.png?v=1736453189",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 33380104929415,
"featured_image_alt": "Tan \/ Tan",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_201_4dd4a68e-a3a5-4783-bcb1-5ec9e6fb0710.jpg?v=1744750108",
"hover_image_alt": "Tan \/ Tan",
"images": [{
"id": 33380104929415,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_001_W_LAITBAR_TanTan.png?v=1736453189",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640008327,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_201_4dd4a68e-a3a5-4783-bcb1-5ec9e6fb0710.jpg?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640073863,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_203_aa7a98b5-b2ea-4102-b323-ac1b0eab5f4b.jpg?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640106631,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_003_W_LAITBAR_TanTan_8976d6f2-9f86-4490-99e0-830373f323e5.png?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640139399,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_AMZ_W_LAITBAR_TanTan_d6e0b199-13ba-4c68-a919-4435c3a1a685.png?v=1744750108",
"alt": "Tan \/ Tan",
"width": 3000,
"height": 3000
},{
"id": 34400640172167,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_004_W_LAITBAR_TanTan_5510a74d-db5f-4aa3-9cb6-b1853f5c2493.png?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640204935,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_202_eb4dab09-8f25-4559-9019-fc0eec87a6b9.jpg?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
},{
"id": 34400640237703,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20510_3434_005_W_LAITBAR_TanTan_e360b3e3-3d96-472c-8d29-17dea6e99354.png?v=1744750108",
"alt": "Tan \/ Tan",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "20510-3434-5"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":6686398447751,
"handle":"ulele-mens-beach-sandals-blue-depth-charcoal",
"title":"Ulele - Blue Depth \/ Charcoal",
"available":true,
"tags":["2024-gift-guide","arch:high","as seen on tv","beach sandals","Beach\/Boat","best sellers","best selling","best:beach_boat","best:everday_wear","best:travel","cat:sandals","color:blue","commercial","enhance gip","enhanced traction footbed","enhanced traction outsole","Everyday Wear","fit:wide","flip flops","gender:men","material:synthetic","men s flipslops","mens","Mens sansandals","olele","oolele","RGroup_10435","sandals","seen on tv","size:true","split_color","style:10435","synthetic","Travel","tv","tv ad","uelele","uiele","ule","ulee flip","Ulele-","uleleulele","uleue","ulule","vegan","water-friendly","wide width"],
"type":"Men’s Water-Ready Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Blue Depth \/ Charcoal"]},{"name":"Size","position":2,"values":["7","8","9","10","11","12","13","14","15"]}],
"price":11000,
"price_min":11000,
"price_max":11000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_001_M_Ulele_BlueDepthChr.png?v=1759447722",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34250983538823,
"featured_image_alt": "Blue Depth \/ Charcoal",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_102_M_ULELE_BlueDepthCharcoal_3a4753f8-7d9b-4661-ab19-4fa9eb43df8c.jpg?v=1746706349",
"hover_image_alt": "Blue Depth \/ Charcoal",
"images": [{
"id": 34250983538823,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_001_M_Ulele_BlueDepthChr.png?v=1759447722",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34587117781127,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_102_M_ULELE_BlueDepthCharcoal_3a4753f8-7d9b-4661-ab19-4fa9eb43df8c.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34587117813895,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_201.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34587117846663,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_101_M_ULELE_BlueDepthCharcoal_29facb9e-4bd9-4167-a614-54000ca5980b.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34587117879431,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_003_M_Ulele_BlueDepthChr_c57d011f-df5e-4d2e-9f24-47b6fdae98d3.png?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34250983702663,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_202_3e4ed1da-48d9-43c5-8d4f-c278b69f5015.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34250983735431,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_004_M_Ulele_BlueDepthChr.png?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34250983768199,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_103_M_ULELE_BlueDepthCharcoal_e2f72db6-e44b-4fae-94ba-280b7d108bc5.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34250983800967,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_203_bcb9738d-77d7-4088-89ea-e899fd550a96.jpg?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34250983833735,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_TF26_005_M_Ulele_BlueDepthChr.png?v=1746706349",
"alt": "Blue Depth \/ Charcoal",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10435-TF26-7"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{"id":8022593175687,
"handle":"southshore-womens-waterproof-leather-sandals-toffee",
"title":"Southshore - Toffee",
"available":true,
"tags":["arch:standard","beach sandals","Beach\/Boat","best sellers","best selling","best:beach_boat","best:everday_wear","cat:sandals","Everyday Wear","fit:standard","flip flops","gender:women","landleather","leather","leather:material","material:leather","olukai beach sandals","RGroup_20532","sandals","size:true","south shore","Southshore","split_color","style:20532","water poof","water-friendly","waterproof","waterproof leather","women","womens","Womenssandals","women’s"],
"type":"Women’s Waterproof Leather Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Toffee"]},{"name":"Size","position":2,"values":["5","6","7","8","9","10","11"]}],
"price":13000,
"price_min":13000,
"price_max":13000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_001_W_SOUTHSHORE_ToffeeToffee.png?v=1737056124",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 3000,
"featured_image_height": 3000,
"featured_image_id": 33422882799751,
"featured_image_alt": "Toffee",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_106_239e8fab-e798-45ac-bee7-198abbf83622.jpg?v=1744750102",
"hover_image_alt": "Toffee",
"images": [{
"id": 33422882799751,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_001_W_SOUTHSHORE_ToffeeToffee.png?v=1737056124",
"alt": "Toffee",
"width": 3000,
"height": 3000
},{
"id": 34400635650183,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_106_239e8fab-e798-45ac-bee7-198abbf83622.jpg?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635682951,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/Southshore_Tech_bc4fcb8f-1b2d-43de-a38c-06eced3983a8.png?v=1744750102",
"alt": "Toffee",
"width": 1000,
"height": 1000
},{
"id": 34400635715719,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_101_ab8021f3-3738-4d80-9632-1719173128dc.jpg?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635748487,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_102_dc7809ec-e8ed-488d-82c6-435a9f7fda0d.jpg?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635781255,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_103_9baa3ede-f25b-4516-a455-a7aed0e9e14c.jpg?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635814023,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3333_003_W_SOUTHSHORE_ToffeeToffee_3c797c1d-45e7-4659-b374-9997114d0815.png?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635846791,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3434_004_W_SOUTHSHORE_TanTan_2e87aa3d-16e8-4e50-a880-d831a7594719.png?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
},{
"id": 34400635879559,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20532_3434_005_M_SOUTHSHORE_TanTan_77760051-2761-478c-8ff2-bd1dc3b1a519.png?v=1744750102",
"alt": "Toffee",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "20532-3333-5"
}
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>
Explore Similar Stories
{ $dispatch('product-item:images-changed', { product: product, source: 'swatch-container' }) })"
@pointercancel="intendedSwatchIndex = null; intendedSwatchEl = null"
x-data="{
wrapper: $el,
selectedSibling:product.siblings[0],
intendedSwatchIndex: null,
intendedSwatchEl: null,
swatchGap: 8,
scrollable: product.siblings.filter(s => !!s.available).length > 9.5,
canPrev: false,
canNext: true,
_edgeReady: false,
imageLimit: 0,
limitImages(nextProduct) {
const images = Array.isArray(nextProduct && nextProduct.images) ? nextProduct.images : [];
const limitedImages = this.imageLimit > 0 ? images.slice(0, this.imageLimit) : images;
const hoverImage = limitedImages[1] || null;
return Object.assign({}, nextProduct, {
images: limitedImages,
hover_image: hoverImage ? hoverImage.src : null,
hover_image_alt: hoverImage ? hoverImage.alt : null
});
},
selectProduct(nextProduct) {
const productRoot = $el.closest('.product-item');
const productData = productRoot && productRoot._x_dataStack && productRoot._x_dataStack[0];
if (productData && typeof productData.setProduct === 'function') {
productData.setProduct(nextProduct);
} else {
$data.product = this.limitImages(nextProduct);
}
},
getSwatchImageSrc(sibling) {
return sibling.images[0].src;
},
buildSwatchSrcset(src) {
if (!src) return '';
const widths = ['48', '96', '192'];
const separator = src.includes('?') ? '&' : '?';
return widths.map(w => `${src}${separator}width=${w} ${w}w`).join(', ');
},
isSwatchPriority(index) {
return window.innerWidth >= 1024 ? index < 3 : index < 2;
},
swatchBg(sibling) {
// swatch_bg precomputed at hydration. Nullish (not ||): null = no colors set
// (fall back to theme default), empty string = invalid combo, no fallback.
return sibling.swatch_bg ?? '#000000';
},
centerSwatch(el) {
if ($data.wrapper.scrollWidth <= $data.wrapper.clientWidth) return false
const wrapperRect = $data.wrapper.getBoundingClientRect()
const elRect = el.getBoundingClientRect()
const centerPoint = wrapperRect.x + (wrapperRect.width / 2)
const behavior = window.innerWidth < 1024 ? 'auto' : 'smooth'
$data.wrapper.scrollTo({
left: $data.wrapper.scrollLeft + (elRect.x - centerPoint + (elRect.width / 2)),
behavior
})
},
selectSwatchFromTap(siblingIndex, el) {
const idx = (this.intendedSwatchIndex !== null && this.intendedSwatchIndex !== undefined)
? this.intendedSwatchIndex
: siblingIndex
const targetEl = this.intendedSwatchEl || el
this.intendedSwatchIndex = null
this.intendedSwatchEl = null
const next = product.siblings[idx]
if (next) product = next
this.centerSwatch(targetEl)
},
scroll(direction = 'forward') {
const swatch = $data.wrapper.querySelector('.product-item__swatch')
const unit = swatch ? swatch.offsetWidth + $data.swatchGap : $data.wrapper.clientWidth * 0.3
let amount = 2 * unit
$data.wrapper.scrollTo({
left: direction == 'forward' ? $data.wrapper.scrollLeft + amount : $data.wrapper.scrollLeft - amount,
behavior:'smooth'
})
},
// Lazily wire the prev/next edge detection on first desktop hover/focus —
// the arrows are a desktop affordance, so no observer is built at load and
// none is ever built on mobile. canPrev/canNext default to the at-start state.
initSwatchEdges() {
if (this._edgeReady || window.innerWidth <= 1023) return
this._edgeReady = true
const root = this.wrapper
const swatches = root.querySelectorAll('.product-item__swatch')
if (swatches.length < 2) return
const first = swatches[0], last = swatches[swatches.length - 1]
const io = new IntersectionObserver((entries) => {
const d = window.Alpine && window.Alpine.$data ? window.Alpine.$data(root) : null
if (!d) return
entries.forEach((e) => {
if (e.target === first) d.canPrev = !e.isIntersecting
if (e.target === last) d.canNext = !e.isIntersecting
})
}, { root, threshold: 0.99 })
io.observe(first)
io.observe(last)
root._swatchEdgeIO = io
}
}"
@pointerenter="initSwatchEdges()"
@focusin="initSwatchEdges()"
>