News
OluKai - Ulele
Introducing Ulele
The versatile, lightweight, and water-friendly sandal.
Shop The Story
{"id":6696749334663,
"handle":"ulele-mens-beach-sandals-clay-mustang",
"title":"Ulele - Clay \/ Mustang",
"available":true,
"tags":["01","arch:high","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","best:travel","blue-depth","cat:sandals","collection:back-to-school","collection:chief-home-officer","collection:tide-tracker","collection:wfh","color:Clay \/ Mustang","color:tan","Division-01","enhanced traction footbed","enhanced traction outsole","Everyday Wear","EXP_REC_MEN","Fatherβs Day Gifts","filpflops","fit:wide","gender:men","gifts","labor day","Ltd.","M","material:synthetic","October Trading Co.","Sand","sandals","size:true","split_color","style:10435","synthetic","Travel","Ulele-","vegan","water-friendly","wide width","YGroup_10435"],
"type":"Menβs Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Clay \/ Mustang"]},{"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\/products\/10435_1013_001_M_Ulele_ClyMus_75dc71b9-bd8d-49d1-9a69-53a8dbecf437.png?v=1762445187",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 29185385431175,
"featured_image_alt": "Clay \/ Mustang",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_103_1024x1024_cc7e6701-3a01-4233-b590-97bf52c189ab.jpg?v=1743118373",
"hover_image_alt": "Clay \/ Mustang",
"images": [{
"id": 29185385431175,
"src": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_001_M_Ulele_ClyMus_75dc71b9-bd8d-49d1-9a69-53a8dbecf437.png?v=1762445187",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 30360161091719,
"src": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_103_1024x1024_cc7e6701-3a01-4233-b590-97bf52c189ab.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 1024,
"height": 1024
},{
"id": 32280713658503,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_1013_201.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 30360161058951,
"src": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_105_1024x1024_95ef862e-51dc-4570-8b23-3bf1e56928d8.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 1024,
"height": 1024
},{
"id": 29185385562247,
"src": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_004_M_Ulele_ClyMus_d94f51e3-4f02-4767-84a2-5425f2e7df53.png?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 32380999336071,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_1013_102_M_ULELE_ClyMus.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 32380999303303,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_1013_103_M_ULELE_ClyMus.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 32280713691271,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_1013_102.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 32280713724039,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_1013_203.jpg?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
},{
"id": 29185385693319,
"src": "\/\/olukai.ca\/cdn\/shop\/products\/10435_1013_005_M_Ulele_ClyMus_ac04ca33-b1e9-47df-9675-c25ac7d3d599.png?v=1743118373",
"alt": "Clay \/ Mustang",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10435-1013-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":6696749400199,
"handle":"ulele-mens-beach-sandals-dark-shadow-black",
"title":"Ulele - Dark Shadow \/ Black",
"available":true,
"tags":["01","arch:high","as seen on tv","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","best:travel","blue-depth","cat:sandals","collection:chief-home-officer","collection:tide-tracker","collection:wfh","color:Dark Shadow \/ Black","color:grey","commercial","Division-01","enhanced traction footbed","enhanced traction outsole","Everyday Wear","EXP_REC_MEN","fisherman","fisherman sandals","fit:wide","gender:men","Ltd.","M","material:synthetic","men s flipslops","Mens sansandals","October Trading Co.","RGroup_10435","Sand","sandals","seen on tv","size:true","split_color","style:10435","synthetic","Travel","tv","tv ad","uelele","ulee flip","Ulele-","uleleulele","uleue","ulule","vegan","water-friendly","wide width","widewidh","YGroup_10435"],
"type":"Menβs Water-Ready Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Dark Shadow \/ Black"]},{"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_6C40_001_M_Ulele_DksBlk.png?v=1762445187",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34414949499015,
"featured_image_alt": "Dark Shadow \/ Black",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_101_M_Ulele_DksBlk_Web_Opt.jpg?v=1744996238",
"hover_image_alt": "Dark Shadow \/ Black",
"images": [{
"id": 34414949499015,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_001_M_Ulele_DksBlk.png?v=1762445187",
"alt": "Dark Shadow \/ Black",
"width": 2000,
"height": 2000
},{
"id": 34414949531783,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_101_M_Ulele_DksBlk_Web_Opt.jpg?v=1744996238",
"alt": "Dark Shadow \/ Black",
"width": 2000,
"height": 2000
},{
"id": 34414949564551,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_004_M_Ulele_DksBlk.png?v=1744996238",
"alt": "Dark Shadow \/ Black",
"width": 2000,
"height": 2000
},{
"id": 34414949597319,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_102_M_Ulele_DksBlk_Web_Opt.jpg?v=1744996238",
"alt": "Dark Shadow \/ Black",
"width": 2000,
"height": 2000
},{
"id": 34414949630087,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_6C40_005_M_Ulele_DksBlk.png?v=1744996238",
"alt": "Dark Shadow \/ Black",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10435-6C40-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":6629497667719,
"handle":"ulele-mens-beach-sandals-stone",
"title":"Ulele - Stone",
"available":true,
"tags":["01","arch:high","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","best:travel","blue-depth","bundle|1|3|0|2","cat:sandals","collection:chief-home-officer","collection:HGG-Slider-M","collection:tide-tracker","collection:wfh","color:grey","color:Stone","Division-01","enhanced traction footbed","enhanced traction outsole","Everyday Wear","EXP_REC_MEN","fit:wide","gender:men","labor day","Ltd.","M","material:synthetic","men s flipslops","Mens sansandals","October Trading Co.","RGroup_10435","Sand","sandals","size:true","split_color","style:10435","synthetic","Travel","uelele","ulee flip","Ulele-","uleue","ulule","vegan","water-friendly","wide width","YGroup_10435"],
"type":"Menβs Water-Ready Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Stone"]},{"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_4Q4Q_001_M_Ulele_StnStn_fe5b5388-2e67-4f4f-a4cc-5696af418e10.png?v=1762443940",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34414952480903,
"featured_image_alt": "Stone",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_101.jpg?v=1746706343",
"hover_image_alt": "Stone",
"images": [{
"id": 34414952480903,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_001_M_Ulele_StnStn_fe5b5388-2e67-4f4f-a4cc-5696af418e10.png?v=1762443940",
"alt": "Stone",
"width": 2000,
"height": 2000
},{
"id": 34414952579207,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_101.jpg?v=1746706343",
"alt": "Stone",
"width": 1023,
"height": 1024
},{
"id": 34414952677511,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_4Q4Q_103_565fe995-ccad-47ab-8207-504f510f6250.jpg?v=1746706343",
"alt": "Stone",
"width": 1024,
"height": 1024
},{
"id": 34414952775815,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_003_M_Ulele_StnStn.png?v=1746706343",
"alt": "Stone",
"width": 2000,
"height": 2000
},{
"id": 34414952874119,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_104_5eecee93-74b3-4795-a42e-f9babcca37c5.jpg?v=1746706343",
"alt": "Stone",
"width": 2000,
"height": 2000
},{
"id": 34414952972423,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10465_4Q4Q_102_M_ULELE_StoneStone.jpg?v=1746706343",
"alt": "Stone",
"width": 2000,
"height": 2000
},{
"id": 34414953070727,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_004_M_Ulele_StnStn.png?v=1746706343",
"alt": "Stone",
"width": 2000,
"height": 2000
},{
"id": 34414953136263,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_4Q4Q_005_M_Ulele_StnStn.png?v=1746706343",
"alt": "Stone",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10435-4Q4Q-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":6696749367431,
"handle":"ulele-mens-beach-sandals-slate-blue-charcoal",
"title":"Ulele - Slate Blue \/ Charcoal",
"available":true,
"tags":["01","arch:high","beach sandals","Beach\/Boat","best:beach_boat","best:everday_wear","best:travel","blue-depth","cat:sandals","collection:chief-home-officer","collection:tide-tracker","collection:wfh","color:blue","color:Slate Blue \/ Charcoal","Division-01","enhanced traction footbed","enhanced traction outsole","Everyday Wear","EXP_REC_MEN","fit:wide","gender:men","labor day","Ltd.","M","material:synthetic","men s flipslops","Mens sansandals","October Trading Co.","RGroup_10435","Sand","sandals","size:true","split_color","style:10435","synthetic","Travel","uelele","ulee flip","Ulele-","uleue","ulule","vegan","water-friendly","wide width","widewidh","YGroup_10435"],
"type":"Menβs Water-Ready Beach Sandals",
"options_with_values": [{"name":"Color","position":1,"values":["Slate Blue \/ 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_7S26_001_M_Ulele_SltbChr.png?v=1762445187",
"featured_image_aspect_ratio": 1.0,
"featured_image_width": 2000,
"featured_image_height": 2000,
"featured_image_id": 34414949761159,
"featured_image_alt": "Slate Blue \/ Charcoal",
"hover_image": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_101_554d31ff-0c73-4b9b-b935-f944ab9a8475.jpg?v=1744996241",
"hover_image_alt": "Slate Blue \/ Charcoal",
"images": [{
"id": 34414949761159,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_001_M_Ulele_SltbChr.png?v=1762445187",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34414949793927,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_101_554d31ff-0c73-4b9b-b935-f944ab9a8475.jpg?v=1744996241",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34414949826695,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_102_M_Ulele_SltbChar_Web_Opt_1024x1024_f1946ce0-afb1-467b-a579-26983500873b.jpg?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 1024,
"height": 1024
},{
"id": 34414949859463,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_004_M_Ulele_SltbChr.png?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34414949892231,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_104_27e591d9-44c7-4b81-ba58-4a2882b2efc9.jpg?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2001
},{
"id": 34414949924999,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_105_1724a753-f48c-4bd4-9f59-0333f977ad61.jpg?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34414949957767,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_104_c9cc79e1-98d0-4368-904a-4436e87bf914.jpg?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
},{
"id": 34414949990535,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_101_1024x1024_c319504f-69f6-4836-baef-b1e63f4d184f.jpg?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 1024,
"height": 1024
},{
"id": 34414950023303,
"src": "\/\/olukai.ca\/cdn\/shop\/files\/10435_7S26_005_M_Ulele_SltbChr.png?v=1744996242",
"alt": "Slate Blue \/ Charcoal",
"width": 2000,
"height": 2000
}],
"plp_image_order_positions": "",
"sku": "10435-7S26-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()"
>