Seed: music template (13 files)
This commit is contained in:
@@ -0,0 +1,128 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Headphones, Clock, Music, ChevronDown, ChevronUp } from "lucide-react";
|
||||||
|
import Header from "@/components/Header";
|
||||||
|
import Footer from "@/components/Footer";
|
||||||
|
|
||||||
|
const filters = ["All", "Albums", "EPs", "Singles"];
|
||||||
|
|
||||||
|
const releases = [
|
||||||
|
{
|
||||||
|
title: "Chromatic Abyss", year: "2026", type: "Albums", trackCount: 12, genre: "Synthwave", gradient: "from-purple-600 to-fuchsia-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Neon Requiem", dur: "4:12" }, { n: "02", title: "Violet Horizon", dur: "3:48" },
|
||||||
|
{ n: "03", title: "Pulse Decay", dur: "5:01" }, { n: "04", title: "Afterglow", dur: "3:33" },
|
||||||
|
{ n: "05", title: "Starfall", dur: "4:27" }, { n: "06", title: "Digital Mirage", dur: "3:55" },
|
||||||
|
{ n: "07", title: "Eclipse Rising", dur: "6:10" }, { n: "08", title: "Last Transmission", dur: "4:44" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Midnight Circuits", year: "2024", type: "Albums", trackCount: 10, genre: "Electronic", gradient: "from-fuchsia-500 to-pink-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Wire Dreams", dur: "3:56" }, { n: "02", title: "Copper Sky", dur: "4:22" },
|
||||||
|
{ n: "03", title: "Binary Heart", dur: "3:18" }, { n: "04", title: "Flux State", dur: "5:05" },
|
||||||
|
{ n: "05", title: "Overload", dur: "4:11" }, { n: "06", title: "Midnight Run", dur: "3:40" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Phantom Frequencies", year: "2022", type: "Albums", trackCount: 11, genre: "Darkwave", gradient: "from-violet-600 to-purple-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Ghost Signal", dur: "4:05" }, { n: "02", title: "Static Bloom", dur: "3:30" },
|
||||||
|
{ n: "03", title: "Void Walker", dur: "5:22" }, { n: "04", title: "Fade Pattern", dur: "3:47" },
|
||||||
|
{ n: "05", title: "Deep Frequency", dur: "4:38" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Neon Therapy", year: "2023", type: "EPs", trackCount: 6, genre: "Ambient", gradient: "from-indigo-600 to-violet-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Warm Static", dur: "3:22" }, { n: "02", title: "Soft Reboot", dur: "4:10" },
|
||||||
|
{ n: "03", title: "Pastel Waves", dur: "3:55" }, { n: "04", title: "Calm Protocol", dur: "4:31" },
|
||||||
|
{ n: "05", title: "Drift Mode", dur: "3:08" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Genesis Protocol", year: "2021", type: "EPs", trackCount: 5, genre: "Electro", gradient: "from-purple-700 to-indigo-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Boot Sequence", dur: "4:15" }, { n: "02", title: "Raw Input", dur: "3:42" },
|
||||||
|
{ n: "03", title: "Core Dump", dur: "5:00" }, { n: "04", title: "Voltage", dur: "3:28" },
|
||||||
|
{ n: "05", title: "First Light", dur: "4:50" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Supernova", year: "2025", type: "Singles", trackCount: 1, genre: "Synthpop", gradient: "from-fuchsia-600 to-rose-500",
|
||||||
|
tracks: [
|
||||||
|
{ n: "01", title: "Supernova", dur: "3:45" },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function MusicPage() {
|
||||||
|
const [filter, setFilter] = useState("All");
|
||||||
|
const [expanded, setExpanded] = useState<number | null>(null);
|
||||||
|
|
||||||
|
const filtered = filter === "All" ? releases : releases.filter((r) => r.type === filter);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen bg-slate-950 text-white">
|
||||||
|
<Header />
|
||||||
|
|
||||||
|
{/* Hero */}
|
||||||
|
<section className="pt-32 pb-16 text-center px-6">
|
||||||
|
<h1 className="text-5xl md:text-6xl font-black tracking-tight mb-4 bg-gradient-to-r from-purple-400 to-fuchsia-400 bg-clip-text text-transparent animate-fade-up">Discography</h1>
|
||||||
|
<p className="text-slate-400 max-w-xl mx-auto">Every record, every sound, every moment.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Filters */}
|
||||||
|
<section className="px-6 pb-6">
|
||||||
|
<div className="mx-auto max-w-5xl flex flex-wrap gap-2 justify-center">
|
||||||
|
{filters.map((f) => (
|
||||||
|
<Button key={f} variant={filter === f ? "default" : "outline"} size="sm" onClick={() => { setFilter(f); setExpanded(null); }} className={filter === f ? "bg-purple-600 hover:bg-purple-500 active:scale-[0.98] text-white" : "border-slate-700 text-slate-300 hover:bg-slate-800 active:scale-[0.98]"}>
|
||||||
|
{f}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Releases Grid */}
|
||||||
|
<section className="px-6 pb-24">
|
||||||
|
<div className="mx-auto max-w-5xl grid sm:grid-cols-2 lg:grid-cols-3 gap-6 stagger">
|
||||||
|
{filtered.map((r, i) => (
|
||||||
|
<Card key={i} className="backdrop-blur-sm bg-card/80 border-border/50 hover:border-purple-500/30 hover:-translate-y-1 hover:shadow-lg transition-all duration-300 overflow-hidden">
|
||||||
|
<div className={`aspect-square bg-gradient-to-br \${r.gradient} flex items-center justify-center relative`}>
|
||||||
|
<Music className="h-20 w-20 text-white/50" />
|
||||||
|
<Badge className="absolute top-3 right-3 bg-black/40 text-white border-white/20 text-xs">{r.type === "Albums" ? "Album" : r.type === "EPs" ? "EP" : "Single"}</Badge>
|
||||||
|
</div>
|
||||||
|
<CardContent className="p-5">
|
||||||
|
<h3 className="font-bold text-white text-lg mb-1">{r.title}</h3>
|
||||||
|
<div className="flex items-center gap-2 mb-3">
|
||||||
|
<span className="text-sm text-slate-400">{r.year}</span>
|
||||||
|
<span className="text-slate-600">·</span>
|
||||||
|
<span className="text-sm text-slate-400">{r.trackCount} tracks</span>
|
||||||
|
</div>
|
||||||
|
<Badge className="mb-4 bg-purple-500/15 text-purple-300 border-purple-500/20 text-xs">{r.genre}</Badge>
|
||||||
|
<Button variant="ghost" size="sm" className="w-full text-purple-400 hover:text-purple-300 hover:bg-purple-500/10" onClick={() => setExpanded(expanded === i ? null : i)}>
|
||||||
|
{expanded === i ? <><ChevronUp className="h-4 w-4 mr-2" />Hide Tracks</> : <><ChevronDown className="h-4 w-4 mr-2" />Show Tracks</>}
|
||||||
|
</Button>
|
||||||
|
{expanded === i && (
|
||||||
|
<div className="mt-3 space-y-2 border-t border-slate-800 pt-3">
|
||||||
|
{r.tracks.map((t) => (
|
||||||
|
<div key={t.n} className="flex items-center gap-3 text-sm group cursor-pointer hover:bg-purple-500/5 rounded px-2 py-1 transition-colors">
|
||||||
|
<span className="text-slate-600 font-mono text-xs">{t.n}</span>
|
||||||
|
<span className="flex-1 text-slate-300 group-hover:text-purple-300 transition-colors">{t.title}</span>
|
||||||
|
<span className="text-slate-500 flex items-center gap-1"><Clock className="h-3 w-3" />{t.dur}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<Footer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user