Resize Block Action

Helps adjust the content according to type of block we create.

Description

The resizeBlock action allows a custom block to communicate its content height to the parent app. This ensures that the container (especially in Popup or Bottom Sheet layouts) expands or shrinks to fit the content perfectly.

This is commonly used for:

Expanding a block when a "Read More" section is toggled.

Shrinking a block after a form is submitted.

Adjusting for dynamic content like product reviews or carousels.

Function Signature

Superfans.actions.resizeBlock({});

Structure of Response

StatusResponse
Success{ "status": "success", "message": "Action executed" }
Invalid Params{ "status": "error", "errorId": 400, "errorHandle": "invalid-params", "message": "Invalid params" }
Unexpected Error{ "status": "error", "errorId": 500, "errorHandle": "unknown-error", "message": "Something unexpected happened" }

Example Usage

const tabsContainer = document.getElementById("tabsContainer");
const tabContent = document.getElementById("tabContent");
// Array of tab objects with title + HTML content
const tabData = [
  {
    title: "Overview",
    content: `<t5>This product is designed to offer exceptional quality and performance. Suitable for a wide range of uses, it guarantees customer satisfaction.</t5>`
  },
  {
    title: "Specifications",
    content: `<ul><li><t5>Material: 100% Organic Cotton</t5></li><li><t5>Size: Available in S, M, L, XL</t5></li><li><t5>Weight: 1.2kg</t5></li></ul>`
  },
  {
    title: "Features",
    content: `<t4>Key features include:</t4><ul><li><t5>Durability</t5></li><li><t5>Eco-Friendly Materials</t5></li><li><t5>Lightweight Design</t5></li></ul>`
  },
  {
    title: "Reviews",
    content: `<t5>"Absolutely loved it! Will buy again!"</t5><br><t5>"Exceeded expectations. Highly recommend!"</t5>`
  },
  {
    title: "FAQ",
    content: `<t5><strong>Q:</strong> Is this product machine washable?</p><p><strong>A:</strong> Yes, it is fully machine washable using a gentle cycle.</t5>`
  },
];
// Trigger Superfans to recalculate iframe height
async function resizeBlock() {
  try {
    await Superfans.actions.resizeBlock();
  } catch (err) {
    Superfans.actions.showToast({
      title: "Resize Error",
      message: err.message || "Failed to resize block",
    });
  }
}
// Build tab header items dynamically
function createTabs() {
  tabsContainer.innerHTML = ""; // Clear existing
  tabData.forEach((tab, index) => {
    const tabItem = document.createElement("div");
    tabItem.className = "tab-item";
    tabItem.innerHTML = `<t4>${tab.title}</t4>`;
    // Add click listener to switch tab
    tabItem.addEventListener("click", () => showTab(index));
    tabsContainer.appendChild(tabItem);
  });
}
// Show selected tab content and highlight active tab
async function showTab(index) {
  // Update active tab style
  document.querySelectorAll(".tab-item").forEach((tab, i) => {
    tab.classList.toggle("active", i === index);
    if (i === index) {
      tab.scrollIntoView({ behavior: "smooth", inline: "center" });
    }
  });
  // Inject selected tab HTML
  tabContent.innerHTML = tabData[index].content;
  // Resize container to fit content
  await resizeBlock();
}
// Initialize the tab section on load
(async function initTabs() {
  try {
    if (!Array.isArray(tabData)) throw new Error("Tab data must be an array");
    createTabs();      // Build headers
    await showTab(0);  // Show first tab by default
  } catch (error) {
    console.error("❌ Tab Error:", error);
    Superfans.actions.showToast({
      title: "Error",
      message: "Unable to load tabs",
    });
  }
})();
<!-- Main wrapper -->
<div class="container">
    <!-- Tab titles will be rendered here -->
    <div class="tabs-container" id="tabsContainer"></div>
    <!-- Tab content area -->
    <div class="tab-content" id="tabContent">
        <t5>Select a tab to see the description</t5>
    </div>
</div>
/* Outer container for tab block */
.container {
  display: flex;
  flex-direction: column;
  padding: 14px;
}
/* Horizontal scrollable tab header section */
.tabs-container {
  display: flex;
  overflow-x: auto;
  gap: 12px;
  height: 40px; /* Ensures consistent height */
  align-items: center;
  -webkit-overflow-scrolling: touch; /* iOS smooth scroll */
  scrollbar-width: none; /* Firefox: hide scrollbar */
}
/* Hide scrollbar for webkit browsers */
.tabs-container::-webkit-scrollbar {
  display: none;
}
/* Each clickable tab label */
.tab-item {
  font-size: 14px;
  font-weight: 300;
  white-space: nowrap;
  padding: 2px 2px;
  cursor: pointer;
}
/* Style when tab is active/selected */
.tab-item.active {
  font-weight: 600;
  border-bottom: 2px solid #000;
  color: #000;
}
/* Main content section that updates on tab click */
.tab-content {
  width: 100%;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
}
/* Content list formatting */
.tab-content ul {
  padding-left: 16px;
  margin: 10px 0;
}
.tab-content li {
  margin-bottom: 6px;
}

Best Practices

  1. Avoid Infinite Loops: Don't call resizeBlock inside a generic window.onresize event as it might trigger recursive layout changes.
  2. Debounce: If content changes rapidly (like an animation), debounce the function call to avoid performance lag on the device.

Caveats

  1. Layout Type: This action is most effective for Popups and Bottom Sheets. For inline blocks, the app may ignore resize requests depending on the grid configuration.