⏳ Last Day 49% OFF - Beginner-Friendly DIY – Hand, Everyday Comfort, Best Value

$29.99  - $129.99
/** * 优惠码组件模型类 * 处理优惠码的显示和交互逻辑 */ class SpzCustomDiscountCodeModel extends SPZ.BaseElement { constructor(element) { super(element); // 复制按钮和内容的类名 this.copyBtnClass = "discount_code_btn" this.copyClass = "discount_code_value" } isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } buildCallback() { // 初始化服务 this.action_ = SPZServices.actionServiceForDoc(this.element); this.templates_ = SPZServices.templatesForDoc(this.element); this.xhr_ = SPZServices.xhrFor(this.win); } /** * 渲染优惠码组件 * @param {Object} data - 渲染数据 */ doRender_(data) { return this.templates_ .findAndRenderTemplate(this.element, Object.assign(this.getDefaultData(), data) ) .then((el) => { this.clearDom(); this.element.appendChild(el); // 绑定复制代码功能 this.copyCode(el, data); }); } /** * 获取渲染模板 * @param {Object} data - 渲染数据 */ getRenderTemplate(data) { const renderData = Object.assign(this.getDefaultData(), data); return this.templates_ .findAndRenderTemplate(this.element, renderData) .then((el) => { this.clearDom(); return el; }); } /** * 清除DOM内容 */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * 获取默认数据 * @returns {Object} 默认数据对象 */ getDefaultData() { return { isMobile: appDiscountUtils.judgeMobile(), isRTL: appDiscountUtils.judgeRTL(), image_domain: this.win.SHOPLAZZA.image_domain, copyBtnClass: this.copyBtnClass, copyClass: this.copyClass } } /** * 复制优惠码功能 * @param {Element} el - 当前元素 */ copyCode(el) { const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`); if (copyBtnList.length > 0) { copyBtnList.forEach(item => { item.onclick = async () => { // 确保获取正确的元素和内容 const codeElement = item.querySelector(`.${this.copyClass}`); if (!codeElement) return; // 获取纯文本内容 const textToCopy = codeElement.innerText.trim(); // 尝试使用现代API,如果失败则使用备用方案 try { if (navigator.clipboard && navigator.clipboard.writeText) { await navigator.clipboard.writeText(textToCopy); } else { throw new Error('Clipboard API not available'); } // 显示复制成功提示 this.showCopySuccessToast(textToCopy, el); } catch (err) { console.error('Modern clipboard API failed, trying fallback...', err); // 使用备用复制方案 this.fallbackCopy(textToCopy, el); } const discountId = item.dataset["discountId"]; // 跳转决策: is_redirection + link(可选覆盖) const setting = { is_redirection: item.dataset["redirection"] === "true", link: item.dataset["link"], }; const landingUrl = `/promotions/discount-default/${discountId}`; const finalUrl = appDiscountUtils.resolveDiscountHref(setting, landingUrl); if (finalUrl && appDiscountUtils.inProductBody(this.element)) { this.win.open(finalUrl, '_blank', 'noopener'); } } }) } } /** * 使用 execCommand 的复制方案 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ fallbackCopy(codeText, el) { const textarea = this.win.document.createElement('textarea'); textarea.value = codeText; // 设置样式使文本框不可见 textarea.style.position = 'fixed'; textarea.style.left = '-9999px'; textarea.style.top = '0'; // 添加 readonly 属性防止移动端虚拟键盘弹出 textarea.setAttribute('readonly', 'readonly'); this.win.document.body.appendChild(textarea); textarea.focus(); textarea.select(); try { this.win.document.execCommand('copy'); // 显示复制成功提示 this.showCopySuccessToast(codeText, el); } catch (err) { console.error('Copy failed:', err); } this.win.document.body.removeChild(textarea); } /** * 创建 Toast 元素 * @returns {Element} 创建的 Toast 元素 */ createToastEl_() { const toast = document.createElement('ljs-toast'); toast.setAttribute('layout', 'nodisplay'); toast.setAttribute('hidden', ''); toast.setAttribute('id', 'discount-code-toast'); toast.style.zIndex = '1051'; return toast; } /** * 挂载 Toast 元素到 body * @returns {Element} 挂载的 Toast 元素 */ mountToastToBody_() { const existingToast = this.win.document.getElementById('discount-code-toast'); if (existingToast) { return existingToast; } const toast = this.createToastEl_(); this.win.document.body.appendChild(toast); return toast; } /** * 复制成功的提醒 * @param {string} codeText - 要复制的文本 * @param {Element} el - 当前元素 */ showCopySuccessToast(codeText, el) { const $toast = this.mountToastToBody_(); SPZ.whenApiDefined($toast).then(toast => { toast.showToast("Discount code copied !"); this.codeCopyInSessionStorage(codeText); }); } /** * 复制优惠码成功后要存一份到本地存储中,购物车使用 * @param {string} codeText - 要复制的文本 */ codeCopyInSessionStorage(codeText) { try { sessionStorage.setItem('other-copied-coupon', codeText); } catch (error) { console.error(error) } } } // 注册自定义元素 SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
/** * Custom discount code component that handles displaying and managing discount codes * @extends {SPZ.BaseElement} */ class SpzCustomDiscountCode extends SPZ.BaseElement { constructor(element) { super(element); // API endpoint for fetching discount codes this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list"; // Debounce timer for resize events this.timer = null; // Current variant ID this.variantId = "081e4c5e-db19-4ae3-9936-5cdf67aab7f4"; // Store discount code data this.discountCodeData = {} } /** * Check if layout is supported * @param {string} layout - Layout type * @return {boolean} */ isLayoutSupported(layout) { return layout == SPZCore.Layout.LOGIC; } /** * Initialize component after build */ buildCallback() { this.templates_ = SPZServices.templatesForDoc(); this.viewport_ = this.getViewport(); // Bind methods to maintain context this.render = this.render.bind(this); this.resize = this.resize.bind(this); this.switchVariant = this.switchVariant.bind(this); } /** * Setup component when mounted */ mountCallback() { this.getData(); // Add event listeners this.viewport_.onResize(this.resize); this.win.document.addEventListener('dj.variantChange', this.switchVariant); } /** * Cleanup when component is unmounted */ unmountCallback() { this.viewport_.removeResize(this.resize); this.win.document.removeEventListener('dj.variantChange', this.switchVariant); // 清除定时器 if (this.timer) { clearTimeout(this.timer); this.timer = null; } } /** * Handle resize events with debouncing */ resize() { if (this.timer) { clearTimeout(this.timer) this.timer = null; } this.timer = setTimeout(() => { if (appDiscountUtils.inProductBody(this.element)) { this.render(); } else { this.renderSkeleton(); } }, 200); } /** * Handle variant changes * @param {Event} event - Variant change event */ switchVariant(event) { const variant = event.detail.selected; if (variant.product_id == 'a6736890-7f04-4b41-b45c-c8f57412fe96' && variant.id != this.variantId) { this.variantId = variant.id; this.getData(); } } /** * Fetch discount code data from API */ getData() { if (appDiscountUtils.inProductBody(this.element)) { const reqBody = { product_id: "a6736890-7f04-4b41-b45c-c8f57412fe96", variant_id: this.variantId, product_type: "default", } if (!reqBody.product_id || !reqBody.variant_id) return; this.discountCodeData = {}; this.win.fetch(this.getDiscountCodeApi, { method: "POST", body: JSON.stringify(reqBody), headers: { "Content-Type": "application/json" } }).then(async (response) => { if (response.ok) { let data = await response.json(); if (data.list && data.list.length > 0) { data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config); // Format timestamps to local timezone const zone = this.win.SHOPLAZZA.shop.time_zone; data.list = data.list.map(item => { if(+item.ends_at !== -1) { item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone); } item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone); return item; }); } this.discountCodeData = data; this.render(); } else { this.clearDom(); } }).catch(err => { console.error("discount_code", err) this.clearDom(); }); } else { this.renderSkeleton(); } } /** * Clear component DOM except template */ clearDom() { const children = this.element.querySelector('*:not(template)'); children && SPZCore.Dom.removeElement(children); } /** * Render discount codes with formatted dates */ render() { // Render using discount code model SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => { renderApi.doRender_({ discountCodeData: this.discountCodeData }) }).catch(err => { this.clearDom(); }) } renderSkeleton() { // Render template for non-product pages this.templates_ .findAndRenderTemplate(this.element, { isMobile: appDiscountUtils.judgeMobile() }) .then((el) => { this.clearDom(); this.element.appendChild(el); }) .catch(err => { this.clearDom(); }); } } // Register custom element SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
Style🎁Buy 3— Save 15% OFF & Free Shipping:  🐠 Clownfish
Finished Size:  Approx. 15 × 20 cm / 5.9 × 7.9 in
Quantity
Free worldwide shipping
Free returns
Sustainably made
Secure payments

Description

❤️TIPS: All goods are authentic, with genuine patents, counterfeit must be investigated! Customers, please identify our products!

SHIPPING WORLDWIDE. 
💯Payments Via PayPal® and CreditCard.
⭐Fast refund Guarantee>> Partial or full refund depends on the situation.
📦Orders will not incur additional customs duties.

🎁Don't forget to buy some for your family or friends as it's a unique gift idea.❤️❤️❤️



🐠 Bring Ocean Magic Into Your Christmas Home

Celebrate the season with a decoration that feels playful, festive and truly personal. The DIY Ocean Clownfish Christmas Yarn Art Kit combines soft yarn textures, cheerful ocean details and traditional holiday colors to create an adorable handmade display filled with warmth and character.

From cheerful clownfish and sweet sea turtles to dolphins, octopuses, seahorses, crabs and more, each design brings together ocean charm and Christmas spirit in one unforgettable display. It’s more than holiday décor—it’s a creative Christmas tradition you’ll love making year after year.

Perfect for yarn-art lovers, holiday crafters, ocean enthusiasts and anyone who enjoys meaningful handmade décor.

We don’t run sales like this very often, but today is the last day to grab yours for just $19.99.

After tonight, the price goes back up to $39.19.


✨ Layer by Layer, Create an Ocean Christmas Treasure

Designed with carefully arranged yarn components and tiered ruffled layers, this DIY kit creates a richly textured decoration that stands out from ordinary Christmas ornaments.

The cheerful orange clownfish sits above festive layers of deep green, Christmas red, aqua blue and cream. Seashells, starfish, coral-inspired accents, pearls, a plaid bow and a small bell bring ocean charm and holiday spirit together in one unforgettable design.

✔ Soft, dimensional yarn construction
✔ Layered red, green and aqua ruffles
✔ Shell, starfish and pearl decorations
✔ Festive plaid bow and hanging bell
✔ Adorable ocean-inspired Christmas design


💚 Enjoy the Joy of Slow, Mindful Crafting

Whether you’re crafting quietly by yourself or making memories with family, every step adds more life and personality to your chosen ocean character. Arrange the parts, build the layered base, stitch the sections in place and finish with the decorative holiday details.

No advanced experience is required—just enjoy the soothing process and the satisfaction of creating something special with your own hands.

Perfect for:

  • Quiet winter evenings
  • Weekend crafting sessions
  • Parent-child creative time
  • Christmas hobby projects
  • Screen-free holiday relaxation


🏡 Made to Brighten Every Christmas Corner

Once completed, your handmade clownfish becomes a cheerful seasonal centerpiece that adds color and personality wherever it is displayed.

Place it on a shelf, mantel, side table or holiday display to create a cozy ocean-inspired Christmas atmosphere.

Perfect for:

Living Room
Fireplace Mantel
Entryway Console
Dining Table
Bookshelf
Office Desk
Craft Room
Christmas Display Shelf


🎁 A Meaningful Gift Made With Love

Looking for a thoughtful Christmas gift?

This DIY yarn art collection is perfect for crafters, sea-life lovers, holiday decorators and anyone who appreciates charming handmade pieces. Whether given as a creative kit or presented as a finished decoration, it’s a heartfelt gift that feels personal and memorable.

Great for:

🎄 Christmas craft lovers
🧶 Handmade hobby enthusiasts
🌊 Ocean and marine-life fans
🎁 Thoughtful holiday gift giving
👩👧 Family crafting time
🏡 Unique seasonal home décor lovers


📦 Everything You Need to Start Crafting

Each DIY Ocean Christmas Yarn Art Kit includes the materials needed to create one festive ocean-style decoration.

Package Includes:

🌊 1 × DIY Ocean Christmas Yarn Art Kit
🧶 Pre-made yarn art components
🎄 Layered festive ruffle sections
🐚 Shell, starfish and ocean-themed embellishments
🎀 Plaid bow and decorative bell
✨ Pearl-style accents and finishing details
📖 Easy-to-follow instruction guide
📄 Pattern / layout reference

Open the kit, choose your style, follow the steps and enjoy bringing your handmade holiday ocean character to life.


Frequently Asked Questions

1. Is this a finished decoration or a DIY kit?

This is a DIY yarn art kit designed for you to assemble and decorate yourself. The completed product images are shown as display inspiration.

2. Is this traditional crochet?

The project uses yarn-based components and stitching techniques, but you do not need to crochet the entire design from raw yarn. The prepared shapes and illustrated guide make assembly easier and more approachable.

3. Is it suitable for beginners?

Yes. The project is designed to be beginner-friendly. The pattern and step-by-step instructions guide you through arranging, stitching and decorating each section.

4. What is included in the kit?

The kit includes the clownfish components, layered yarn sections, assembly materials, decorative ocean accents, festive trims, pattern sheet and instructions required to complete the design.

5. Will my finished clownfish look exactly like the photos?

Because every decoration is assembled by hand, small differences in stitching, layer placement and decoration position are completely normal. These variations make each finished piece unique.

6. Is the project difficult or time-consuming?

The project can be completed at your own pace. Work on one section at a time and enjoy the process as a relaxing holiday activity rather than rushing to finish it.

7. Can children make this project?

Older children can enjoy the project with adult supervision, especially when using the needle or attaching smaller decorative pieces.

8. Can the finished decoration be reused every Christmas?

Yes. Store it carefully in a clean, dry place after the holidays, away from moisture and direct sunlight. It can be displayed again for many Christmas seasons.

9. Where can I display the finished product?

It is ideal for mantels, bookshelves, entryway tables, desks, holiday display shelves, side tables and craft-room decorations.

10. Is it suitable as a gift?

Yes. It makes a thoughtful gift either as an enjoyable DIY project or as a completed handmade Christmas decoration.


❤️Thank you very much for visiting our store. Have a nice shopping day❤️

HOW TO PAY

✅Payments Via PayPal®Debit and CreditCard.Add to cart first, and Check out, then select Shipping method and Payment method.
✅If you checkout with a Debit / Credit Card, just enter your * Card Number, * Expiration Date, and * Secure Code.

Certification

✈WORLDWIDE SHIPPING✈

💖 No Extra Tax, Shipping Calculated at Checkout.
🚢 Shipping>>Worldwide Express Shipping Available.

WHY US?

  • We have Quality Control department which help us to keep our promise!

  • Price is Always Competitive.

  • Awesome Customer Service.

  • Amazing products along with High Quality.

  • Read reviews from our lovely customers.

OUR GUARANTEE

📦Insured Worldwide Shipping: Each order includes real-time tracking details and insurance coverage in the unlikely event that a package gets lost or stolen in transit.

💰Money-Back Guarantee: If your items arrive damaged within 90 days of normal usage, we will gladly issue out a replacement or refund.

✉️24/7 Customer Support: We have a team of live reps ready to help and answer any questions you have within a 24-hour time frame, 7 days a week.

🔒Safe & Secure Checkouts: We use state-of-the-art SSL Secure encryption to keep your personal and financial information 100% protected.

🔒100% Risk-Free Purchase: If you bought it and felt that it is not for you, don't worry. Just hit the Contact us button and send us a message, and we will make it right by offering you a replacement or refund. 100% Simple & Risk-Free process.