This commit is contained in:
qiuchenfan 2025-11-18 15:11:13 +08:00
parent 4bf9807b59
commit a7b5e4d5f1
4 changed files with 84 additions and 23 deletions

View File

@ -1,19 +1,52 @@
import * as React from "react" // src/components/CarouselDemo.tsx
import * as React from "react";
import Autoplay from "embla-carousel-autoplay";
import { Card, CardContent } from "@/components/ui/card" import { Card, CardContent } from "@/components/ui/card";
import { import {
Carousel, Carousel,
CarouselContent, CarouselContent,
CarouselItem, CarouselItem,
CarouselNext, CarouselNext,
CarouselPrevious, CarouselPrevious,
} from "@/components/ui/carousel" type CarouselApi,
} from "@/components/ui/carousel";
export function CarouselDemo() { export function CarouselDemo() {
const [api, setApi] = React.useState<CarouselApi>();
const [current, setCurrent] = React.useState(0);
const [count, setCount] = React.useState(0);
const totalSlides = 6;
React.useEffect(() => {
if (!api) return;
setCount(api.scrollSnapList().length);
setCurrent(api.selectedScrollSnap());
api.on("select", () => {
setCurrent(api.selectedScrollSnap());
});
}, [api]);
return ( return (
<Carousel className="w-full max-w-xs"> <div className="relative w-full max-w-xs">
<Carousel
opts={{
loop: true,
}}
plugins={[
Autoplay({
delay: 3000,
stopOnInteraction: false,
}),
]}
setApi={setApi}
className="w-full"
>
<CarouselContent> <CarouselContent>
{Array.from({ length: 5 }).map((_, index) => ( {Array.from({ length: totalSlides }).map((_, index) => (
<CarouselItem key={index}> <CarouselItem key={index}>
<div className="p-1"> <div className="p-1">
<Card> <Card>
@ -25,8 +58,23 @@ export function CarouselDemo() {
</CarouselItem> </CarouselItem>
))} ))}
</CarouselContent> </CarouselContent>
<CarouselPrevious /> <CarouselPrevious className="absolute left-2 top-1/2 -translate-y-1/2 z-10" />
<CarouselNext /> <CarouselNext className="absolute right-2 top-1/2 -translate-y-1/2 z-10" />
</Carousel> </Carousel>
)
{/* 分页指示器 - 右下角 */}
<div className="absolute bottom-4 right-4 flex gap-2 z-10">
{Array.from({ length: count }).map((_, index) => (
<button
key={index}
onClick={() => api?.scrollTo(index)}
className={`h-2 w-2 rounded-full transition-colors ${
index === current ? "bg-black" : "bg-black/50"
}`}
aria-label={`Go to slide ${index + 1}`}
/>
))}
</div>
</div>
);
} }

View File

@ -1,4 +1,4 @@
import { Carousel } from "@/components/ui/carousel"; import { CarouselDemo } from "@/components/untils/Carousel";
import type { Route } from "./+types/news"; import type { Route } from "./+types/news";
@ -10,5 +10,5 @@ export function meta({}: Route.MetaArgs) {
} }
export default function Home() { export default function Home() {
return <Carousel />; return <CarouselDemo />;
} }

View File

@ -20,6 +20,7 @@
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dayjs": "^1.11.19", "dayjs": "^1.11.19",
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"immer": "^10.2.0", "immer": "^10.2.0",
"isbot": "^5.1.31", "isbot": "^5.1.31",

View File

@ -41,6 +41,9 @@ importers:
dayjs: dayjs:
specifier: ^1.11.19 specifier: ^1.11.19
version: 1.11.19 version: 1.11.19
embla-carousel-autoplay:
specifier: ^8.6.0
version: 8.6.0(embla-carousel@8.6.0)
embla-carousel-react: embla-carousel-react:
specifier: ^8.6.0 specifier: ^8.6.0
version: 8.6.0(react@19.2.0) version: 8.6.0(react@19.2.0)
@ -1475,6 +1478,11 @@ packages:
electron-to-chromium@1.5.255: electron-to-chromium@1.5.255:
resolution: {integrity: sha512-Z9oIp4HrFF/cZkDPMpz2XSuVpc1THDpT4dlmATFlJUIBVCy9Vap5/rIXsASP1CscBacBqhabwh8vLctqBwEerQ==} resolution: {integrity: sha512-Z9oIp4HrFF/cZkDPMpz2XSuVpc1THDpT4dlmATFlJUIBVCy9Vap5/rIXsASP1CscBacBqhabwh8vLctqBwEerQ==}
embla-carousel-autoplay@8.6.0:
resolution: {integrity: sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA==}
peerDependencies:
embla-carousel: 8.6.0
embla-carousel-react@8.6.0: embla-carousel-react@8.6.0:
resolution: {integrity: sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==} resolution: {integrity: sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==}
peerDependencies: peerDependencies:
@ -4203,6 +4211,10 @@ snapshots:
electron-to-chromium@1.5.255: {} electron-to-chromium@1.5.255: {}
embla-carousel-autoplay@8.6.0(embla-carousel@8.6.0):
dependencies:
embla-carousel: 8.6.0
embla-carousel-react@8.6.0(react@19.2.0): embla-carousel-react@8.6.0(react@19.2.0):
dependencies: dependencies:
embla-carousel: 8.6.0 embla-carousel: 8.6.0