Skip to content

Cards are 'Flying' in front of me when loop:true (Video is given below) #449

Open
@nayanbamnote

Description

@nayanbamnote
keen.slider.problem.mp4

Here is my code:
import React, { useState, useEffect, useRef } from "react";
import { Button } from "../../ShadcnComponents/button";
import { ArrowRight } from "lucide-react";
import { Projects, Courses } from "./Data";
import { useKeenSlider } from "keen-slider/react";
import "keen-slider/keen-slider.min.css";
import ProjectCard from "./ProjectCard";
import CourseCard from "./CourseCard";
import { limitWords } from "../../../lib/utils";

function Arrow(props) {
const disabled = props.disabled ? " opacity-30 cursor-not-allowed" : "";
return (
<svg
onClick={props.onClick}
className={w-6 h-6 md:w-8 md:h-8 absolute top-1/2 transform -translate-y-1/2 z-10 cursor-pointer fill-primary-foreground ${ props.left ? "-left-1 md:-left-6" : "-right-1 md:-right-6" } ${disabled}}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
{props.left && (

)}
{!props.left && (

)}

);
}

const ProjectCourseCombo = () => {
const [activeTab, setActiveTab] = useState("projects");
const [currentSlide, setCurrentSlide] = useState(0);
const [loaded, setLoaded] = useState(false);
const [sliderInstanceRef, setSliderInstanceRef] = useState(null);
const sliderContainerRef = useRef(null);

// Reset slider when switching tabs
const handleTabChange = (tab) => {
if (tab === activeTab) return;

// First, fade out the content
if (sliderContainerRef.current) {
  sliderContainerRef.current.style.opacity = '0';
}

// Change tab after a short delay
setTimeout(() => {
  setActiveTab(tab);
  setCurrentSlide(0);
  
  // Reset slider and fade back in after content has changed
  setTimeout(() => {
    if (sliderInstanceRef) {
      sliderInstanceRef.update();
      sliderInstanceRef.moveToIdx(0);
    }
    
    if (sliderContainerRef.current) {
      sliderContainerRef.current.style.opacity = '1';
    }
  }, 50);
}, 150);

};

const [sliderRef, instanceRef] = useKeenSlider({
initial: 0,
loop: true,
slides: {
perView: 4,
spacing: 24,
},
breakpoints: {
"(max-width: 1280px)": {
slides: {
perView: 3,
spacing: 24,
},
},
"(max-width: 1024px)": {
slides: {
perView: 2,
spacing: 16,
},
},
"(max-width: 640px)": {
slides: {
perView: 1,
spacing: 16,
},
},
},
slideChanged(slider) {
setCurrentSlide(slider.track.details.rel);
},
created(slider) {
setLoaded(true);
setSliderInstanceRef(slider);
},
});
const activeData = activeTab === "projects" ? Projects : Courses;

return (


compass with a circle.svg
{/* Title */}


Projects and Courses

  <section className="p-3 sm:p-4 md:p-6 lg:p-8 bg-primary rounded-3xl mt-4">
    <div className="!container mx-auto space-y-6">
      {/* Tab Selector */}
      <div className="flex justify-center sm:justify-end items-center">
        <div className="relative bg-background rounded-full border border-border/20 flex w-fit ">
          <button
            className={`py-1.5 px-4 sm:py-2 sm:px-6 md:py-3 md:px-8 rounded-full text-base sm:text-lg md:text-xl font-semibold relative z-10 transition-colors ${
              activeTab === "projects" ? "text-background" : "text-primary-foreground"
            }`}
            onClick={() => handleTabChange("projects")}>
            Projects
          </button>
          <button
            className={`py-1.5 px-4 sm:py-2 sm:px-6 md:py-3 md:px-8 rounded-full text-base sm:text-lg md:text-xl font-semibold relative z-10 transition-colors ${
              activeTab === "courses" ? "text-background" : "text-primary-foreground"
            }`}
            onClick={() => handleTabChange("courses")}>
            Courses
          </button>
          <div
            className={`absolute top-0 h-full bg-primary-foreground rounded-full transition-all duration-300 ${
              activeTab === "projects"
                ? "left-0 w-[100px] sm:w-[120px] md:w-[140px]"
                : "left-[100px] sm:left-[120px] md:left-[140px] w-[100px] sm:w-[120px] md:w-[140px]"
            }`}></div>
        </div>
      </div>

      {/* Projects/Courses Carousel */}
      <div 
        className="navigation-wrapper relative mb-6 md:mb-8 lg:mb-12 mt-4 sm:mt-6"
        ref={sliderContainerRef}
        style={{
          transition: "opacity 0.15s ease-in-out",
          opacity: 1
        }}
      >
        <div ref={sliderRef} className="keen-slider">
          {activeData.map((item, index) => {
            return activeTab === "projects" ? (
              <ProjectCard
                key={`project-${item.id}-${index}`}
                id={item.id}
                title={item.title}
                description={item.description}
                imageUrl={item.image}
              />
            ) : (
              <CourseCard
                key={`course-${item.id}-${index}`}
                id={item.id}
                title={item.title}
                description={item.description}
                imageUrl={item.image}
                chapters={item.stats?.chapters || 7}
                items={item.stats?.sections || 23}
              />
            );
          })}
        </div>
        {loaded && instanceRef.current && (
          <>
            <Arrow
              left
              onClick={(e) => {
                e.stopPropagation();
                instanceRef.current?.prev();
              }}
              disabled={currentSlide === 0}
            />
            <Arrow
              onClick={(e) => {
                e.stopPropagation();
                instanceRef.current?.next();
              }}
              disabled={
                currentSlide ===
                instanceRef.current.track.details.slides.length - instanceRef.current.options.slides.perView
              }
            />
          </>
        )}
      </div>

      {/* See All Button */}
      <div className="flex justify-center">
        <Button variant="cylindrical" size="lg" className=" bg-primary-foreground text-background hover:bg-primary-foreground/80" >
          { activeTab==="projects"? 'All Projects' : 'All Course'}
          <ArrowRight size={16} className="sm:size-20" />
        </Button>
      </div>
    </div>
  </section>
</div>

);
};

export default ProjectCourseCombo;

child component (keen slider):

import React from "react";
import { useNavigate } from "react-router-dom";

const ProjectCard = ({ id, title, description, imageUrl }) => {
const navigate = useNavigate();

const handleViewDetails = () => {
navigate(/projects/${id});
};

return (



{/* Image */}

<img
src={imageUrl}
alt={title}
className="w-full h-full object-cover"
onError={(e) => {
e.target.onerror = null;
e.target.src = "https://images.pexels.com/photos/255377/pexels-photo-255377.jpeg?auto=compress&cs=tinysrgb&w=800";
}}
/>

    <h3 className="font-semibold text-sm sm:text-base md:text-lg text-foreground line-clamp-1 overflow-hidden text-ellipsis">
      {title}
    </h3>
    
    <p className="text-foreground/70 text-xs break-all sm:text-sm md:text-base font-light line-clamp-4 sm:line-clamp-5 overflow-hidden">
      {description}
    </p>
    
    <p 
      className="text-primary-foreground text-sm sm:text-base text-right cursor-pointer mt-auto px-3  "
      onClick={handleViewDetails}
    >
      Details
    </p>
  </div>
</div>

);
};

export default ProjectCard;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions