GL Carousel Banner
Version: 1.0.5
Package:@gift-card-market/gl-carousel-banner
Last Updated: December 24, 2025
📖 Table of Contents
- Overview
- Installation
- Quick Start
- API Reference
- Data Structure
- Configuration Options
- Methods & Controls
- Events
- Styling & Customization
- Advanced Examples
- Troubleshooting
🎯 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
| Prop | Type | Default | Description |
|---|---|---|---|
items | GlCarouselBannerItem[] | Required | Array of carousel slide data |
autoRotate | boolean | true | Enable/disable automatic slide rotation |
rotationSpeed | number | 3 | Time in seconds between auto-rotations |
transitionSpeed | number | 0.5 | Transition animation duration in seconds |
pauseOnHover | boolean | true | Pause auto-rotation when hovering |
ref | GlCarouselBannerHandle | - | Reference for programmatic control |
Vanilla JS Attributes
| Attribute | Type | Default | Description |
|---|---|---|---|
autoRotate | string | "true" | Enable/disable automatic rotation ("true" or "false") |
rotationSpeed | string | "3" | Time in seconds between rotations |
transitionSpeed | string | "0.5" | Transition duration in seconds |
pauseOnHover | string | "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
| Method | Parameters | Returns | Description |
|---|---|---|---|
nextSlide() | - | void | Move to the next slide |
previousSlide() | - | void | Move to the previous slide |
goToSlide(index) | index: number | void | Jump to specific slide (0-indexed) |
pause() | - | void | Pause auto-rotation |
resume() | - | void | Resume auto-rotation |
getCurrentSlide() | - | number | undefined | Get 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 Name | Event Type | Detail Object | Description |
|---|---|---|---|
gl:carousel-loaded | CustomEvent | { slideCount: number } | Fired when carousel is initialized and ready |
gl:slide-changed | CustomEvent | { slideIndex: number, direction: 'next' | 'previous' } | Fired whenever the active slide changes |
gl:carousel-paused | CustomEvent | {} | Fired when auto-rotation is paused |
gl:carousel-resumed | CustomEvent | {} | Fired when auto-rotation is resumed |
gl:error | CustomEvent | { error: string } | Fired when an error occurs |
Event Usage Examples
1. Carousel Loaded Event
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
documentor 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>
);
}
Controlled Carousel with External Navigation
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
1. Carousel Not Rendering (Vanilla JS)
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
autoRotateis set totrue - Verify
rotationSpeedis 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);
};
}, []);
🔗 Links & Resources
- 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
CarouselBannerEventsconstant export for type-safe event handling - ✨ New custom events:
gl:carousel-loaded,gl:carousel-paused,gl:carousel-resumed,gl:error - 🔄 Enhanced
gl:slide-changedevent 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! 🎉