Skip to main content

GL Carousel Banner

Version: 1.0.5
Package: @gift-card-market/gl-carousel-banner
Last Updated: December 24, 2025


📖 Table of Contents


🎯 Overview

GL Carousel Banner is a versatile, high-performance carousel component designed for the Gift Card Marketplace. It supports both React and Vanilla JavaScript implementations, making it framework-agnostic and easy to integrate into any project.

Key Features

Dual Implementation - React component & Web Component (Vanilla JS)
Auto-rotation - Configurable automatic slide transitions
Smooth Animations - Customizable transition speeds
Pause on Hover - User-friendly interaction
Programmatic Control - Full API for slide navigation
Event System - Listen to slide changes
Responsive Design - Mobile-friendly and adaptive
TypeScript Support - Full type definitions included
Customizable Styling - CSS variables for theming


📦 Installation

From GitHub Packages

First, configure npm to use GitHub Packages for @gift-card-market scope:

# Create or edit .npmrc in your project root
echo "@gift-card-market:registry=https://npm.pkg.github.com" >> .npmrc

Then install the package:

npm install @gift-card-market/gl-carousel-banner

Peer Dependencies

This package requires React as a peer dependency:

npm install react react-dom

🚀 Quick Start

React Implementation

1. Install Required Dependencies

npm install react react-dom
npm install slick-carousel

2. Import Styles

import '@gift-card-market/gl-carousel-banner/style.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

3. Import Component and Types

import { 
GlCarouselBanner,
CarouselBannerEvents,
type GlCarouselBannerHandle,
type GlCarouselBannerItem
} from "@gift-card-market/gl-carousel-banner";

4. Basic Usage Example

import { useRef, useState } from 'react';
import {
GlCarouselBanner,
type GlCarouselBannerHandle,
type GlCarouselBannerItem
} from "@gift-card-market/gl-carousel-banner";
import '@gift-card-market/gl-carousel-banner/style.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';

function App() {
const carouselRef = useRef<GlCarouselBannerHandle>(null);
const [currentSlide, setCurrentSlide] = useState(0);

// Sample data
const slides: GlCarouselBannerItem[] = [
{
title_text: 'Welcome to <strong>Our Store</strong>',
title_text_emphasis_color: '#FF6600',
main_text: '<p>Discover amazing products and services</p>',
button_text: 'Shop Now',
button_color: '#0052CC',
button_text_color: '#FFFFFF',
button_link: 'https://example.com/shop',
background_image: 'https://example.com/bg1.svg',
main_image: 'https://example.com/product1.png',
main_image_link: 'https://example.com/product1'
},
{
title_text: 'Special <strong><em>Offer</em></strong>',
main_text: '<p>Get 50% off on selected items</p>',
button_text: 'Learn More',
button_color: '#EE3D84',
button_text_color: '#FFFFFF',
button_link: 'https://example.com/offers',
background_image: 'https://example.com/bg2.svg',
main_image: 'https://example.com/offer.png'
}
];

// Control handlers
const handleNext = () => {
carouselRef.current?.nextSlide();
};

const handlePrevious = () => {
carouselRef.current?.previousSlide();
};

const handleGoToSlide = (index: number) => {
carouselRef.current?.goToSlide(index);
};

return (
<div>
<GlCarouselBanner
ref={carouselRef}
items={slides}
autoRotate={true}
rotationSpeed={3}
transitionSpeed={0.5}
pauseOnHover={true}
/>

<div style={{ marginTop: '20px', textAlign: 'center' }}>
<button onClick={handlePrevious}>Previous</button>
<button onClick={handleNext}>Next</button>
<button onClick={() => handleGoToSlide(0)}>Go to First</button>
</div>
</div>
);
}

export default App;

Vanilla JavaScript Implementation

1. Include Scripts and Styles

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GL Carousel Banner Demo</title>

<!-- Include CSS -->
<link rel="stylesheet"
href="./node_modules/@gift-card-market/gl-carousel-banner/dist/browser/gl-carousel-banner.css">
</head>
<body>
<div id="carousel-container"></div>

<!-- Include JS -->
<script src="./node_modules/@gift-card-market/gl-carousel-banner/dist/browser/gl-carousel-banner.global.js"></script>

<script type="module">
// Your code here
</script>
</body>
</html>

2. Basic Usage Example

<script type="module">
// Sample data
const carouselData = [
{
title_text: 'Welcome to <strong>Our Store</strong>',
title_text_emphasis_color: '#FF6600',
main_text: '<p>Discover amazing products and services</p>',
button_text: 'Shop Now',
button_color: '#0052CC',
button_text_color: '#FFFFFF',
button_link: 'https://example.com/shop',
background_image: 'https://example.com/bg1.svg',
main_image: 'https://example.com/product1.png',
main_image_link: 'https://example.com/product1'
},
{
title_text: 'Special <strong><em>Offer</em></strong>',
main_text: '<p>Get 50% off on selected items</p>',
button_text: 'Learn More',
button_color: '#EE3D84',
button_text_color: '#FFFFFF',
button_link: 'https://example.com/offers',
background_image: 'https://example.com/bg2.svg',
main_image: 'https://example.com/offer.png'
}
];

// Create carousel element
const carousel = document.createElement('gl-carousel-banner');

// Set attributes
carousel.setAttribute('autoRotate', 'true');
carousel.setAttribute('rotationSpeed', '3');
carousel.setAttribute('transitionSpeed', '0.5');
carousel.setAttribute('pauseOnHover', 'true');

// Append to container
document.getElementById('carousel-container').appendChild(carousel);

// Wait for component to be defined, then set items
customElements.whenDefined('gl-carousel-banner').then(() => {
// Set items as property
carousel.items = carouselData;

console.log('✅ Carousel initialized successfully!');
});
</script>

3. Advanced Vanilla JS Example with Controls

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>GL Carousel Banner - Full Example</title>
<link rel="stylesheet"
href="./node_modules/@gift-card-market/gl-carousel-banner/dist/browser/gl-carousel-banner.css">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
}

.controls {
display: flex;
gap: 10px;
justify-content: center;
margin: 20px 0;
}

button {
padding: 10px 20px;
background: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: transform 0.2s;
}

button:hover {
transform: scale(1.05);
}

.info-box {
background: white;
padding: 20px;
border-radius: 12px;
margin-top: 20px;
text-align: center;
}
</style>
</head>
<body>
<h1 style="color: white; text-align: center;">GL Carousel Banner Demo</h1>

<div class="controls">
<button id="prevBtn">⬅️ Previous</button>
<button id="pauseBtn">⏸️ Pause</button>
<button id="resumeBtn">▶️ Resume</button>
<button id="nextBtn">Next ➡️</button>
</div>

<div id="carousel-container"></div>

<div class="info-box">
<p>Current Slide: <strong id="currentSlide">1</strong></p>
</div>

<script src="./node_modules/@gift-card-market/gl-carousel-banner/dist/browser/gl-carousel-banner.global.js"></script>
<script type="module">
const carouselData = [
{
title_text: 'Slide 1: <strong>Welcome</strong>',
main_text: '<p>This is the first slide</p>',
button_text: 'Get Started',
button_color: '#0052CC',
button_text_color: '#FFFFFF',
button_link: '#',
background_image: 'https://example.com/bg1.svg',
main_image: 'https://example.com/image1.png'
},
{
title_text: 'Slide 2: <strong>Features</strong>',
main_text: '<p>Explore amazing features</p>',
button_text: 'Learn More',
button_color: '#EE3D84',
button_text_color: '#FFFFFF',
button_link: '#',
background_image: 'https://example.com/bg2.svg',
main_image: 'https://example.com/image2.png'
},
{
title_text: 'Slide 3: <strong>Contact</strong>',
main_text: '<p>Get in touch with us</p>',
button_text: 'Contact Us',
button_color: '#FFE606',
button_text_color: '#183238',
button_link: '#',
background_image: 'https://example.com/bg3.svg',
main_image: 'https://example.com/image3.png'
}
];

const carousel = document.createElement('gl-carousel-banner');
carousel.setAttribute('autoRotate', 'true');
carousel.setAttribute('rotationSpeed', '3');
carousel.setAttribute('transitionSpeed', '0.5');
carousel.setAttribute('pauseOnHover', 'true');

document.getElementById('carousel-container').appendChild(carousel);

customElements.whenDefined('gl-carousel-banner').then(() => {
carousel.items = carouselData;

// Setup event listeners after a small delay
setTimeout(() => {
document.getElementById('prevBtn').addEventListener('click', () => {
carousel.previousSlide();
updateCurrentSlide();
});

document.getElementById('nextBtn').addEventListener('click', () => {
carousel.nextSlide();
updateCurrentSlide();
});

document.getElementById('pauseBtn').addEventListener('click', () => {
carousel.pause();
});

document.getElementById('resumeBtn').addEventListener('click', () => {
carousel.resume();
});
}, 200);
});

function updateCurrentSlide() {
const current = carousel.getCurrentSlide();
if (current !== undefined) {
document.getElementById('currentSlide').textContent = current + 1;
}
}

// Update current slide periodically
setInterval(updateCurrentSlide, 200);

// Listen to slide change events
carousel.addEventListener('slideChange', (event) => {
console.log('Slide changed to:', event.detail);
document.getElementById('currentSlide').textContent = event.detail + 1;
});

// Make carousel available in console for testing
window.carousel = carousel;
</script>
</body>
</html>

📚 API Reference

Exports

The package exports the following:

import { 
GlCarouselBanner, // React Component
CarouselBannerEvents, // Event name constants
type GlCarouselBannerHandle, // Type for ref
type GlCarouselBannerItem // Type for slide data
} from "@gift-card-market/gl-carousel-banner";

CarouselBannerEvents Object

Event name constants for listening to carousel events:

CarouselBannerEvents = {
CAROUSEL_LOADED: "gl:carousel-loaded",
SLIDE_CHANGED: "gl:slide-changed",
CAROUSEL_PAUSED: "gl:carousel-paused",
CAROUSEL_RESUMED: "gl:carousel-resumed",
ERROR: "gl:error"
}

See Events section for detailed usage.

React Props

PropTypeDefaultDescription
itemsGlCarouselBannerItem[]RequiredArray of carousel slide data
autoRotatebooleantrueEnable/disable automatic slide rotation
rotationSpeednumber3Time in seconds between auto-rotations
transitionSpeednumber0.5Transition animation duration in seconds
pauseOnHoverbooleantruePause auto-rotation when hovering
refGlCarouselBannerHandle-Reference for programmatic control

Vanilla JS Attributes

AttributeTypeDefaultDescription
autoRotatestring"true"Enable/disable automatic rotation ("true" or "false")
rotationSpeedstring"3"Time in seconds between rotations
transitionSpeedstring"0.5"Transition duration in seconds
pauseOnHoverstring"true"Pause on hover ("true" or "false")

Note: For Vanilla JS, set the items property directly (not as an attribute):

carousel.items = arrayOfItems;

🗂️ Data Structure

GlCarouselBannerItem Interface

interface GlCarouselBannerItem {
// Title
title_text: string; // HTML string for title (supports <strong>, <em>)
title_text_emphasis_color?: string; // Color for emphasized text (e.g., '#FF6600')

// Main Content
main_text: string | string[]; // HTML string or array of strings for content

// Button (Call-to-Action)
button_text: string; // Button text
button_color?: string; // Button background color (e.g., '#0052CC')
button_text_color?: string; // Button text color (e.g., '#FFFFFF')
button_link: string; // Button URL

// Images
background_image?: string; // URL for background image/pattern
main_image?: string; // URL for main slide image
main_image_link?: string; // URL when clicking main image
}

Example Data Object

const slideData = {
title_text: 'How <strong><em>local</em> gift cards</strong> work',
title_text_emphasis_color: '#FF6600',
main_text: [
'<strong>Search</strong> for local businesses',
'<strong>Choose</strong> the amount',
'<strong>Send</strong> instantly by email'
],
button_text: 'Get Started',
button_color: '#0052CC',
button_text_color: '#FFFFFF',
button_link: 'https://example.com/start',
background_image: 'https://example.com/pattern.svg',
main_image: 'https://example.com/hero.png',
main_image_link: 'https://example.com/details'
};

⚙️ Configuration Options

Auto-Rotation Settings

// React
<GlCarouselBanner
autoRotate={true} // Enable auto-rotation
rotationSpeed={5} // Rotate every 5 seconds
pauseOnHover={true} // Pause when user hovers
items={slides}
/>
// Vanilla JS
carousel.setAttribute('autoRotate', 'true');
carousel.setAttribute('rotationSpeed', '5');
carousel.setAttribute('pauseOnHover', 'true');

Transition Settings

// React
<GlCarouselBanner
transitionSpeed={0.8} // Slower transitions (0.8 seconds)
items={slides}
/>
// Vanilla JS
carousel.setAttribute('transitionSpeed', '0.8');

Disable Auto-Rotation

// React
<GlCarouselBanner
autoRotate={false} // Manual control only
items={slides}
/>
// Vanilla JS
carousel.setAttribute('autoRotate', 'false');

🎮 Methods & Controls

React (via ref)

const carouselRef = useRef<GlCarouselBannerHandle>(null);

// Navigate to next slide
carouselRef.current?.nextSlide();

// Navigate to previous slide
carouselRef.current?.previousSlide();

// Go to specific slide (0-indexed)
carouselRef.current?.goToSlide(2);

// Pause auto-rotation
carouselRef.current?.pause();

// Resume auto-rotation
carouselRef.current?.resume();

// Get current slide index
const currentIndex = carouselRef.current?.getCurrentSlide();

Vanilla JavaScript

// Navigate to next slide
carousel.nextSlide();

// Navigate to previous slide
carousel.previousSlide();

// Go to specific slide (0-indexed)
carousel.goToSlide(2);

// Pause auto-rotation
carousel.pause();

// Resume auto-rotation
carousel.resume();

// Get current slide index
const currentIndex = carousel.getCurrentSlide();

Method Reference

MethodParametersReturnsDescription
nextSlide()-voidMove to the next slide
previousSlide()-voidMove to the previous slide
goToSlide(index)index: numbervoidJump to specific slide (0-indexed)
pause()-voidPause auto-rotation
resume()-voidResume auto-rotation
getCurrentSlide()-number | undefinedGet current slide index

📡 Events

The carousel component emits custom events that you can listen to for various lifecycle events and state changes.

CarouselBannerEvents Constants

The package exports a CarouselBannerEvents object containing all available event names:

import { CarouselBannerEvents } from "@gift-card-market/gl-carousel-banner";

// Event names:
CarouselBannerEvents.CAROUSEL_LOADED // "gl:carousel-loaded"
CarouselBannerEvents.SLIDE_CHANGED // "gl:slide-changed"
CarouselBannerEvents.CAROUSEL_PAUSED // "gl:carousel-paused"
CarouselBannerEvents.CAROUSEL_RESUMED // "gl:carousel-resumed"
CarouselBannerEvents.ERROR // "gl:error"

Available Events

Event NameEvent TypeDetail ObjectDescription
gl:carousel-loadedCustomEvent{ slideCount: number }Fired when carousel is initialized and ready
gl:slide-changedCustomEvent{ slideIndex: number, direction: 'next' | 'previous' }Fired whenever the active slide changes
gl:carousel-pausedCustomEvent{}Fired when auto-rotation is paused
gl:carousel-resumedCustomEvent{}Fired when auto-rotation is resumed
gl:errorCustomEvent{ error: string }Fired when an error occurs

Event Usage Examples

Listen for when the carousel finishes initialization:

document.addEventListener('gl:carousel-loaded', (event) => {
console.log('✅ Carousel loaded with', event.detail.slideCount, 'slides');
// Initialize custom UI or analytics
});

// Or use the constant:
import { CarouselBannerEvents } from "@gift-card-market/gl-carousel-banner";

document.addEventListener(CarouselBannerEvents.CAROUSEL_LOADED, (event) => {
console.log('Carousel ready!', event.detail);
});

2. Slide Changed Event

Track slide changes with direction information:

document.addEventListener('gl:slide-changed', (event) => {
const { slideIndex, direction } = event.detail;
console.log(`Moved to slide ${slideIndex} (${direction})`);

// Update custom UI
document.getElementById('currentSlide').textContent = slideIndex + 1;

// Track analytics
analytics.track('Carousel Slide Changed', {
slide: slideIndex,
direction: direction
});
});

3. Pause/Resume Events

Monitor auto-rotation state:

document.addEventListener('gl:carousel-paused', () => {
console.log('⏸️ Carousel paused');
document.getElementById('status').textContent = 'Paused';
});

document.addEventListener('gl:carousel-resumed', () => {
console.log('▶️ Carousel resumed');
document.getElementById('status').textContent = 'Playing';
});

4. Error Handling

Handle errors gracefully:

document.addEventListener('gl:error', (event) => {
console.error('❌ Carousel error:', event.detail.error);

// Show error to user or log to error tracking service
showNotification('Carousel failed to load', 'error');
});

Complete Event Listener Example

import { CarouselBannerEvents } from "@gift-card-market/gl-carousel-banner";

// Setup all event listeners
function setupCarouselEventListeners() {
// Loaded
document.addEventListener(CarouselBannerEvents.CAROUSEL_LOADED, (event) => {
console.log('🎠 Carousel initialized with', event.detail.slideCount, 'slides');
});

// Slide changed
document.addEventListener(CarouselBannerEvents.SLIDE_CHANGED, (event) => {
const { slideIndex, direction } = event.detail;
console.log(`📍 Slide ${slideIndex + 1} (${direction})`);
updateIndicator(slideIndex);
});

// Paused
document.addEventListener(CarouselBannerEvents.CAROUSEL_PAUSED, () => {
console.log('⏸️ Paused');
document.getElementById('playButton').textContent = 'Play';
});

// Resumed
document.addEventListener(CarouselBannerEvents.CAROUSEL_RESUMED, () => {
console.log('▶️ Playing');
document.getElementById('playButton').textContent = 'Pause';
});

// Error
document.addEventListener(CarouselBannerEvents.ERROR, (event) => {
console.error('❌ Error:', event.detail.error);
showErrorMessage(event.detail.error);
});
}

setupCarouselEventListeners();

React Event Listeners

In React, you can listen to these events using useEffect:

import { useEffect, useState } from 'react';
import { CarouselBannerEvents } from "@gift-card-market/gl-carousel-banner";

function CarouselWithEvents() {
const [slideInfo, setSlideInfo] = useState({ index: 0, total: 0 });
const [isPaused, setIsPaused] = useState(false);

useEffect(() => {
// Carousel loaded handler
const handleLoaded = (event: CustomEvent) => {
setSlideInfo(prev => ({ ...prev, total: event.detail.slideCount }));
console.log('Carousel loaded');
};

// Slide changed handler
const handleSlideChange = (event: CustomEvent) => {
setSlideInfo(prev => ({
...prev,
index: event.detail.slideIndex
}));
console.log('Slide changed to', event.detail.slideIndex);
};

// Pause handler
const handlePause = () => {
setIsPaused(true);
};

// Resume handler
const handleResume = () => {
setIsPaused(false);
};

// Error handler
const handleError = (event: CustomEvent) => {
console.error('Carousel error:', event.detail.error);
};

// Add event listeners
document.addEventListener(CarouselBannerEvents.CAROUSEL_LOADED, handleLoaded as EventListener);
document.addEventListener(CarouselBannerEvents.SLIDE_CHANGED, handleSlideChange as EventListener);
document.addEventListener(CarouselBannerEvents.CAROUSEL_PAUSED, handlePause);
document.addEventListener(CarouselBannerEvents.CAROUSEL_RESUMED, handleResume);
document.addEventListener(CarouselBannerEvents.ERROR, handleError as EventListener);

// Cleanup
return () => {
document.removeEventListener(CarouselBannerEvents.CAROUSEL_LOADED, handleLoaded as EventListener);
document.removeEventListener(CarouselBannerEvents.SLIDE_CHANGED, handleSlideChange as EventListener);
document.removeEventListener(CarouselBannerEvents.CAROUSEL_PAUSED, handlePause);
document.removeEventListener(CarouselBannerEvents.CAROUSEL_RESUMED, handleResume);
document.removeEventListener(CarouselBannerEvents.ERROR, handleError as EventListener);
};
}, []);

return (
<div>
<GlCarouselBanner items={slides} />
<div>
Slide {slideInfo.index + 1} of {slideInfo.total}
{isPaused ? ' (Paused)' : ' (Playing)'}
</div>
</div>
);
}

Event Bubbling

All carousel events use bubbles: true and composed: true, which means:

  • Events bubble up through the DOM tree
  • Events can cross shadow DOM boundaries
  • You can listen on document or any parent element

Legacy slideChange Event (Deprecated)

Note: The component still supports the legacy slideChange event on the carousel element itself for backward compatibility, but it's recommended to use the new gl:slide-changed event with CarouselBannerEvents constants instead.

// ❌ Old way (still works, but deprecated)
carousel.addEventListener('slideChange', (event) => {
console.log('Slide:', event.detail);
});

// ✅ New way (recommended)
document.addEventListener(CarouselBannerEvents.SLIDE_CHANGED, (event) => {
console.log('Slide:', event.detail.slideIndex);
});

🎨 Styling & Customization

CSS Variables

You can customize the carousel appearance using CSS variables:

:root {
/* Dot Navigation */
--gl-carousel-dot-color: #cccccc;
--gl-carousel-dot-active-color: #0052cc;

/* Arrow Controls */
--gl-carousel-arrow-color: #000000;
--gl-carousel-arrow-bg: rgba(255, 255, 255, 0.8);

/* Slide Title */
--gl-slide-title-font: 'Arial', sans-serif;
--gl-slide-title-size: 32px;
--gl-slide-title-color: #000000;

/* Slide Text */
--gl-slide-text-font: 'Arial', sans-serif;
--gl-slide-text-size: 18px;
--gl-slide-text-color: #333333;

/* Button */
--gl-button-border-radius: 4px;

/* Layout */
--gl-slide-padding: 40px;
}

Example Customization

:root {
--gl-carousel-dot-active-color: #EE3D84;
--gl-slide-title-size: 40px;
--gl-slide-title-color: #1a1a1a;
--gl-button-border-radius: 24px;
}

Override Specific Styles

/* Custom arrow styling */
gl-carousel-banner .slick-arrow {
background: rgba(0, 82, 204, 0.9) !important;
border-radius: 50%;
}

/* Custom dot styling */
gl-carousel-banner .slick-dots li button:before {
font-size: 14px;
}

🚀 Advanced Examples

Dynamic Data Loading

React

import { useState, useEffect, useRef } from 'react';
import { GlCarouselBanner, type GlCarouselBannerItem } from '@gift-card-market/gl-carousel-banner';

function DynamicCarousel() {
const [slides, setSlides] = useState<GlCarouselBannerItem[]>([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
// Fetch slides from API
fetch('https://api.example.com/carousel-slides')
.then(res => res.json())
.then(data => {
setSlides(data);
setLoading(false);
})
.catch(err => {
console.error('Failed to load slides:', err);
setLoading(false);
});
}, []);

if (loading) {
return <div>Loading carousel...</div>;
}

return (
<GlCarouselBanner
items={slides}
autoRotate={true}
rotationSpeed={4}
/>
);
}

Vanilla JS

// Fetch and render carousel dynamically
async function loadCarousel() {
try {
const response = await fetch('https://api.example.com/carousel-slides');
const slides = await response.json();

const carousel = document.createElement('gl-carousel-banner');
carousel.setAttribute('autoRotate', 'true');
carousel.setAttribute('rotationSpeed', '4');

document.getElementById('carousel-container').appendChild(carousel);

await customElements.whenDefined('gl-carousel-banner');
carousel.items = slides;

console.log('Carousel loaded with', slides.length, 'slides');
} catch (error) {
console.error('Failed to load carousel:', error);
}
}

loadCarousel();

Multiple Carousels on Same Page

function MultiCarouselPage() {
const carousel1Data = [...];
const carousel2Data = [...];

return (
<div>
<section>
<h2>Featured Products</h2>
<GlCarouselBanner
items={carousel1Data}
autoRotate={true}
rotationSpeed={3}
/>
</section>

<section style={{ marginTop: '40px' }}>
<h2>Customer Stories</h2>
<GlCarouselBanner
items={carousel2Data}
autoRotate={true}
rotationSpeed={5}
/>
</section>
</div>
);
}
function ControlledCarousel() {
const carouselRef = useRef<GlCarouselBannerHandle>(null);
const [currentSlide, setCurrentSlide] = useState(0);

const slides: GlCarouselBannerItem[] = [...];

const handleThumbnailClick = (index: number) => {
carouselRef.current?.goToSlide(index);
setCurrentSlide(index);
};

return (
<div>
<GlCarouselBanner
ref={carouselRef}
items={slides}
autoRotate={false}
/>

<div className="thumbnails">
{slides.map((slide, index) => (
<img
key={index}
src={slide.main_image}
onClick={() => handleThumbnailClick(index)}
className={currentSlide === index ? 'active' : ''}
style={{
width: '100px',
cursor: 'pointer',
opacity: currentSlide === index ? 1 : 0.5
}}
/>
))}
</div>
</div>
);
}

Responsive Configuration

function ResponsiveCarousel() {
const [isMobile, setIsMobile] = useState(window.innerWidth < 768);

useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth < 768);
};

window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);

return (
<GlCarouselBanner
items={slides}
autoRotate={!isMobile} // Disable auto-rotate on mobile
rotationSpeed={isMobile ? 5 : 3} // Slower on mobile
pauseOnHover={!isMobile} // Only on desktop
/>
);
}

🐛 Troubleshooting

Common Issues

Problem: Carousel appears empty or doesn't render.

Solution: Make sure to wait for the custom element to be defined before setting items:

// ❌ Wrong
const carousel = document.createElement('gl-carousel-banner');
carousel.items = data; // Too early!
document.body.appendChild(carousel);

// ✅ Correct
const carousel = document.createElement('gl-carousel-banner');
document.body.appendChild(carousel);

customElements.whenDefined('gl-carousel-banner').then(() => {
carousel.items = data; // Set items after component is ready
});

2. Methods Not Available (Vanilla JS)

Problem: carousel.nextSlide() throws "not a function" error.

Solution: Wait for component initialization with a small delay:

customElements.whenDefined('gl-carousel-banner').then(() => {
carousel.items = data;

// Wait for React to mount internally
setTimeout(() => {
carousel.nextSlide(); // Now available!
}, 200);
});

3. Styles Not Applied

Problem: Carousel has no styling or looks broken.

Solution: Ensure all CSS files are imported:

// React - Import ALL required styles
import '@gift-card-market/gl-carousel-banner/style.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
<!-- Vanilla JS - Include stylesheet -->
<link rel="stylesheet"
href="./node_modules/@gift-card-market/gl-carousel-banner/dist/browser/gl-carousel-banner.css">

4. TypeScript Errors (React)

Problem: Type errors when using the component.

Solution: Import types explicitly:

import { 
GlCarouselBanner,
type GlCarouselBannerHandle,
type GlCarouselBannerItem
} from "@gift-card-market/gl-carousel-banner";

// Use the types
const carouselRef = useRef<GlCarouselBannerHandle>(null);
const slides: GlCarouselBannerItem[] = [...];

5. Auto-Rotation Not Working

Problem: Carousel doesn't auto-advance.

Solution:

  • Check autoRotate is set to true
  • Verify rotationSpeed is a positive number
  • Ensure carousel is not paused
// React
<GlCarouselBanner
autoRotate={true} // Must be boolean true
rotationSpeed={3} // Must be number > 0
items={slides}
/>

6. Images Not Loading

Problem: Slide images don't appear.

Solution:

  • Verify image URLs are accessible
  • Check for CORS issues
  • Ensure URLs are complete (include protocol)
// ✅ Good
background_image: 'https://example.com/image.png'

// ❌ Bad
background_image: '/image.png' // Relative path may not work
background_image: 'example.com/image.png' // Missing protocol

📊 Performance Tips

1. Optimize Images

  • Use WebP format for better compression
  • Lazy load images for off-screen slides
  • Provide appropriate image sizes (avoid oversized images)

2. Limit Slide Count

  • Keep carousel to 5-10 slides for best performance
  • For more content, consider pagination or multiple carousels

3. Adjust Animation Speed

  • Balance between smooth transitions and performance
  • Slower devices may benefit from faster transitions (lower transitionSpeed)
<GlCarouselBanner
transitionSpeed={0.3} // Faster = better performance
rotationSpeed={4} // Longer view time = less frequent transitions
items={slides}
/>

4. Disable Auto-Rotation When Not Visible

useEffect(() => {
const handleVisibilityChange = () => {
if (document.hidden) {
carouselRef.current?.pause();
} else {
carouselRef.current?.resume();
}
};

document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}, []);

  • Package Location: @gift-card-market/gl-carousel-banner
  • Current Version: 1.0.3
  • Dependencies:
    • React 18+ (for React implementation)
    • Slick Carousel (for animations)
  • Key Features:
    • React & Vanilla JS support
    • Comprehensive event system with CarouselBannerEvents
    • Full TypeScript definitions
    • Programmatic control API
    • CSS customization

📝 Changelog

Version 1.0.3 (Current)

  • ✨ Added CarouselBannerEvents constant export for type-safe event handling
  • ✨ New custom events: gl:carousel-loaded, gl:carousel-paused, gl:carousel-resumed, gl:error
  • 🔄 Enhanced gl:slide-changed event with direction information
  • 📚 Comprehensive event documentation with React and Vanilla JS examples
  • ⚡ Improved event system with bubbling support
  • 🐛 Bug fixes and performance improvements

Version 1.0.2

  • 🐛 Bug fixes and stability improvements
  • 📚 Documentation enhancements

Version 1.0.1

  • 🎉 Initial release
  • ✅ React component support
  • ✅ Web Component (Vanilla JS) support
  • ✅ Auto-rotation with configurable speed
  • ✅ Pause on hover functionality
  • ✅ Programmatic control API
  • ✅ Basic event system for slide changes
  • ✅ Full TypeScript support
  • ✅ CSS customization via variables

📞 Support

For questions, issues, or feature requests, please contact the Gift Card Marketplace development team.


📄 License

© 2025 Gift Card Marketplace. All rights reserved.


Happy Coding! 🎉