News
OluKai and HLA Presents: On Guard Episode 4
On Guard - Episode 4 with Luke Shepardson
In the latest installment of On Guard, we shine a light on Luke Shepardson, lifeguard, Eddie Aikau Champion, waterman, and father. As humble as he is fearless, Luke’s developed a sterling reputation for his bravado in the lineup and his leadership on land.
In this episode, he opens up about his path to the tower, the importance of serving his community, and his pursuit of the world’s heaviest waves.
While Luke's story marks the end of the opening installment of On Guard, the watch is far from over. Stay tuned for more stories from the tower.
Shop The Story
{"id":8323812688007,
"handle":"ulele-womens-beach-sandals-black",
"title":"Ulele - Black \/ Black",
"available":true,
"tags":["arch:high","arch:standard","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","best:travel","breathable","cat:sandals","Dark Soled","enhanced traction footbed","enhanced traction outsole","Everyday Wear","fit:standard","flip flops","gender:women","lightweight","material:synthetic","prime","RGroup_10435","sandals","shearling lined","size:true","split_color","style:20562","synthetic","textile","Travel","ulee flip","Ulele-","ulelel","ulelesandals","uleleulele","uulele","vegan","water sandals mens","water-friendly","water-resistant","waterproof","wide sizes","wide width","women","Women fliplflop","women's sandals","womens","Womenssandal","Womenssandals","women’s"],
"type":"Women’s Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Black \/ Black"]},{"name":"Size","position":2,"values":["5","6","7","8","9","10","11","12"]}],
"price":11000,
"price_min":11000,
"price_max":11000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/20562_4040_001_W_ULELE_BlackBlack.png?v=1767641260",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 38417798004871,
"featured_image_alt": "Ulele - Black \/ Black",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/20562-4040-206.jpg?v=1767641260",
"hover_image_alt": "Ulele - Black \/ Black",
"images": [{
"id": 38417798004871,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562_4040_001_W_ULELE_BlackBlack.png?v=1767641260",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417798496391,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562-4040-206.jpg?v=1767641260",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417798955143,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562-4040-101.jpg?v=1767641261",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417799217287,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562-4040-205.jpg?v=1767641261",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417799577735,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562-4040-102.jpg?v=1767641261",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417799970951,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562_4040_003_W_ULELE_BlackBlack.png?v=1767641262",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417800462471,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562_4040_004_W_ULELE_BlackBlack.png?v=1767641263",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
},{
"id": 38417800790151,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/20562_4040_005_W_ULELE_BlackBlack.png?v=1767641264",
"alt": "Ulele - Black \/ Black",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "20562-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":8047520383111,
"handle":"ahi-mens-boat-shoes-blue-pearl-white-sand",
"title":"‘Ahi - Blue Pearl \/ White Sand",
"available":true,
"tags":["ahi","arch:standard","Beach\/Boat","best sellers","best selling","best:beach_boat","boat","boat ahoe","boat shoe","boaters","boatshoes","cat:shoes","drop-in heel®","fisherman","fisherman shoe","fishing","fishing shoe","fit:standard","free shipping","gender:men","landtextile","material:textilemens","men's","RGroup_10554","shoes","size:true","sneakers","split_color","style:10554","swim shoes","water friendly shoe","water resisitant","water resistant","water-friendly","waterboat","watershoe","watershoes"],
"type":"Men’s Performance Marine Shoe",
"options_with_values": [{"name":"Color","position":1,"values":["Blue Pearl \/ White Sand"]},{"name":"Size","position":2,"values":["7","8","8.5","9","9.5","10","10.5","11","11.5","12","13","14","15"]}],
"price":18000,
"price_min":18000,
"price_max":18000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_001_M_AHI_BluePearlWhiteSand.png?v=1741308464",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 33819070398599,
"featured_image_alt": "Blue Pearl \/ White Sand",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_101_a8eccf0c-69d2-4cbc-a239-732e35f8bed1.jpg?v=1744996551",
"hover_image_alt": "Blue Pearl \/ White Sand",
"images": [{
"id": 33819070398599,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_001_M_AHI_BluePearlWhiteSand.png?v=1741308464",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414994718855,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_101_a8eccf0c-69d2-4cbc-a239-732e35f8bed1.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414994751623,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_104_75eed257-e33b-4869-9233-b8ad68325a80.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 1080,
"height": 1080
},{
"id": 34414994784391,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_201_d5528aee-ff6d-432b-9495-ce0193ec94f4.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414994817159,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_103_620b9adf-4df9-4fb3-8227-082c84a9d2c6.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 1080,
"height": 1080
},{
"id": 34414994849927,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_105_b5f4c6fd-00cf-4fb9-bfe4-ca53e4af3492.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 1080,
"height": 1080
},{
"id": 34414994882695,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_102_13438bec-c13c-4ee1-adef-052d67086aa9.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414994915463,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_203_807da40f-a7ca-44a5-bbc1-581b2709870d.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 1080,
"height": 1080
},{
"id": 34414994948231,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/Ahi_-_10554-ELWS_Blue_Pearl_-_White_Sand_1.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414994980999,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_202_357ad690-7a35-4d02-84a6-5a3d37022a83.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 1080,
"height": 1080
},{
"id": 34414995013767,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/Ahi_-_10554-ELWS_Blue_Pearl_-_White_Sand_2.jpg?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
},{
"id": 34414995046535,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10554_ELWS_005_M_AHI_BluePearlWhiteSand_abbdc423-31e3-441a-a47f-a7c8574dbfd5.png?v=1744996551",
"alt": "Blue Pearl \/ White Sand",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10554-ELWS-8"
}
{ $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":8323812294791,
"handle":"ahi-kai-mens-beach-sandals-seagreen-trench-blue",
"title":"'Ahi Kai - Seagreen \/ Trench Blue",
"available":true,
"tags":["71'ahi kai - m","ahi kai","Ahi Kai Sandals","ahikai","ahikai men sandals","arch:standard","beach","beach sandals","breathable","cat:sandals","Dark Soled","enhanced traction footbed","enhanced traction outsole","fit:standard","fli p flflop men","flip flops","gender:men","lightweight","material:synthetic","men","men beach sandals","men's beach sandals","mens","mens sandals","Mens sansandals","men’s","olukai beach sandals","Rgroup_10571","sandals","shearling lined","size:true","split_color","style:10571","synthetic","textile","vegan","water sandals mens","water-friendly","water-resistant","waterproof"],
"type":"Men’s Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Seagreen \/ Trench Blue"]},{"name":"Size","position":2,"values":["7","8","9","10","11","12","13","14","15"]}],
"price":12000,
"price_min":12000,
"price_max":12000,
"compare_at_price":null,"featured_image": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_001.png?v=1767641256",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 38417795121287,
"featured_image_alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_-_Seagreen_Trench_-_201.jpg?v=1767641256",
"hover_image_alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"images": [{
"id": 38417795121287,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_001.png?v=1767641256",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
},{
"id": 38417795219591,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_-_Seagreen_Trench_-_201.jpg?v=1767641256",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
},{
"id": 38417795514503,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_-_Seagreen_Trench_-_101.jpg?v=1767641257",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
},{
"id": 38417795973255,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_003.png?v=1767641258",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
},{
"id": 38417796530311,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_004.png?v=1767641258",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
},{
"id": 38417796857991,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10571_SNDE_002.png?v=1767641259",
"alt": "'Ahi Kai - Seagreen \/ Trench Blue",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10571-SNDE-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()"
>
{ $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()"
>