Skip to main content

Slider

Big O

React JS​

import React, { useEffect, useState } from "react";
import "./styles.css"; // Importing classic CSS styles

const TAGS = new Set([
"Philosophy",
"Self",
"Inspiration",
"Growth",
"Success",
"Happiness",
"Perseverance",
"Mindfulness",
"Wisdom",
"Courage",
"Determination",
"Positivity",
"Leadership",
"Life",
"Motivation",
"Achievement",
"Gratitude",
"Resilience",
"Hope",
"Empowerment",
"Confidence",
"Strength",
"Focus",
"Balance",
"Purpose",
"Vision",
"Wellness",
"Ambition",
"Creativity",
"Change",
]);

// Loading spinner component styled using classic CSS
const Spinner = () => (
<div className="spinner-overlay">
<div className="spinner"></div>
</div>
);

export function QuoteCarousel() {
const [slides, setSlides] = useState([]);
const [currentIndex, setCurrentIndex] = useState(0);
const [loading, setLoading] = useState(true);

useEffect(() => {
const loadData = async () => {
try {
const fetchedSlides = [];
for (let i = 0; i < 20; i++) {
const data = await fetch("https://dummyjson.com/quotes/random");
const res = await data.json();
const image = `https://picsum.photos/seed/${res.id}/1600/900`;

const tags = [];
const numberOfTags = Math.floor(Math.random() * 3) + 1;
for (let j = 0; j < numberOfTags; j++) {
let arr = Array.from(TAGS);
tags.push(arr[Math.floor(Math.random() * TAGS.size)]);
}

const slide = {
imageUrl: image,
quote: {
id: res.id,
quote: res.quote,
author: res.author,
tags,
},
};

fetchedSlides.push(slide);
}

setSlides(fetchedSlides);
} catch (error) {
console.error("Error fetching:", error);
} finally {
setLoading(false);
}
};

loadData();
}, []);

const handlePrevious = () => {
setLoading(true);
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex === 0 ? slides.length - 1 : prevIndex - 1;
return newIndex;
});
};

const handleNext = () => {
setLoading(true);
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex === slides.length - 1 ? 0 : prevIndex + 1;
return newIndex;
});
};

useEffect(() => {
if (slides.length > 0) {
const image = new Image();
image.src = slides[currentIndex].imageUrl;
image.onload = () => {
setLoading(false);
};
}
}, [currentIndex, slides]);

if (loading) {
return <Spinner />;
}

const currentSlide = slides[currentIndex];

return (
<div className="carousel">
<div className="slide" key={currentSlide.quote.id}>
<div className="image-container">
<img src={currentSlide.imageUrl} alt="Quote" />
</div>
<div className="quote-info">
<p className="quote-text">{currentSlide.quote.quote}</p>
<p className="quote-author">{currentSlide.quote.author}</p>
<div className="tags">
{currentSlide.quote.tags.map((tag) => (
<span key={tag} className="tag">
{tag}
</span>
))}
</div>
</div>
<div className="controls">
<div className="dots">
{slides.map((_, index) => (
<span
key={index}
className={`dot ${index === currentIndex ? "active" : ""}`}
></span>
))}
</div>
<div className="buttons">
<button onClick={handlePrevious}>Previous</button>
<button onClick={handleNext}>Next</button>
</div>
</div>
</div>
</div>
);
}

function App() {
return (
<div className="App">
<QuoteCarousel />
</div>
);
}

export default App;

React TS​

import React, { useEffect, useState } from "react";
import "./styles.css";

const TAGS = new Set([
"Philosophy",
"Self",
"Inspiration",
"Growth",
"Success",
"Happiness",
"Perseverance",
"Mindfulness",
"Wisdom",
"Courage",
"Determination",
"Positivity",
"Leadership",
"Life",
"Motivation",
"Achievement",
"Gratitude",
"Resilience",
"Hope",
"Empowerment",
"Confidence",
"Strength",
"Focus",
"Balance",
"Purpose",
"Vision",
"Wellness",
"Ambition",
"Creativity",
"Change",
]);

type Quote = {
id: string;
quote: string;
author: string;
tags: string[];
};

type Slide = {
imageUrl: string;
quote: Quote;
};

const CAROUSEL_SIZE = 20;

const Spinner = () => (
<div className="spinner-overlay">
<div className="spinner"></div>
</div>
);

export function QuoteCarousel() {
const [slides, setSlides] = useState<Slide[]>([]);
const [currentIndex, setCurrentIndex] = useState(0);
const [loading, setLoading] = useState(true);

useEffect(() => {
const loadData = async () => {
try {
const fetchedSlides: Slide[] = [];
for (let i = 0; i < CAROUSEL_SIZE; i++) {
const data = await fetch("https://dummyjson.com/quotes/random");
const res = await data.json();
const image = `https://picsum.photos/seed/${res.id}/1600/900`;

const tags: string[] = [];
const numberOfTags = Math.floor(Math.random() * 3) + 1;
for (let j = 0; j < numberOfTags; j++) {
let arr = Array.from(TAGS);
tags.push(arr[Math.floor(Math.random() * TAGS.size)]);
}

const slide: Slide = {
imageUrl: image,
quote: {
id: res.id,
quote: res.quote,
author: res.author,
tags,
},
};

fetchedSlides.push(slide);
}

setSlides(fetchedSlides);
} catch (error) {
console.error("Error fetching:", error);
} finally {
setLoading(false);
}
};

loadData();
}, []);

const handlePrevious = () => {
setLoading(true);
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex === 0 ? slides.length - 1 : prevIndex - 1;
return newIndex;
});
};

const handleNext = () => {
setLoading(true);
setCurrentIndex((prevIndex) => {
const newIndex = prevIndex === slides.length - 1 ? 0 : prevIndex + 1;
return newIndex;
});
};

useEffect(() => {
if (slides.length > 0) {
const image = new Image();
image.src = slides[currentIndex].imageUrl;
image.onload = () => {
setLoading(false);
};
}
}, [currentIndex, slides]);

if (loading) {
return <Spinner />;
}

const currentSlide = slides[currentIndex];

return (
<div className="carousel">
<div className="slide" key={currentSlide.quote.id}>
<div className="image-container">
<img src={currentSlide.imageUrl} alt="Quote" />
</div>
<div className="quote-info">
<p className="quote-text">{currentSlide.quote.quote}</p>
<p className="quote-author">{currentSlide.quote.author}</p>
<div className="tags">
{currentSlide.quote.tags.map((tag) => (
<span key={tag} className="tag">
{tag}
</span>
))}
</div>
</div>
<div className="controls">
<div className="dots">
{slides.map((_, index) => (
<span
key={index}
className={`dot ${index === currentIndex ? "active" : ""}`}
></span>
))}
</div>
<div className="buttons">
<button onClick={handlePrevious}>Previous</button>
<button onClick={handleNext}>Next</button>
</div>
</div>
</div>
</div>
);
}

function App() {
return (
<div className="App">
<QuoteCarousel />
</div>
);
}

export default App;

React JS + Tailwind​

import React, { useEffect, useState } from "react";
import "./Spinner.css"; // If additional styles are needed

// A set of tags that will be randomly assigned to quotes
const TAGS = new Set([
"Philosophy",
"Self",
"Inspiration",
"Growth",
"Success",
"Happiness",
"Perseverance",
"Mindfulness",
"Wisdom",
"Courage",
"Determination",
"Positivity",
"Leadership",
"Life",
"Motivation",
"Achievement",
"Gratitude",
"Resilience",
"Hope",
"Empowerment",
"Confidence",
"Strength",
"Focus",
"Balance",
"Purpose",
"Vision",
"Wellness",
"Ambition",
"Creativity",
"Change",
]);

// Loading spinner component styled using Tailwind CSS
const Spinner = () => (
<div className="fixed inset-0 flex items-center justify-center bg-white bg-opacity-75 z-50">
<div className="w-16 h-16 border-4 border-t-4 border-t-transparent border-gray-400 rounded-full animate-spin"></div>
</div>
);

export function QuoteCarousel() {
// State to store the slides
const [slides, setSlides] = useState([]);
// State to track the current slide index
const [currentIndex, setCurrentIndex] = useState(0);
// State to track the loading status
const [loading, setLoading] = useState(true);

// Effect to load data when the component is mounted
useEffect(() => {
const loadData = async () => {
try {
const fetchedSlides = [];

// Loop to fetch and create the slides
for (let i = 0; i < 20; i++) {
// Fetching random quote data
const data = await fetch("https://dummyjson.com/quotes/random");
const res = await data.json();
// Generating a random image URL based on the quote ID
const image = `https://picsum.photos/seed/${res.id}/1600/900`;

// Randomly selecting a number of tags to associate with the quote
const tags = [];
const numberOfTags = Math.floor(Math.random() * 3) + 1;
for (let j = 0; j < numberOfTags; j++) {
let arr = Array.from(TAGS);
tags.push(arr[Math.floor(Math.random() * TAGS.size)]);
}

// Creating a slide object and adding it to the array
const slide = {
imageUrl: image,
quote: {
id: res.id,
quote: res.quote,
author: res.author,
tags,
},
};

fetchedSlides.push(slide);
}

// Updating the state with the fetched slides
setSlides(fetchedSlides);
} catch (error) {
console.error("Error fetching:", error);
} finally {
// Set loading to false once data is fetched
setLoading(false);
}
};

loadData();
}, []); // Empty dependency array to run this effect only once on component mount

// Function to handle switching to the previous slide
const handlePrevious = () => {
setLoading(true); // Start loading
setCurrentIndex((prevIndex) => {
// Calculate the new index, wrapping around if necessary
const newIndex = prevIndex === 0 ? slides.length - 1 : prevIndex - 1;
return newIndex;
});
};

// Function to handle switching to the next slide
const handleNext = () => {
setLoading(true); // Start loading
setCurrentIndex((prevIndex) => {
// Calculate the new index, wrapping around if necessary
const newIndex = prevIndex === slides.length - 1 ? 0 : prevIndex + 1;
return newIndex;
});
};

// Effect to handle loading the image for the current slide
useEffect(() => {
if (slides.length > 0) {
// Create a new Image object to preload the current slide's image
const image = new Image();
image.src = slides[currentIndex].imageUrl;
image.onload = () => {
// Set loading to false once the image is fully loaded
setLoading(false);
};
}
}, [currentIndex, slides]); // Dependency array includes the current index and slides

// If still loading, display the spinner
if (loading) {
return <Spinner />;
}

// Get the current slide based on the current index
const currentSlide = slides[currentIndex];

return (
<div className="carousel w-full h-screen flex flex-col items-center justify-center bg-white text-center p-4">
<div
className="slide flex flex-col items-center w-4/5"
key={currentSlide.quote.id}
>
<div className="image-container w-full h-[70vh] mb-4">
<img
src={currentSlide.imageUrl}
alt="Quote"
className="w-full h-full object-cover"
/>
</div>
<div className="quote-info w-full text-left p-4 h-[150px]">
<p className="text-2xl font-semibold">{currentSlide.quote.quote}</p>
<p className="text-xl italic">{currentSlide.quote.author}</p>
<div className="tags flex gap-2 mt-2">
{currentSlide.quote.tags.map((tag) => (
<span key={tag} className="tag bg-gray-200 p-1 rounded">
{tag}
</span>
))}
</div>
</div>
<div className="controls flex flex-col items-center mt-8">
<div className="dots flex space-x-2 mb-4">
{slides.map((_, index) => (
<span
key={index}
className={`dot w-3 h-3 rounded-full ${index === currentIndex ? "bg-black" : "bg-gray-300"}`}
></span>
))}
</div>
<div className="buttons">
<button
onClick={handlePrevious}
className="mr-2 p-2 bg-gray-300 rounded"
>
Previous
</button>
<button
onClick={handleNext}
className="ml-2 p-2 bg-gray-300 rounded"
>
Next
</button>
</div>
</div>
</div>
</div>
);
}

function App() {
return (
<div className="App">
<QuoteCarousel />
</div>
);
}

export default App;

React TS + Tailwind​

import React, { useEffect, useState } from "react";
import "./Spinner.css"; // If additional styles are needed

// A set of tags that will be randomly assigned to quotes
const TAGS = new Set([
"Philosophy",
"Self",
"Inspiration",
"Growth",
"Success",
"Happiness",
"Perseverance",
"Mindfulness",
"Wisdom",
"Courage",
"Determination",
"Positivity",
"Leadership",
"Life",
"Motivation",
"Achievement",
"Gratitude",
"Resilience",
"Hope",
"Empowerment",
"Confidence",
"Strength",
"Focus",
"Balance",
"Purpose",
"Vision",
"Wellness",
"Ambition",
"Creativity",
"Change",
]);

// Loading spinner component styled using Tailwind CSS
const Spinner = () => (
<div className="fixed inset-0 flex items-center justify-center bg-white bg-opacity-75 z-50">
<div className="w-16 h-16 border-4 border-t-4 border-t-transparent border-gray-400 rounded-full animate-spin"></div>
</div>
);

// Defining types for Quote and Slide objects
type Quote = {
id: string;
quote: string;
author: string;
tags: string[];
};

type Slide = {
imageUrl: string;
quote: Quote;
};

// Constant defining the number of slides in the carousel
const CAROUSEL_SIZE = 20;

export function QuoteCarousel() {
// State to store the slides
const [slides, setSlides] = useState<Slide[]>([]);
// State to track the current slide index
const [currentIndex, setCurrentIndex] = useState(0);
// State to track the loading status
const [loading, setLoading] = useState(true);

// Effect to load data when the component is mounted
useEffect(() => {
const loadData = async () => {
try {
const fetchedSlides: Slide[] = [];

// Loop to fetch and create the slides
for (let i = 0; i < CAROUSEL_SIZE; i++) {
// Fetching random quote data
const data = await fetch("https://dummyjson.com/quotes/random");
const res = await data.json();
// Generating a random image URL based on the quote ID
const image = `https://picsum.photos/seed/${res.id}/1600/900`;

// Randomly selecting a number of tags to associate with the quote
const tags: string[] = [];
const numberOfTags = Math.floor(Math.random() * 3) + 1;
for (let j = 0; j < numberOfTags; j++) {
let arr = Array.from(TAGS);
tags.push(arr[Math.floor(Math.random() * TAGS.size)]);
}

// Creating a slide object and adding it to the array
const slide: Slide = {
imageUrl: image,
quote: {
id: res.id,
quote: res.quote,
author: res.author,
tags,
},
};

fetchedSlides.push(slide);
}

// Updating the state with the fetched slides
setSlides(fetchedSlides);
} catch (error) {
console.error("Error fetching:", error);
} finally {
// Set loading to false once data is fetched
setLoading(false);
}
};

loadData();
}, []); // Empty dependency array to run this effect only once on component mount

// Function to handle switching to the previous slide
const handlePrevious = () => {
setLoading(true); // Start loading
setCurrentIndex((prevIndex) => {
// Calculate the new index, wrapping around if necessary
const newIndex = prevIndex === 0 ? slides.length - 1 : prevIndex - 1;
return newIndex;
});
};

// Function to handle switching to the next slide
const handleNext = () => {
setLoading(true); // Start loading
setCurrentIndex((prevIndex) => {
// Calculate the new index, wrapping around if necessary
const newIndex = prevIndex === slides.length - 1 ? 0 : prevIndex + 1;
return newIndex;
});
};

// Effect to handle loading the image for the current slide
useEffect(() => {
if (slides.length > 0) {
// Create a new Image object to preload the current slide's image
const image = new Image();
image.src = slides[currentIndex].imageUrl;
image.onload = () => {
// Set loading to false once the image is fully loaded
setLoading(false);
};
}
}, [currentIndex, slides]); // Dependency array includes the current index and slides

// If still loading, display the spinner
if (loading) {
return <Spinner />;
}

// Get the current slide based on the current index
const currentSlide = slides[currentIndex];

return (
<div className="carousel w-full h-screen flex flex-col items-center justify-center bg-white text-center p-4">
<div
className="slide flex flex-col items-center w-4/5"
key={currentSlide.quote.id}
>
<div className="image-container w-full h-[70vh] mb-4">
<img
src={currentSlide.imageUrl}
alt="Quote"
className="w-full h-full object-cover"
/>
</div>
<div className="quote-info w-full text-left p-4 h-[150px]">
<p className="text-2xl font-semibold">{currentSlide.quote.quote}</p>
<p className="text-xl italic">{currentSlide.quote.author}</p>
<div className="tags flex gap-2 mt-2">
{currentSlide.quote.tags.map((tag) => (
<span key={tag} className="tag bg-gray-200 p-1 rounded">
{tag}
</span>
))}
</div>
</div>
<div className="controls flex flex-col items-center mt-8">
<div className="dots flex space-x-2 mb-4">
{slides.map((_, index) => (
<span
key={index}
className={`dot w-3 h-3 rounded-full ${index === currentIndex ? "bg-black" : "bg-gray-300"}`}
></span>
))}
</div>
<div className="buttons">
<button
onClick={handlePrevious}
className="mr-2 p-2 bg-gray-300 rounded"
>
Previous
</button>
<button
onClick={handleNext}
className="ml-2 p-2 bg-gray-300 rounded"
>
Next
</button>
</div>
</div>
</div>
</div>
);
}

function App() {
return (
<div className="App">
<QuoteCarousel />
</div>
);
}

export default App;