Add partners section
This commit is contained in:
31
src/app.tsx
31
src/app.tsx
@ -1,3 +1,5 @@
|
||||
import { Navbar } from "./components/navbar/navbar";
|
||||
import { PartnersMarquee } from "./components/partners-marquee/partners-marquee";
|
||||
import { AuroraText } from "./components/ui/aurora-text";
|
||||
import { DotPattern } from "./components/ui/dot-pattern";
|
||||
import { RainbowButton } from "./components/ui/rainbow-button";
|
||||
@ -5,18 +7,8 @@ import { TextAnimate } from "./components/ui/text-animate";
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<div className="h-screen w-screen flex flex-col">
|
||||
<nav className="flex justify-between items-center p-4 px-6 shadow-md">
|
||||
<h1 className="text-2xl font-bold">Great Music LLM</h1>
|
||||
<div className="hidden sm:flex gap-2">
|
||||
<button className="bg-blue-500 text-white px-4 py-2 rounded">
|
||||
Button 1
|
||||
</button>
|
||||
<button className="bg-green-500 text-white px-4 py-2 rounded">
|
||||
Button 2
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div className="h-screen w-screen flex flex-col font-merriweather">
|
||||
<Navbar />
|
||||
<main className="flex-1 overflow-auto">
|
||||
<div
|
||||
className="h-full bg-cover bg-center
|
||||
@ -42,9 +34,18 @@ export function App() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative overflow-hidden">
|
||||
<DotPattern />
|
||||
Section 2 coming soon...
|
||||
<div className="relative overflow-hidden py-5 flex flex-col gap-5">
|
||||
<TextAnimate
|
||||
animation="blurInUp"
|
||||
by="character"
|
||||
as="h3"
|
||||
className="text-xl font-bold text-center"
|
||||
>
|
||||
Our Partners
|
||||
</TextAnimate>
|
||||
<PartnersMarquee />
|
||||
<span></span> {/* Spacer for DotPattern */}
|
||||
<DotPattern className="-z-10" />
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
15
src/components/navbar/navbar.tsx
Normal file
15
src/components/navbar/navbar.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
export function Navbar() {
|
||||
return (
|
||||
<nav className="flex justify-between items-center p-4 px-6 shadow-md">
|
||||
<h1 className="text-2xl font-bold font-alex-brush">Great Music LLM</h1>
|
||||
<div className="hidden sm:flex gap-2">
|
||||
<button className="bg-blue-500 text-white px-4 py-2 rounded">
|
||||
Button 1
|
||||
</button>
|
||||
<button className="bg-green-500 text-white px-4 py-2 rounded">
|
||||
Button 2
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
}
|
||||
48
src/components/partners-marquee/partners-marquee.tsx
Normal file
48
src/components/partners-marquee/partners-marquee.tsx
Normal file
@ -0,0 +1,48 @@
|
||||
import { Marquee } from "../ui/marquee";
|
||||
|
||||
export function PartnersMarquee() {
|
||||
const partners = [
|
||||
{
|
||||
name: "Conductor Orchestra",
|
||||
logo: "https://t3.ftcdn.net/jpg/05/71/43/76/360_F_571437617_ZNppyF5qpbJn9dYifhjWEQkgjbZNBXP9.jpg",
|
||||
},
|
||||
{
|
||||
name: "Chicago Symphony Orchestra",
|
||||
logo: "https://upload.wikimedia.org/wikipedia/commons/1/1f/Wiki-CSO_logo2024_stacked-whitebg.png",
|
||||
},
|
||||
{
|
||||
name: "Toronto Symphony Orchestra",
|
||||
logo: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSfThsC3B2BGCKjnyr_IMiJmp-0jI9I9blZrw&s",
|
||||
},
|
||||
{
|
||||
name: "Los Angeles Chamber Orchestra",
|
||||
logo: "https://admin.itsnicethat.com/images/TOHFR2DIydoDTaGM6NbfVRFZfJU=/168760/format-webp%7Cwidth-2880/5d947a047fa44cbd2200fd0f.jpg",
|
||||
},
|
||||
{
|
||||
name: "Richmond Symphony Orchestra",
|
||||
logo: "https://richmondsymphony.org/wp-content/uploads/2021/07/rso-logo-2023.png",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="relative flex w-full flex-col items-center justify-center overflow-hidden">
|
||||
<Marquee>
|
||||
{partners.map((partner) => (
|
||||
<div
|
||||
key={partner.name}
|
||||
className="flex flex-col items-center justify-center p-4 bg-white border-2 border-gray-300 rounded-lg shadow-md"
|
||||
>
|
||||
<img
|
||||
src={partner.logo}
|
||||
alt={`${partner.name} logo`}
|
||||
className="max-h-24"
|
||||
/>
|
||||
<p>{partner.name}</p>
|
||||
</div>
|
||||
))}
|
||||
</Marquee>
|
||||
<div className="from-background pointer-events-none absolute inset-y-0 left-0 w-4 bg-linear-to-r"></div>
|
||||
<div className="from-background pointer-events-none absolute inset-y-0 right-0 w-4 bg-linear-to-l"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
74
src/components/ui/marquee.tsx
Normal file
74
src/components/ui/marquee.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import type { ComponentPropsWithoutRef } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface MarqueeProps extends ComponentPropsWithoutRef<"div"> {
|
||||
/**
|
||||
* Optional CSS class name to apply custom styles
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Whether to reverse the animation direction
|
||||
* @default false
|
||||
*/
|
||||
reverse?: boolean;
|
||||
/**
|
||||
* Whether to pause the animation on hover
|
||||
* @default false
|
||||
*/
|
||||
pauseOnHover?: boolean;
|
||||
/**
|
||||
* Content to be displayed in the marquee
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Whether to animate vertically instead of horizontally
|
||||
* @default false
|
||||
*/
|
||||
vertical?: boolean;
|
||||
/**
|
||||
* Number of times to repeat the content
|
||||
* @default 4
|
||||
*/
|
||||
repeat?: number;
|
||||
}
|
||||
|
||||
export function Marquee({
|
||||
className,
|
||||
reverse = false,
|
||||
pauseOnHover = false,
|
||||
children,
|
||||
vertical = false,
|
||||
repeat = 4,
|
||||
...props
|
||||
}: MarqueeProps) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn(
|
||||
"group flex [gap:var(--gap)] overflow-hidden p-2 [--duration:40s] [--gap:1rem]",
|
||||
{
|
||||
"flex-row": !vertical,
|
||||
"flex-col": vertical,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{Array(repeat)
|
||||
.fill(0)
|
||||
.map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cn("flex shrink-0 justify-around [gap:var(--gap)]", {
|
||||
"animate-marquee flex-row": !vertical,
|
||||
"animate-marquee-vertical flex-col": vertical,
|
||||
"group-hover:[animation-play-state:paused]": pauseOnHover,
|
||||
"[animation-direction:reverse]": reverse,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
3
src/globals.d.ts
vendored
Normal file
3
src/globals.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
declare module "*.css";
|
||||
declare module "@fontsource/*" {}
|
||||
declare module "@fontsource-variable/*" {}
|
||||
@ -4,6 +4,9 @@
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme inline {
|
||||
--font-alex-brush: "Alex Brush", cursive;
|
||||
--font-merriweather: "Merriweather Variable", serif;
|
||||
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
@ -40,42 +43,70 @@
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--animate-aurora: aurora 8s ease-in-out infinite alternate;
|
||||
|
||||
@keyframes aurora {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
transform: rotate(-5deg) scale(0.9);
|
||||
}
|
||||
|
||||
25% {
|
||||
background-position: 50% 100%;
|
||||
transform: rotate(5deg) scale(1.1);
|
||||
}
|
||||
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
transform: rotate(-3deg) scale(0.95);
|
||||
}
|
||||
|
||||
75% {
|
||||
background-position: 50% 0%;
|
||||
transform: rotate(3deg) scale(1.05);
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
transform: rotate(-5deg) scale(0.9);
|
||||
}
|
||||
}
|
||||
|
||||
--animate-rainbow: rainbow var(--speed, 2s) infinite linear;
|
||||
--color-color-5: var(--color-5);
|
||||
--color-color-4: var(--color-4);
|
||||
--color-color-3: var(--color-3);
|
||||
--color-color-2: var(--color-2);
|
||||
--color-color-1: var(--color-1);
|
||||
|
||||
@keyframes rainbow {
|
||||
0% {
|
||||
background-position: 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: 200%;
|
||||
}
|
||||
}
|
||||
|
||||
--animate-marquee: marquee var(--duration) infinite linear;
|
||||
|
||||
--animate-marquee-vertical: marquee-vertical var(--duration) linear infinite;
|
||||
@keyframes marquee {
|
||||
from {
|
||||
transform: translateX(0);
|
||||
}
|
||||
to {
|
||||
transform: translateX(calc(-100% - var(--gap)));
|
||||
}
|
||||
}
|
||||
@keyframes marquee-vertical {
|
||||
from {
|
||||
transform: translateY(0);
|
||||
}
|
||||
to {
|
||||
transform: translateY(calc(-100% - var(--gap)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
@ -161,6 +192,7 @@
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ import { StrictMode } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import "./index.css";
|
||||
import { App } from "./app";
|
||||
import "@fontsource/alex-brush";
|
||||
import "@fontsource-variable/merriweather";
|
||||
|
||||
createRoot(document.getElementById("root")!).render(
|
||||
<StrictMode>
|
||||
|
||||
Reference in New Issue
Block a user