GuidesAPI ReferenceRelease Notes
HomeLog InHome
Guides

WidgetCustomView example

WidgetCustomView example

A full custom renderer that draws a thumbnail grid, marks read and unread items with a border color, and calls playContent on click. The destroy hook runs when the widget is torn down.

// Custom Widget Example
const customWidget = BlazeSDK.WidgetCustomView('widget-container-custom', {
  dataSource: BlazeSDK.DataSourceBuilder().labels({
    labels: 'highlights',
    orderType: 'AToZ'
  }),
  contentType: 'story',
  shouldOrderWidgetByReadStatus : true,
  customRenderer: {
    render: (contents, container, playContent) => {
      container.innerHTML = '';
      
      // Add simple grid styles
      container.style.cssText = `
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
        gap: 12px;
        padding: 16px;
      `;
      
      // Create thumbnail cards
      contents.forEach(content => {
        const card = document.createElement('div');
        card.style.cssText = `
          position: relative;
          border-radius: 12px;
          overflow: hidden;
          cursor: pointer;
          transition: transform 0.2s ease;
          border: 3px solid ${content.hasViewed ? '#22c55e' : '#f97316'};
          background: white;
          box-shadow: 0 4px 12px rgba(0,0,0,0.1);
        `;

        card.innerHTML = `
          <img src="${content.thumbnails[0].rendition.url}" 
              style="width: 100%; height: 120px; object-fit: cover;">
          <div style="padding: 8px;">
            <div style="font-size: 12px; font-weight: 600; margin-bottom: 4px; 
                        white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
              ${content.title}
            </div>
            <div style="display: flex; justify-content: space-between; align-items: center;">
              <span style="font-size: 11px; color: #666;">${content.duration}</span>
              <span style="font-size: 10px;">${content.hasViewed ? '✅' : '🆕'}</span>
            </div>
          </div>
        `;
        
        // Hover effect
        card.onmouseenter = () => card.style.transform = 'scale(1.05)';
        card.onmouseleave = () => card.style.transform = 'scale(1)';
        
        // Click to play
        card.onclick = () => playContent(content.id);
        
        container.appendChild(card);
      });
    },
    
    destroy: () => {
      console.log('Custom renderer destroyed');
    }
  },
  delegates: {
    [BlazeSDK.Delegations.onWidgetDataLoadStarted]: (e) => console.log("Custom Widget - onWidgetDataLoadStarted", e),
    [BlazeSDK.Delegations.onWidgetDataLoadCompleted]: (e) => console.log("Custom Widget - onWidgetDataLoadCompleted", e.detail),
    [BlazeSDK.Delegations.onWidgetStoryPlayerDismissed]: (e) => console.log("Custom Widget - onWidgetStoryPlayerDismissed", e.detail),
    [BlazeSDK.Delegations.onWidgetPlayerDismissed]: (e) => console.log("Custom Widget - onWidgetPlayerDismissed", e.detail),
  }
});

Related

Custom widgets | Custom widget content types | Global delegate methods


Did this page help you?