diff --git a/package-lock.json b/package-lock.json
index a0b9c28..d807d4c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,8 @@
"name": "bcdigital-challenge",
"version": "0.0.0",
"dependencies": {
+ "@fontsource-variable/merriweather": "^5.2.6",
+ "@fontsource/alex-brush": "^5.2.8",
"@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.16",
"class-variance-authority": "^0.7.1",
@@ -894,6 +896,24 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@fontsource-variable/merriweather": {
+ "version": "5.2.6",
+ "resolved": "https://registry.npmjs.org/@fontsource-variable/merriweather/-/merriweather-5.2.6.tgz",
+ "integrity": "sha512-bHCDt99f/M48eUcFA86uh/oSPyn8r/ZxXR9l578wqLvjTwDzXx8A/XOAI05WfJ3LnH1rDufQX5RJwiZtbXUCkw==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
+ "node_modules/@fontsource/alex-brush": {
+ "version": "5.2.8",
+ "resolved": "https://registry.npmjs.org/@fontsource/alex-brush/-/alex-brush-5.2.8.tgz",
+ "integrity": "sha512-ShSsZkWN7O6H6x56Jc2c1d+YXDTCGIRBvLKiVIa7r3tyg6Ern56fN2xriAjNNBmvn37Y96XCkavrpERm/IRCEQ==",
+ "license": "OFL-1.1",
+ "funding": {
+ "url": "https://github.com/sponsors/ayuhito"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
diff --git a/package.json b/package.json
index 09c430c..fee63ec 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,8 @@
"**/*": "prettier --write --ignore-unknown"
},
"dependencies": {
+ "@fontsource-variable/merriweather": "^5.2.6",
+ "@fontsource/alex-brush": "^5.2.8",
"@radix-ui/react-slot": "^1.2.3",
"@tailwindcss/vite": "^4.1.16",
"class-variance-authority": "^0.7.1",
diff --git a/src/app.tsx b/src/app.tsx
index 7fd6599..de0a002 100644
--- a/src/app.tsx
+++ b/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 (
-
-
+
+
-
- Section 2 coming soon...
+
+
+ Our Partners
+
+
+
{/* Spacer for DotPattern */}
+
diff --git a/src/components/navbar/navbar.tsx b/src/components/navbar/navbar.tsx
new file mode 100644
index 0000000..99a2c77
--- /dev/null
+++ b/src/components/navbar/navbar.tsx
@@ -0,0 +1,15 @@
+export function Navbar() {
+ return (
+
+ );
+}
diff --git a/src/components/partners-marquee/partners-marquee.tsx b/src/components/partners-marquee/partners-marquee.tsx
new file mode 100644
index 0000000..9438620
--- /dev/null
+++ b/src/components/partners-marquee/partners-marquee.tsx
@@ -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 (
+
+
+
+
+
+ );
+}
diff --git a/src/components/ui/marquee.tsx b/src/components/ui/marquee.tsx
new file mode 100644
index 0000000..0bd11ec
--- /dev/null
+++ b/src/components/ui/marquee.tsx
@@ -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 (
+
+ {Array(repeat)
+ .fill(0)
+ .map((_, i) => (
+
+ {children}
+
+ ))}
+
+ );
+}
diff --git a/src/globals.d.ts b/src/globals.d.ts
new file mode 100644
index 0000000..e583f13
--- /dev/null
+++ b/src/globals.d.ts
@@ -0,0 +1,3 @@
+declare module "*.css";
+declare module "@fontsource/*" {}
+declare module "@fontsource-variable/*" {}
diff --git a/src/index.css b/src/index.css
index 58878da..83a1246 100644
--- a/src/index.css
+++ b/src/index.css
@@ -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;
}
diff --git a/src/main.tsx b/src/main.tsx
index b160e7a..79328ed 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -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(