Erste Aenderungen

This commit is contained in:
Marc Wieland 2025-04-20 17:15:07 +02:00
parent a517191176
commit 79aa26d48a
17 changed files with 418 additions and 184 deletions

View File

@ -3,18 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>froggy-volleyball-haven</title> <title>TG Laudenbach - Volleyball</title>
<meta name="description" content="Lovable Generated Project" />
<meta name="author" content="Lovable" />
<meta property="og:title" content="Lovable Generated Project" />
<meta property="og:description" content="Lovable Generated Project" />
<meta property="og:type" content="website" />
<meta property="og:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@lovable_dev" />
<meta name="twitter:image" content="https://lovable.dev/opengraph-image-p98pqg.png" />
</head> </head>
<body> <body>

33
package-lock.json generated
View File

@ -43,6 +43,7 @@
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"embla-carousel-react": "^8.3.0", "embla-carousel-react": "^8.3.0",
"input-otp": "^1.2.4", "input-otp": "^1.2.4",
"keen-slider": "^6.8.6",
"lucide-react": "^0.462.0", "lucide-react": "^0.462.0",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"react": "^18.3.1", "react": "^18.3.1",
@ -50,7 +51,7 @@
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-hook-form": "^7.53.0", "react-hook-form": "^7.53.0",
"react-resizable-panels": "^2.1.3", "react-resizable-panels": "^2.1.3",
"react-router-dom": "^6.26.2", "react-router-dom": "^6.30.0",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"sonner": "^1.5.0", "sonner": "^1.5.0",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",
@ -2310,9 +2311,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@remix-run/router": { "node_modules/@remix-run/router": {
"version": "1.20.0", "version": "1.23.0",
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz",
"integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==", "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
@ -4942,6 +4943,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/keen-slider": {
"version": "6.8.6",
"resolved": "https://registry.npmjs.org/keen-slider/-/keen-slider-6.8.6.tgz",
"integrity": "sha512-dcEQ7GDBpCjUQA8XZeWh3oBBLLmyn8aoeIQFGL/NTVkoEOsmlnXqA4QykUm/SncolAZYGsEk/PfUhLZ7mwMM2w==",
"license": "MIT"
},
"node_modules/keyv": { "node_modules/keyv": {
"version": "4.5.4", "version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
@ -6117,12 +6124,12 @@
} }
}, },
"node_modules/react-router": { "node_modules/react-router": {
"version": "6.27.0", "version": "6.30.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz", "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.0.tgz",
"integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==", "integrity": "sha512-D3X8FyH9nBcTSHGdEKurK7r8OYE1kKFn3d/CF+CoxbSHkxU7o37+Uh7eAHRXr6k2tSExXYO++07PeXJtA/dEhQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@remix-run/router": "1.20.0" "@remix-run/router": "1.23.0"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"
@ -6132,13 +6139,13 @@
} }
}, },
"node_modules/react-router-dom": { "node_modules/react-router-dom": {
"version": "6.27.0", "version": "6.30.0",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz", "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.0.tgz",
"integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==", "integrity": "sha512-x30B78HV5tFk8ex0ITwzC9TTZMua4jGyA9IUlH1JLQYQTFyxr/ZxwOJq7evg1JX1qGVUcvhsmQSKdPncQrjTgA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@remix-run/router": "1.20.0", "@remix-run/router": "1.23.0",
"react-router": "6.27.0" "react-router": "6.30.0"
}, },
"engines": { "engines": {
"node": ">=14.0.0" "node": ">=14.0.0"

View File

@ -46,6 +46,7 @@
"date-fns": "^3.6.0", "date-fns": "^3.6.0",
"embla-carousel-react": "^8.3.0", "embla-carousel-react": "^8.3.0",
"input-otp": "^1.2.4", "input-otp": "^1.2.4",
"keen-slider": "^6.8.6",
"lucide-react": "^0.462.0", "lucide-react": "^0.462.0",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"react": "^18.3.1", "react": "^18.3.1",
@ -53,7 +54,7 @@
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-hook-form": "^7.53.0", "react-hook-form": "^7.53.0",
"react-resizable-panels": "^2.1.3", "react-resizable-panels": "^2.1.3",
"react-router-dom": "^6.26.2", "react-router-dom": "^6.30.0",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"sonner": "^1.5.0", "sonner": "^1.5.0",
"tailwind-merge": "^2.5.2", "tailwind-merge": "^2.5.2",

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

View File

@ -15,7 +15,7 @@ const Footer = () => {
<span className="font-bold text-xl">TG Laudenbach</span> <span className="font-bold text-xl">TG Laudenbach</span>
</div> </div>
<p className="text-gray-400"> <p className="text-gray-400">
Volleyball mit Leidenschaft und Teamgeist seit 1975. Volleyball seit 1974.
</p> </p>
<div className="flex space-x-4"> <div className="flex space-x-4">
<Button variant="ghost" size="icon" className="text-gray-400 hover:text-white"> <Button variant="ghost" size="icon" className="text-gray-400 hover:text-white">

View File

@ -1,24 +1,28 @@
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Volleyball } from "lucide-react"; import { Volleyball } from "lucide-react";
const Hero = () => { const Hero = () => {
return ( return (
<div className="hero-pattern pt-28 pb-16"> <div
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> className="relative min-h-[600px] md:min-h-[700px] lg:min-h-[800px] bg-cover bg-center bg-no-repeat pt-28 pb-16"
style={{ backgroundImage: "url('/images/abteilung-bg.jpg')" }}
>
<div className="absolute inset-0 bg-black/15 z-0" />
<div className="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex flex-col md:flex-row items-center"> <div className="flex flex-col md:flex-row items-center">
<div className="md:w-1/2 text-white"> <div className="md:w-1/2 text-white">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold"> <h1 className="text-4xl md:text-5xl lg:text-6xl font-bold">
Willkommen beim <span className="text-white">TG Laudenbach</span> Willkommen bei der <span className="text-white">TG Laudenbach - Abteilung Volleyball</span>
</h1> </h1>
<p className="mt-4 text-lg md:text-xl"> <p className="mt-4 text-lg md:text-xl">
Volleyball mit Leidenschaft und Teamgeist - werde Teil unserer Gemeinschaft! Volleyball mit Leidenschaft und Teamgeist werde Teil unserer Gemeinschaft!
</p> </p>
<div className="mt-8 flex flex-wrap gap-4"> <div className="mt-8 flex flex-wrap gap-4">
<Button className="bg-white text-frog-700 hover:bg-gray-100"> <Button className="bg-white text-frog-700 hover:bg-gray-100">
Training besuchen Training besuchen
</Button> </Button>
<Button variant="outline" className="text-white border-white hover:bg-white/10"> <Button className="bg-white text-frog-700 hover:bg-gray-100">
Teams kennenlernen Teams kennenlernen
</Button> </Button>
</div> </div>

View File

@ -2,6 +2,7 @@
import { useState } from 'react'; import { useState } from 'react';
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Menu, X, Volleyball } from "lucide-react"; import { Menu, X, Volleyball } from "lucide-react";
import {Link} from "react-router-dom";
const Navbar = () => { const Navbar = () => {
const [isMenuOpen, setIsMenuOpen] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false);
@ -11,7 +12,7 @@ const Navbar = () => {
}; };
return ( return (
<nav className="bg-white shadow-md fixed w-full z-50"> <nav className="fixed top-0 left-0 w-full z-50 bg-white/30 backdrop-blur-md border-b border-white/20">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16 items-center"> <div className="flex justify-between h-16 items-center">
<div className="flex items-center"> <div className="flex items-center">
@ -27,7 +28,11 @@ const Navbar = () => {
<a href="#gallery" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Galerie</a> <a href="#gallery" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Galerie</a>
<a href="#about" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Über uns</a> <a href="#about" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Über uns</a>
<a href="#contact" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Kontakt</a> <a href="#contact" className="text-gray-700 hover:text-frog-600 px-3 py-2 rounded-md font-medium">Kontakt</a>
<Button className="bg-frog-500 hover:bg-frog-600 text-white">Mitglied werden</Button> <Link to="/mitglied-werden" className="w-full">
<Button className="w-full bg-frog-500 hover:bg-frog-600 text-white">
Mitglied werden
</Button>
</Link>
</div> </div>
{/* Mobile menu button */} {/* Mobile menu button */}

View File

@ -2,6 +2,7 @@
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { ArrowRight } from "lucide-react"; import { ArrowRight } from "lucide-react";
import {Link} from "react-router-dom";
const NewsSection = () => { const NewsSection = () => {
const news = [ const news = [
@ -59,9 +60,11 @@ const NewsSection = () => {
</div> </div>
<div className="text-center mt-12"> <div className="text-center mt-12">
<Link to="/alle-neuigkeiten">
<Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50"> <Button variant="outline" className="border-frog-500 text-frog-600 hover:bg-frog-50">
Alle Neuigkeiten Alle Neuigkeiten
</Button> </Button>
</Link>
</div> </div>
</div> </div>
</section> </section>

View File

@ -1,7 +1,9 @@
import { useKeenSlider } from "keen-slider/react";
import { useRef } from "react";
import { ChevronLeft, ChevronRight, Users } from "lucide-react";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Users } from "lucide-react"; import {Link} from "react-router-dom";
const TeamSection = () => { const TeamSection = () => {
const teams = [ const teams = [
@ -32,20 +34,68 @@ const TeamSection = () => {
league: "Hobby", league: "Hobby",
description: "Für alle, die Volleyball zum Spaß spielen möchten. Anfänger und Fortgeschrittene sind willkommen!", description: "Für alle, die Volleyball zum Spaß spielen möchten. Anfänger und Fortgeschrittene sind willkommen!",
trainingTimes: "Mo 18:00 - 20:00 Uhr" trainingTimes: "Mo 18:00 - 20:00 Uhr"
},
{
id: 5,
name: "U12",
league: "Jugendliga",
description: "Unsere kleinsten Stars sammeln erste Spielerfahrung in der U12-Jugendliga.",
trainingTimes: "Mi 16:00 - 17:30 Uhr"
},
{
id: 6,
name: "Mixed-Team",
league: "Hobbyliga",
description: "Spaß, Gemeinschaft und gemischte Teams unser Mixed-Team steht für Vielfalt!",
trainingTimes: "Fr 19:00 - 21:00 Uhr"
} }
]; ];
const [sliderRef, slider] = useKeenSlider<HTMLDivElement>({
slides: {
perView: 1,
spacing: 16,
},
breakpoints: {
"(min-width: 640px)": {
slides: { perView: 2, spacing: 16 },
},
"(min-width: 1024px)": {
slides: { perView: 3, spacing: 20 },
},
"(min-width: 1280px)": {
slides: { perView: 4, spacing: 24 },
},
},
});
return ( return (
<section id="team" className="py-16"> <section id="team" className="py-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12"> <div className="text-center mb-12">
<h2 className="text-3xl font-bold text-gray-900">Unsere Teams</h2> <h2 className="text-3xl font-bold text-gray-900">Unsere Teams</h2>
<p className="mt-4 text-xl text-gray-600">Von Anfängern bis Leistungssport - für jeden ist etwas dabei</p> <p className="mt-4 text-xl text-gray-600">Von Anfängern bis Leistungssport für jeden ist etwas dabei</p>
</div> </div>
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6"> <div className="relative">
{/* Navigation Buttons */}
<button
onClick={() => slider.current?.prev()}
className="absolute left-0 top-1/2 -translate-y-1/2 z-10 bg-white rounded-full p-2 shadow-md hover:bg-frog-100"
>
<ChevronLeft className="text-frog-600" />
</button>
<button
onClick={() => slider.current?.next()}
className="absolute right-0 top-1/2 -translate-y-1/2 z-10 bg-white rounded-full p-2 shadow-md hover:bg-frog-100"
>
<ChevronRight className="text-frog-600" />
</button>
<div ref={sliderRef} className="keen-slider">
{teams.map((team) => ( {teams.map((team) => (
<Card key={team.id} className="hover:shadow-lg transition-shadow border-t-4 border-t-frog-500"> <div key={team.id} className="keen-slider__slide">
<Card className="h-full hover:shadow-lg transition-shadow border-t-4 border-t-frog-500">
<CardHeader> <CardHeader>
<CardTitle className="flex items-center"> <CardTitle className="flex items-center">
<Users className="h-5 w-5 mr-2 text-frog-500" /> <Users className="h-5 w-5 mr-2 text-frog-500" />
@ -60,14 +110,18 @@ const TeamSection = () => {
</div> </div>
</CardContent> </CardContent>
<CardFooter> <CardFooter>
<Link to={`/teams/${team.id}`} className="w-full">
<Button variant="outline" size="sm" className="w-full border-frog-500 text-frog-600 hover:bg-frog-50"> <Button variant="outline" size="sm" className="w-full border-frog-500 text-frog-600 hover:bg-frog-50">
Team Details Team Details
</Button> </Button>
</Link>
</CardFooter> </CardFooter>
</Card> </Card>
</div>
))} ))}
</div> </div>
</div> </div>
</div>
</section> </section>
); );
}; };

19
src/layout/Layout.tsx Normal file
View File

@ -0,0 +1,19 @@
import Navbar from "@/components/Navbar";
import Footer from "@/components/Footer";
import { ReactNode } from "react";
type LayoutProps = {
children: ReactNode;
};
const Layout = ({ children }: LayoutProps) => {
return (
<div className="min-h-screen bg-white flex flex-col">
<Navbar />
<main className="flex-1 pt-16">{children}</main>
<Footer />
</div>
);
};
export default Layout;

View File

@ -1,5 +1,49 @@
import { createRoot } from 'react-dom/client' import React from "react";
import App from './App.tsx' import ReactDOM from "react-dom/client";
import './index.css' import { BrowserRouter, Routes, Route } from "react-router-dom";
import "keen-slider/keen-slider.min.css";
createRoot(document.getElementById("root")!).render(<App />); import Index from "./pages/Index";
import MitgliedWerdenPage from "./pages/MitgliedWerden";
import AlleNeuigkeitenPage from "./pages/AlleNeuigkeiten";
import Layout from "./layout/Layout";
import TeamDetailPage from "./pages/TeamDetailPage";
import "./index.css"
ReactDOM.createRoot(document.getElementById("root")!).render(
<React.StrictMode>
<BrowserRouter>
<Routes>
<Route
path="/"
element={
<Layout>
<Index />
</Layout>
}
/>
<Route
path="/mitglied-werden"
element={
<Layout>
<MitgliedWerdenPage />
</Layout>
}
/>
<Route
path="/alle-neuigkeiten"
element={
<Layout>
<AlleNeuigkeitenPage />
</Layout>
}
/>
<Route path="/teams/:id" element={<Layout><TeamDetailPage /></Layout>} />
</Routes>
</BrowserRouter>
</React.StrictMode>
);

View File

@ -0,0 +1,52 @@
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
const news = [
{
id: 1,
title: "Saisonstart 2023/24",
date: "15. September 2023",
description: "Die neue Saison beginnt mit einem Heimspiel gegen VfB Mosbach. Kommt vorbei und unterstützt unser Team!",
image: "https://images.unsplash.com/photo-1612872087720-bb876e2e67d1?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
},
{
id: 2,
title: "Beachvolleyball-Turnier",
date: "3. Juli 2023",
description: "Unser jährliches Beachvolleyball-Turnier war ein voller Erfolg! 24 Teams kämpften um den Sieg.",
image: "https://images.unsplash.com/photo-1583514555852-6f77e7c9e081?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
},
{
id: 3,
title: "Neuer Trainer für die Jugendmannschaft",
date: "21. Mai 2023",
description: "Wir freuen uns, Marc Schneider als neuen Trainer für unsere U16-Mannschaft begrüßen zu dürfen.",
image: "https://images.unsplash.com/photo-1547347298-4074fc3086f0?ixlib=rb-4.0.3&auto=format&fit=crop&w=500&q=80"
},
// 🔜 später kannst du hier easy mehr News reinladen oder aus ner API holen
];
const AlleNeuigkeitenPage = () => {
return (
<div className="max-w-5xl mx-auto px-4 py-12">
<h1 className="text-3xl font-bold text-center mb-8 text-frog-600">Alle Neuigkeiten</h1>
<div className="grid md:grid-cols-2 gap-6">
{news.map((item) => (
<Card key={item.id} className="overflow-hidden">
<div className="h-48 overflow-hidden">
<img src={item.image} alt={item.title} className="w-full h-full object-cover" />
</div>
<CardHeader>
<CardTitle>{item.title}</CardTitle>
<CardDescription>{item.date}</CardDescription>
</CardHeader>
<CardContent>
<p>{item.description}</p>
</CardContent>
</Card>
))}
</div>
</div>
);
};
export default AlleNeuigkeitenPage;

View File

@ -11,14 +11,12 @@ import Footer from "@/components/Footer";
const Index = () => { const Index = () => {
return ( return (
<div className="min-h-screen bg-white"> <div className="min-h-screen bg-white">
<Navbar />
<Hero /> <Hero />
<NewsSection /> <NewsSection />
<TeamSection /> <TeamSection />
<GallerySection /> <GallerySection />
<AboutSection /> <AboutSection />
<ContactSection /> <ContactSection />
<Footer />
</div> </div>
); );
}; };

View File

@ -0,0 +1,26 @@
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Card, CardContent } from "@/components/ui/card";
const MitgliedWerdenPage = () => {
return (
<div className="flex justify-center mt-10">
<Card className="w-full max-w-md">
<CardContent className="p-6">
<h1 className="text-2xl font-bold mb-4 text-center">Mitglied werden</h1>
<form className="space-y-4">
<Input placeholder="Vorname" />
<Input placeholder="Nachname" />
<Input placeholder="E-Mail" type="email" />
<Input placeholder="Geburtsdatum" type="date" />
<Button type="submit" className="w-full bg-frog-500 hover:bg-frog-600 text-white">
Absenden
</Button>
</form>
</CardContent>
</Card>
</div>
);
};
export default MitgliedWerdenPage;

View File

@ -0,0 +1,37 @@
import { useParams } from "react-router-dom";
const teamData = [
{
id: "1",
name: "Damen I",
league: "Landesliga Nord",
description: "Unsere erste Damenmannschaft ...",
trainingTimes: "Di & Do 19:00 - 21:00 Uhr",
},
{
id: "2",
name: "Herren I",
league: "Bezirksliga",
description: "Das Herrenteam kämpft ...",
trainingTimes: "Mo & Mi 20:00 - 22:00 Uhr",
},
// usw...
];
const TeamDetailPage = () => {
const { id } = useParams();
const team = teamData.find((t) => t.id === id);
if (!team) return <p>Team nicht gefunden 🐸</p>;
return (
<div className="max-w-3xl mx-auto py-12 px-4">
<h1 className="text-4xl font-bold text-frog-600 mb-2">{team.name}</h1>
<p className="text-gray-700 mb-2">{team.league}</p>
<p className="text-gray-600 mb-4">{team.description}</p>
<p className="text-sm text-frog-700 font-medium">Training: {team.trainingTimes}</p>
</div>
);
};
export default TeamDetailPage;

0
src/routes.tsx Normal file
View File

View File

@ -1,4 +1,3 @@
import type { Config } from "tailwindcss"; import type { Config } from "tailwindcss";
export default { export default {
@ -13,108 +12,104 @@ export default {
theme: { theme: {
container: { container: {
center: true, center: true,
padding: '2rem', padding: "2rem",
screens: { screens: {
'2xl': '1400px' "2xl": "1400px",
} },
}, },
extend: { extend: {
backgroundImage: {
"hero-pattern": "url('/images/abteilung-bg.jpg')",
},
colors: { colors: {
border: 'hsl(var(--border))', border: "hsl(var(--border))",
input: 'hsl(var(--input))', input: "hsl(var(--input))",
ring: 'hsl(var(--ring))', ring: "hsl(var(--ring))",
background: 'hsl(var(--background))', background: "hsl(var(--background))",
foreground: 'hsl(var(--foreground))', foreground: "hsl(var(--foreground))",
primary: { primary: {
DEFAULT: 'hsl(var(--primary))', DEFAULT: "hsl(var(--primary))",
foreground: 'hsl(var(--primary-foreground))' foreground: "hsl(var(--primary-foreground))",
}, },
secondary: { secondary: {
DEFAULT: 'hsl(var(--secondary))', DEFAULT: "hsl(var(--secondary))",
foreground: 'hsl(var(--secondary-foreground))' foreground: "hsl(var(--secondary-foreground))",
}, },
destructive: { destructive: {
DEFAULT: 'hsl(var(--destructive))', DEFAULT: "hsl(var(--destructive))",
foreground: 'hsl(var(--destructive-foreground))' foreground: "hsl(var(--destructive-foreground))",
}, },
muted: { muted: {
DEFAULT: 'hsl(var(--muted))', DEFAULT: "hsl(var(--muted))",
foreground: 'hsl(var(--muted-foreground))' foreground: "hsl(var(--muted-foreground))",
}, },
accent: { accent: {
DEFAULT: 'hsl(var(--accent))', DEFAULT: "hsl(var(--accent))",
foreground: 'hsl(var(--accent-foreground))' foreground: "hsl(var(--accent-foreground))",
}, },
popover: { popover: {
DEFAULT: 'hsl(var(--popover))', DEFAULT: "hsl(var(--popover))",
foreground: 'hsl(var(--popover-foreground))' foreground: "hsl(var(--popover-foreground))",
}, },
card: { card: {
DEFAULT: 'hsl(var(--card))', DEFAULT: "hsl(var(--card))",
foreground: 'hsl(var(--card-foreground))' foreground: "hsl(var(--card-foreground))",
}, },
sidebar: { sidebar: {
DEFAULT: 'hsl(var(--sidebar-background))', DEFAULT: "hsl(var(--sidebar-background))",
foreground: 'hsl(var(--sidebar-foreground))', foreground: "hsl(var(--sidebar-foreground))",
primary: 'hsl(var(--sidebar-primary))', primary: "hsl(var(--sidebar-primary))",
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))', "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
accent: 'hsl(var(--sidebar-accent))', accent: "hsl(var(--sidebar-accent))",
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))', "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
border: 'hsl(var(--sidebar-border))', border: "hsl(var(--sidebar-border))",
ring: 'hsl(var(--sidebar-ring))' ring: "hsl(var(--sidebar-ring))",
}, },
frog: { frog: {
50: '#f0fdf4', 50: "#f0fdf4",
100: '#dcfce7', 100: "#dcfce7",
200: '#bbf7d0', 200: "#bbf7d0",
300: '#86efac', 300: "#86efac",
400: '#4ade80', 400: "#4ade80",
500: '#4CAF50', // Hauptfarbe Froschgrün 500: "#4CAF50", // Hauptfarbe Froschgrün
600: '#16a34a', 600: "#16a34a",
700: '#15803d', 700: "#15803d",
800: '#166534', 800: "#166534",
900: '#14532d', 900: "#14532d",
}
}, },
},
borderRadius: { borderRadius: {
lg: 'var(--radius)', lg: "var(--radius)",
md: 'calc(var(--radius) - 2px)', md: "calc(var(--radius) - 2px)",
sm: 'calc(var(--radius) - 4px)' sm: "calc(var(--radius) - 4px)",
}, },
keyframes: { keyframes: {
'accordion-down': { "accordion-down": {
from: { from: { height: "0" },
height: '0' to: { height: "var(--radix-accordion-content-height)" },
}, },
to: { "accordion-up": {
height: 'var(--radix-accordion-content-height)' from: { height: "var(--radix-accordion-content-height)" },
} to: { height: "0" },
}, },
'accordion-up': { "bounce-slow": {
from: { "0%, 100%": {
height: 'var(--radix-accordion-content-height)' transform: "translateY(-5%)",
animationTimingFunction: "cubic-bezier(0.8, 0, 1, 1)",
}, },
to: { "50%": {
height: '0' transform: "translateY(0)",
} animationTimingFunction: "cubic-bezier(0, 0, 0.2, 1)",
}, },
'bounce-slow': {
'0%, 100%': {
transform: 'translateY(-5%)',
animationTimingFunction: 'cubic-bezier(0.8, 0, 1, 1)'
}, },
'50%': {
transform: 'translateY(0)',
animationTimingFunction: 'cubic-bezier(0, 0, 0.2, 1)'
}
}
}, },
animation: { animation: {
'accordion-down': 'accordion-down 0.2s ease-out', "accordion-down": "accordion-down 0.2s ease-out",
'accordion-up': 'accordion-up 0.2s ease-out', "accordion-up": "accordion-up 0.2s ease-out",
'bounce-slow': 'bounce-slow 3s infinite' "bounce-slow": "bounce-slow 3s infinite",
} },
} },
}, },
plugins: [require("tailwindcss-animate")], plugins: [require("tailwindcss-animate")],
} satisfies Config; } satisfies Config;