文、意如
最新消息



NewsSection.tsx
"use client";
import "keen-slider/keen-slider.min.css";
import { useKeenSlider } from "keen-slider/react";
import { useState } from "react";
import { ArrowLeft, ArrowRight } from "lucide-react";
type NewsItem = {
title: string;
image: string;
summary: string;
link: string;
};
const newsList: NewsItem[] = [
{
title: "全新官網上線啦!",
image: "/images/news1.jpg",
summary: "我們重新設計了網站介面,提供更流暢的使用體驗。",
link: "#",
},
{
title: "夏季優惠活動開跑",
image: "/images/news2.jpg",
summary: "限時折扣全面開跑,快來看看有沒有你喜歡的商品吧!",
link: "#",
},
{
title: "產品上架公告",
image: "/images/news3.jpg",
summary: "我們新增了一系列全新產品,立即瀏覽了解更多資訊。",
link: "#",
},
{
title: "售後服務升級",
image: "/images/news4.jpg",
summary: "全新客服系統上線,24 小時為您服務。",
link: "#",
},
];
export default function NewsCarousel() {
const [currentSlide, setCurrentSlide] = useState(0);
const [sliderRef, instanceRef] = useKeenSlider<HTMLDivElement>({
loop: false,
slides: {
perView: 1,
spacing: 16,
},
breakpoints: {
"(min-width: 768px)": {
slides: {
perView: 3,
spacing: 24,
},
},
},
slideChanged(slider) {
setCurrentSlide(slider.track.details.rel);
},
});
const totalPages = Math.ceil(newsList.length / 3);
return (
<section className="bg-white py-16 px-4">
<div className="max-w-6xl mx-auto">
<div className="flex justify-between items-center mb-6">
<h2 className="text-4xl font-bold text-center w-full text-gray-900">
最新消息
</h2>
</div>
<div className="relative">
<div ref={sliderRef} className="keen-slider">
{newsList.map((item, idx) => (
<div key={idx} className="keen-slider__slide">
<a
href={item.link}
className="block bg-white border rounded-lg shadow-sm hover:shadow-md transition h-[400px] overflow-hidden flex flex-col"
>
<img
src={item.image}
alt={item.title}
className="w-full h-48 object-cover rounded-t-lg"
/>
<div className="p-4 flex flex-col flex-grow">
<h3 className="text-lg font-semibold text-gray-800 line-clamp-2">
{item.title}
</h3>
<p className="text-sm text-gray-700 mt-2 line-clamp-3">
{item.summary}
</p>
</div>
</a>
</div>
))}
</div>
</div>
{/* 頁碼指示 */}
<div className="flex justify-center mt-6 gap-2">
{Array.from({ length: totalPages }).map((_, idx) => (
<button
key={idx}
onClick={() => instanceRef.current?.moveToIdx(idx * 3)}
className={`px-3 py-1 text-sm rounded ${
currentSlide === idx * 3
? "bg-black text-white"
: "bg-gray-200 text-gray-800"
}`}
>
{idx + 1}
</button>
))}
</div>
</div>
</section>
);
}
page.tsx
import Navbar from "@/components/Navbar";
import HeroCarousel from "@/components/HeroCarousel";
import NewsSection from "@/components/NewsSection";
export default function Home() {
return (
<>
<Navbar />
<main className="pt-15 min-h-screen">
<HeroCarousel />
<NewsSection />
<div className="p-8">
<h1 className="text-3xl font-bold text-black">首頁內容</h1>
</div>
</main>
</>
);
}
產品資訊


public/images/
├── product1.jpg
├── product2.jpg
├── product3.jpg
└── product4.jpg
src/components/ProductCard.tsx
// src/components/ProductCard.tsx
type Product = {
id: number
name: string
image: string
description: string
}
export default function ProductCard({ product }: { product: Product }) {
return (
<div className="border rounded-lg overflow-hidden shadow-sm hover:shadow-md transition bg-white">
<img
src={product.image}
alt={product.name}
className="w-full h-48 object-cover"
/>
<div className="p-4">
<h3 className="text-lg font-semibold text-gray-800">{product.name}</h3>
<p className="text-sm text-gray-600 mt-1 line-clamp-2">{product.description}</p>
</div>
</div>
)
}
src/components/ProductSection.tsx
// src/components/ProductSection.tsx
import ProductCard from "@/components/ProductCard"
const dummyProducts = Array.from({ length: 8 }).map((_, index) => ({
id: index + 1,
name: `產品名稱 ${index + 1}`,
image: `/images/product${(index % 8) + 1}.jpg`,
description: "這是一段產品介紹的範例內容,可以用兩行文字呈現。",
}))
export default function ProductSection() {
return (
<section className="py-12 bg-white">
<div className="max-w-7xl mx-auto px-4">
<h2 className="text-4xl font-bold text-center mb-8 text-gray-900">產品資訊</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-4 gap-6">
{dummyProducts.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</div>
<div className="mt-8 flex justify-center">
<a
href="/products"
className="px-6 py-2 bg-black text-white rounded hover:bg-gray-800 transition"
>
查看更多
</a>
</div>
</div>
</section>
)
}
src/app/page.tsx
// src/app/page.tsx
import Navbar from "@/components/Navbar";
import HeroCarousel from "@/components/HeroCarousel";
import NewsSection from "@/components/NewsSection";
import ProductSection from "@/components/ProductSection";
export default function Home() {
return (
<>
<Navbar />
<main className="pt-15 min-h-screen">
<HeroCarousel />
<NewsSection />
<ProductSection />
<div className="p-8">
<h1 className="text-3xl font-bold text-black">首頁內容</h1>
</div>
</main>
</>
);
}
Yiru@Studio - 關於我 - 意如