creativetimofficial / material-tailwind

@material-tailwind is an easy-to-use components library for Tailwind CSS and Material Design.
https://material-tailwind.com/
MIT License
3.71k stars 318 forks source link

Carousel doesn't load images with next/image <Image fill /> #462

Open TristanWasTaken opened 11 months ago

TristanWasTaken commented 11 months ago

When I try to use next/image <Image fill /> instead of <img /> the carousel component won't load that image. Though this seems to be only the case with some images/ in some situations.

Steps to reproduce: Required packages: next. sharp, react,

  1. copy paste the Carousel Custom Navigation code from the carousel docs with "use client" in L1
  2. Download the image files, move them to some local folder and import them
  3. Replace <img /> with Next's <Image /> and add the fill (fill={true}) option to all three images
  4. the carousel is either completely invisible or can't load/hides the images with fill=true option

There are some variations too where I set img2 to fill=false and img1 was able to load but img3 wasn't (see carousel.tsx and second carousel.tsx code)

code: app/layout.tsx:

import type {ReactNode, JSX} from "react";
import type {Metadata} from 'next';
import { Open_Sans } from 'next/font/google';
import {NextFont} from 'next/dist/compiled/@next/font';
import {cn} from '../lib/utils';
import './globals.css';

const inter: NextFont = Open_Sans({
    subsets: ['latin']
});

export const metadata: Metadata = {
    title: 'Test'
}

export default function RootLayout({children}: {children: ReactNode}): JSX.Element {
    return (
        <html lang="en">
        <body className={cn(
            inter.className,
            "bg-black"
        )}>
            {children}
        </body>
        </html>
    )
}

app/page.tsx

import {JSX} from "react";
import {Carousel} from "../components/carousel";

export default function Page(): JSX.Element {
    return (
        <Carousel />
    );
}

components/carousel.tsx

"use client";

import {JSX} from "react";
import Image from "next/image";
import {Carousel as MTCarousel, IconButton as MTIconButton} from "@material-tailwind/react";
import img1 from "../public/photo-1497436072909-60f360e1d4b1.jpg";
import img2 from "../public/photo-1493246507139-91e8fad9978e.jpg";
import img3 from "../public/photo-1518623489648-a173ef7824f3.jpg";

export const Carousel = (): JSX.Element => {
    return (
        <MTCarousel
            className="rounded-xl flex relative h-full w-full overflow-hidden"
            prevArrow={({ handlePrev }) => (
                <MTIconButton
                    variant="text"
                    color="white"
                    size="lg"
                    onClick={handlePrev}
                    className="!absolute top-2/4 left-4 -translate-y-2/4"
                >
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                        strokeWidth={2}
                        stroke="currentColor"
                        className="h-6 w-6"
                    >
                        <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18"
                        />
                    </svg>
                </MTIconButton>
            )}
            nextArrow={({ handleNext }) => (
                <MTIconButton
                    variant="text"
                    color="white"
                    size="lg"
                    onClick={handleNext}
                    className="!absolute top-2/4 !right-4 -translate-y-2/4"
                >
                    <svg
                        xmlns="http://www.w3.org/2000/svg"
                        fill="none"
                        viewBox="0 0 24 24"
                        strokeWidth={2}
                        stroke="currentColor"
                        className="h-6 w-6"
                    >
                        <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3"
                        />
                    </svg>
                </MTIconButton>
            )}
            navigation={({ setActiveIndex, activeIndex, length }) => (
                <div className="absolute bottom-4 left-2/4 z-50 flex -translate-x-2/4 gap-2">
                    {new Array(length).fill("").map((_, i) => (
                        <span
                            key={i}
                            className={`block h-1 cursor-pointer rounded-2xl transition-all content-[''] ${
                                activeIndex === i ? "w-8 bg-white" : "w-4 bg-white/50"
                            }`}
                            onClick={() => setActiveIndex(i)}
                        />
                    ))}
                </div>
            )}
        >
            <Image
                src={img1}
                alt="image 1"
                className="h-full w-full object-cover"
                fill
            />
            <Image
                src={img2}
                alt="image 2"
                className="h-full w-full object-cover"
                fill
            />
            <Image
                src={img3}
                alt="image 3"
                className="h-full w-full object-cover"
                fill
            />
        </MTCarousel>
    );
}

carousel.tsx only img3 doesn't load:

<MTCarousel>
    <Image
        src={img1}
        alt="image 1"
        className="h-full w-full object-cover"
        fill
    />
    <Image
        src={img2}
        alt="image 2"
        className="h-full w-full object-cover"
        fill={false}
    />
    <Image
        src={img3}
        alt="image 3"
        className="h-full w-full object-cover"
        fill
    />
</MTCarousel>
girdhariag commented 10 months ago

I wrapped the carousel inside another div with a fixed height and it worked fine for me.