From 7597bbdf0ac562001c249cc838b164401925b36f Mon Sep 17 00:00:00 2001 From: Arnav Joshi <74690929+arnav-joshi@users.noreply.github.com> Date: Thu, 12 Mar 2026 14:26:59 -0500 Subject: [PATCH 1/7] nuke it and start over --- public/index.html | 2 + src/components/EclairDrawer.tsx | 207 -------------- src/components/Footer.css | 87 ++++++ src/components/Footer.tsx | 113 ++------ src/components/Nav.css | 213 ++++++++++++++ src/components/Nav.tsx | 78 +++++ src/components/NavbarElement.tsx | 49 ---- src/components/ResponsiveAppBar.tsx | 120 -------- src/components/YoutubeEmbed.tsx | 15 - src/data/officers.ts | 117 ++++++++ src/data/projects.ts | 225 +++++++++++++++ src/hooks/useCursor.ts | 63 +++++ src/hooks/useReveal.ts | 28 ++ src/index.tsx | 2 +- src/pages/About.css | 277 ++++++++++++++++++ src/pages/About.tsx | 283 ++++++++----------- src/pages/App.tsx | 126 ++++----- src/pages/Contact.css | 165 +++++++++++ src/pages/Contact.tsx | 200 +++++++++---- src/pages/Homepage.css | 246 ++++++++++++++++ src/pages/Homepage.tsx | 307 +++++++------------- src/pages/Projects.css | 183 ++++++++++++ src/pages/Projects.tsx | 305 +++++--------------- src/pages/Sponsors.css | 155 ++++++++++ src/pages/Sponsors.tsx | 234 +++++++-------- src/static/images/logo/E.png | Bin 0 -> 12066 bytes src/styles/about/about.css | 327 --------------------- src/styles/about/officerCard.css | 159 ----------- src/styles/app.css | 391 -------------------------- src/styles/contact.css | 30 -- src/styles/eclairbutton.css | 54 ---- src/styles/eclairdrawer.css | 31 -- src/styles/footer.css | 13 - src/styles/globals.css | 238 ++++++++++++++++ src/styles/index.css | 13 - src/styles/input.css | 3 - src/styles/loader.css | 0 src/styles/mailer.css | 53 ---- src/styles/navbar.css | 3 - src/styles/navbarelement.css | 53 ---- src/styles/projects/popup.css | 160 ----------- src/styles/projects/projectcard.css | 176 ------------ src/styles/projects/projects.css | 209 -------------- src/styles/projects/resourcescard.css | 171 ----------- src/styles/sponsors/sponsors.css | 214 -------------- src/styles/youtubeEmbed.css | 20 -- 46 files changed, 2689 insertions(+), 3429 deletions(-) delete mode 100644 src/components/EclairDrawer.tsx create mode 100644 src/components/Footer.css create mode 100644 src/components/Nav.css create mode 100644 src/components/Nav.tsx delete mode 100644 src/components/NavbarElement.tsx delete mode 100644 src/components/ResponsiveAppBar.tsx delete mode 100644 src/components/YoutubeEmbed.tsx create mode 100644 src/data/officers.ts create mode 100644 src/data/projects.ts create mode 100644 src/hooks/useCursor.ts create mode 100644 src/hooks/useReveal.ts create mode 100644 src/pages/About.css create mode 100644 src/pages/Contact.css create mode 100644 src/pages/Homepage.css create mode 100644 src/pages/Projects.css create mode 100644 src/pages/Sponsors.css create mode 100644 src/static/images/logo/E.png delete mode 100644 src/styles/about/about.css delete mode 100644 src/styles/about/officerCard.css delete mode 100644 src/styles/app.css delete mode 100644 src/styles/contact.css delete mode 100644 src/styles/eclairbutton.css delete mode 100644 src/styles/eclairdrawer.css delete mode 100644 src/styles/footer.css create mode 100644 src/styles/globals.css delete mode 100644 src/styles/index.css delete mode 100644 src/styles/input.css delete mode 100644 src/styles/loader.css delete mode 100644 src/styles/mailer.css delete mode 100644 src/styles/navbar.css delete mode 100644 src/styles/navbarelement.css delete mode 100644 src/styles/projects/popup.css delete mode 100644 src/styles/projects/projectcard.css delete mode 100644 src/styles/projects/projects.css delete mode 100644 src/styles/projects/resourcescard.css delete mode 100644 src/styles/sponsors/sponsors.css delete mode 100644 src/styles/youtubeEmbed.css diff --git a/public/index.html b/public/index.html index 5008dff..4abc182 100644 --- a/public/index.html +++ b/public/index.html @@ -24,6 +24,8 @@ work correctly both with client-side routing and a non-root public URL. Learn how to configure a non-root public URL by running `npm run build`. --> + + ECLAIR diff --git a/src/components/EclairDrawer.tsx b/src/components/EclairDrawer.tsx deleted file mode 100644 index 244ca5a..0000000 --- a/src/components/EclairDrawer.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import React from 'react' -import { useState, useEffect, useRef } from 'react'; -import { Drawer, Typography } from '@mui/material' -import { Link, useLocation } from 'react-router-dom'; -import MenuIcon from '@mui/icons-material/Menu'; -import CloseIcon from '@mui/icons-material/Close'; -import { createTheme } from '@mui/material/styles'; -import '../styles/eclairdrawer.css'; -import { ThemeProvider } from 'styled-components'; -function EclairDrawer() { - - const location = useLocation(); - const drawerRef = useRef(null); - - const handleOutSideClick = (event: MouseEvent) => { - if (drawerRef.current && !drawerRef.current.contains(event.target as Node)) { - setDrawerOpen(false); - } - } - - const [currentPath, setCurrentPath] = useState<{ [key: string]: boolean }>({ - '/': false, - '/about': false, - '/sponsors': false, - '/projects': false, - '/contact': false, - - }); - - const themeDrawer = createTheme({ - palette: { - primary: { - // light: will be calculated from palette.primary.main, - main: '#ffffff', - }, - secondary: { - light: '#0066ff', - main: '#0044ff', - // dark: will be calculated from palette.secondary.main, - contrastText: '#ffcc00', - }, - } - }) - - useEffect(() => { - - document.addEventListener('mousedown', handleOutSideClick); - return () => { - document.removeEventListener('mousedown', handleOutSideClick); - }; - - - - - }, []); - const currentUrl = location.pathname; - useEffect(() => { - - console.log(currentUrl); - - setCurrentPath( - (prevCurrentPath: { [key: string]: boolean }) => { - const updatedPath: { [key: string]: boolean } = Object.keys(prevCurrentPath).reduce((acc: { [key: string]: boolean }, key: string) => { - if (key === currentUrl) { - acc[key] = true; - } else { - acc[key] = false; - } - return acc; - }, {}) - - return updatedPath; - } - ); - - }, [currentUrl]); - - useEffect(() => { - console.log(currentPath); - }, [currentPath]); - - const [drawerOpen, setDrawerOpen] = useState(false); - const toggleDrawer = () => { - setDrawerOpen(!drawerOpen); - return drawerOpen; - } - - const titleStyle = { - background: 'linear-gradient(to right, #20c997, #ff77ff)', - backgroundClip: 'text', - WebkitBackgroundClip: 'text', - color: 'transparent', - alignItems: 'center', - display: 'flex', - justifyContent: 'center', - - } - - return ( - -
-
- {!drawerOpen && ()} -
- - -
- -
-
-
- -
-
- - ECLAIR - -
- -
- - Home - -
-
- {currentPath['/'] && ()} - -
- - About - -
-
- {currentPath['/about'] && ()} - -
- - Sponsors - -
-
- {currentPath['/sponsors'] && ()} - -
- - What We Do - -
-
- {currentPath['/projects'] && ()} - -
- - Contact Us - -
-
- {currentPath['/contact'] && ()} -
- - - -
-
-
- ) -} - -export default EclairDrawer diff --git a/src/components/Footer.css b/src/components/Footer.css new file mode 100644 index 0000000..054fb6c --- /dev/null +++ b/src/components/Footer.css @@ -0,0 +1,87 @@ +.footer { + position: relative; + z-index: 2; + border-top: 1px solid var(--border); + padding: 28px 48px; + display: flex; + align-items: center; + justify-content: space-between; + flex-wrap: wrap; + gap: 16px; + background: var(--black); +} + +.footer-left { + display: flex; + flex-direction: column; + gap: 4px; +} + +.footer-brand { + font-family: var(--display); + font-weight: 800; + font-size: 14px; + letter-spacing: 0.15em; + background: var(--grad); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.footer-copy { + font-family: var(--mono); + font-size: 10px; + color: var(--lo); + letter-spacing: 0.08em; +} + +.footer-links { + display: flex; + gap: 28px; + list-style: none; +} + +.footer-links a { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--lo); + transition: color 0.2s; +} + +.footer-links a:hover { + color: var(--muted); +} + +.footer-social { + display: flex; + gap: 20px; +} + +.footer-social a { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--lo); + transition: color 0.2s; +} + +.footer-social a:hover { + color: var(--magenta); +} + +@media (max-width: 700px) { + .footer { + padding: 24px 20px; + flex-direction: column; + align-items: flex-start; + gap: 20px; + } + + .footer-links { + flex-wrap: wrap; + gap: 16px; + } +} diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 73302e1..9b0fac5 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,93 +1,26 @@ -import * as React from 'react'; -import BottomNavigation from '@mui/material/BottomNavigation'; -import { Grid } from '@mui/material'; -import { createTheme } from '@mui/material/styles'; -import { ThemeProvider } from '@emotion/react'; -import DiscordLogo from '../static/images/footer-icons/Discord-Logo-White.png'; -import GithubLogo from '../static/images/footer-icons/GitHub-Mark-Light-32px.png'; -import InstaIcon from '../static/images/footer-icons/insta_icon.png'; -import EmailIcon from '../static/images/footer-icons/emailIcon2.png' -import '../styles/footer.css' -// import EmailIcon from '@mui/icons-material/Email'; +import React from 'react'; +import './Footer.css'; -export default function SimpleBottomNavigation() { +export default function Footer() { + return ( + + ); +} diff --git a/src/components/Nav.css b/src/components/Nav.css new file mode 100644 index 0000000..8e8aa5f --- /dev/null +++ b/src/components/Nav.css @@ -0,0 +1,213 @@ +.nav { + position: fixed; + top: 0; left: 0; right: 0; + z-index: 100; + height: var(--nav-height); + padding: 0 48px; + display: flex; + align-items: center; + justify-content: space-between; + border-bottom: 1px solid var(--border); + background: rgba(5, 5, 8, 0.7); + backdrop-filter: blur(24px) saturate(1.3); + transition: background 0.3s; +} + +.nav--scrolled { + background: rgba(5, 5, 8, 0.92); +} + +/* Logo */ +.nav-logo { + display: flex; + align-items: center; + gap: 12px; +} + +.nav-logo-img { + height: 64px; + width: auto; +} + +.nav-logo-text { + font-family: var(--display); + font-weight: 800; + font-size: 17px; + letter-spacing: 0.15em; + color: var(--text); +} + +/* Desktop links */ +.nav-links { + display: flex; + gap: 36px; + list-style: none; +} + +.nav-link { + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--muted); + transition: color 0.2s; + position: relative; +} + +.nav-link::after { + content: ''; + position: absolute; + bottom: -4px; + left: 0; + right: 0; + height: 1px; + background: var(--grad); + transform: scaleX(0); + transform-origin: left; + transition: transform 0.3s; +} + +.nav-link:hover, +.nav-link--active { + color: var(--text); +} + +.nav-link:hover::after, +.nav-link--active::after { + transform: scaleX(1); +} + +/* CTA */ +.nav-cta { + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--text); + padding: 10px 22px; + border: 1px solid rgba(217, 70, 239, 0.45); + background: rgba(217, 70, 239, 0.07); + transition: border-color 0.3s, box-shadow 0.3s, background 0.3s; +} + +.nav-cta:hover { + border-color: var(--magenta); + box-shadow: 0 0 24px rgba(217, 70, 239, 0.2); + background: rgba(217, 70, 239, 0.14); +} + +/* Hamburger */ +.nav-hamburger { + display: none; + flex-direction: column; + gap: 5px; + padding: 4px; + background: none; + border: none; +} + +.nav-hamburger span { + display: block; + width: 22px; + height: 1.5px; + background: var(--text); + transition: transform 0.3s, opacity 0.3s; +} + +.nav-hamburger--open span:nth-child(1) { + transform: translateY(6.5px) rotate(45deg); +} +.nav-hamburger--open span:nth-child(2) { + opacity: 0; +} +.nav-hamburger--open span:nth-child(3) { + transform: translateY(-6.5px) rotate(-45deg); +} + +/* Mobile drawer */ +.nav-drawer { + position: fixed; + top: var(--nav-height); + left: 0; + right: 0; + bottom: 0; + z-index: 99; + background: rgba(5, 5, 8, 0.97); + backdrop-filter: blur(24px); + display: flex; + align-items: center; + justify-content: center; + transform: translateY(-100%); + opacity: 0; + pointer-events: none; + transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.4s; + border-top: 1px solid var(--border); +} + +.nav-drawer--open { + transform: translateY(0); + opacity: 1; + pointer-events: all; +} + +.nav-drawer-overlay { + position: fixed; + inset: 0; + z-index: 98; +} + +.nav-drawer-links { + list-style: none; + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; + width: 100%; + padding: 40px 24px; +} + +.nav-drawer-link { + display: block; + font-family: var(--display); + font-weight: 700; + font-size: clamp(28px, 6vw, 48px); + color: var(--muted); + letter-spacing: -0.01em; + padding: 8px 0; + transition: color 0.2s; + width: 100%; + text-align: center; +} + +.nav-drawer-link:hover { + color: var(--text); +} + +.nav-drawer-cta { + display: inline-block; + margin-top: 16px; + font-family: var(--mono); + font-size: 12px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--text); + padding: 14px 32px; + border: 1px solid rgba(217, 70, 239, 0.5); + background: rgba(217, 70, 239, 0.1); +} + +/* ─── RESPONSIVE ────────────────────────────────────────────── */ +@media (max-width: 900px) { + .nav { + padding: 0 20px; + } + + .nav-links, + .nav-cta { + display: none; + } + + .nav-hamburger { + display: flex; + } +} diff --git a/src/components/Nav.tsx b/src/components/Nav.tsx new file mode 100644 index 0000000..fe46d7c --- /dev/null +++ b/src/components/Nav.tsx @@ -0,0 +1,78 @@ +import React, { useState, useEffect } from 'react'; +import { Link, useLocation } from 'react-router-dom'; +import Logo from '../static/images/logo/E.png'; +import './Nav.css'; + +const NAV_LINKS = [ + { label: 'About', href: '/about' }, + { label: 'Projects', href: '/projects' }, + { label: 'Team', href: '/about#team' }, + { label: 'Sponsors', href: '/sponsors' }, + { label: 'Contact', href: '/contact' }, +]; + +export default function Nav() { + const location = useLocation(); + const [menuOpen, setMenuOpen] = useState(false); + const [scrolled, setScrolled] = useState(false); + + useEffect(() => { + const onScroll = () => setScrolled(window.scrollY > 20); + window.addEventListener('scroll', onScroll, { passive: true }); + return () => window.removeEventListener('scroll', onScroll); + }, []); + + // Close drawer on route change + useEffect(() => { setMenuOpen(false); }, [location]); + + return ( + <> + + + {/* Mobile drawer */} +
+ +
+ {menuOpen && ( +
setMenuOpen(false)} /> + )} + + ); +} diff --git a/src/components/NavbarElement.tsx b/src/components/NavbarElement.tsx deleted file mode 100644 index 352f773..0000000 --- a/src/components/NavbarElement.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react' -import { useState, useEffect, useRef } from 'react' -import { useLocation } from 'react-router-dom'; -import '../styles/navbarelement.css' -import { Link } from 'react-router-dom'; - -interface Props { - text: string; - highlighted?: boolean; - href: string; - ref?: any; - onclick?: () => void; -} - -function NavbarElement(props: Props) { - const location = useLocation(); - const [currentUrl, setCurrentUrl] = useState(''); - const elementRef = useRef(null); - - useEffect(() => { - - - const elementBounds = elementRef.current?.getBoundingClientRect(); - console.log(elementBounds?.width); - const width = elementBounds?.width; - }, []); - - useEffect(() => { - - setCurrentUrl(location.pathname); - - }, [location.pathname]); - - return ( -
- -
- {props.text} -
- - { props.href===currentUrl &&()} -
- ) -} - -export default NavbarElement diff --git a/src/components/ResponsiveAppBar.tsx b/src/components/ResponsiveAppBar.tsx deleted file mode 100644 index 5aa56c6..0000000 --- a/src/components/ResponsiveAppBar.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import * as React from 'react'; -import { memo, useState, useEffect } from 'react'; -import AppBar from '@mui/material/AppBar'; -import Box from '@mui/material/Box'; -import Toolbar from '@mui/material/Toolbar'; -import Typography from '@mui/material/Typography'; -import Container from '@mui/material/Container'; -import NavbarElement from './NavbarElement'; -import { createTheme } from '@mui/material/styles'; -import { ThemeProvider } from '@emotion/react'; -import { useNavigate } from 'react-router-dom'; -import '../styles/navbar.css'; - - -function ResponsiveAppBar() { - - const navigate = useNavigate(); - - useEffect(() => { - window.scrollTo(0, 0); - }, [navigate]); - - const theme = createTheme({ - palette: { - primary: { - // light: will be calculated from palette.primary.main, - main: '#2d354948', - }, - secondary: { - light: '#0066ff', - main: '#0044ff', - // dark: will be calculated from palette.secondary.main, - contrastText: '#ffcc00', - }, - }, - }); - - const titleStyle = { - background: 'linear-gradient(to right, #20c997, #ff77ff)', - backgroundClip: 'text', - WebkitBackgroundClip: 'text', - color: 'transparent', - alignItems: 'center', - display: 'flex', - justifyContent: 'center', - - } - - return ( - - - - -
-
- - ECLAIR - - -
- -
-
- -
-
- -
-
- - -
- -
- - -
-
-
- - - -
-
-
-
-
- ); -} -export default memo(ResponsiveAppBar); \ No newline at end of file diff --git a/src/components/YoutubeEmbed.tsx b/src/components/YoutubeEmbed.tsx deleted file mode 100644 index dddbe6d..0000000 --- a/src/components/YoutubeEmbed.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react' -import '../styles/youtubeEmbed.css'; -function YoutubeEmbed() { - return ( -
- + return ( +
+
setOpen(!open)} + > +
+ {officer.img + ? {officer.name} + :
{officer.initials}
+ }
-
-
- Where to find us! -
-
- We meet in the Gates-Dell Complex, home of UT CS! -
+
+
{officer.name}
+
{officer.role}
- - - - ) -} +
+
+ {officer.bio &&

"{officer.bio}"

} +
e.stopPropagation()}> + {officer.linkedin && ( + + LinkedIn ↗ + + )} + {officer.email && ( + + Email ↗ + + )} +
+
+
-export default About +
{open ? '✕' : '+'}
+
+
+ ); +} diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 60513f7..670d2b8 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -1,86 +1,76 @@ -import React, { useState, useEffect } from 'react' -import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'; -import About from './About'; +import React, { useEffect } from 'react'; +import { BrowserRouter as Router, Route, Routes, useLocation } from 'react-router-dom'; +import { initializeApp } from 'firebase/app'; + +import Nav from '../components/Nav'; +import Footer from '../components/Footer'; import Homepage from './Homepage'; +import About from './About'; import Projects from './Projects'; -import ResponsiveAppBar from '../components/ResponsiveAppBar'; -import Contact from './Contact'; -import Footer from '../components/Footer'; import Sponsors from './Sponsors'; -import EclairDrawer from '../components/EclairDrawer'; -// Import the functions you need from the SDKs you need -import { initializeApp } from "firebase/app"; +import Contact from './Contact'; + +import { useCursor } from '../hooks/useCursor'; +import '../styles/globals.css'; +// ─── Firebase ────────────────────────────────────────────────────────────── const firebaseConfig = { - apiKey: "AIzaSyApKv2_Muv15F14Vfuo04rwuqxUcTtMy9o", - authDomain: "eclair-website-387316.firebaseapp.com", - projectId: "eclair-website-387316", - storageBucket: "eclair-website-387316.appspot.com", - messagingSenderId: "664767979379", - appId: "1:664767979379:web:7904edda15a1350c3b6f06", - measurementId: "G-XVQ8FB05W1" + apiKey: 'AIzaSyApKv2_Muv15F14Vfuo04rwuqxUcTtMy9o', + authDomain: 'eclair-website-387316.firebaseapp.com', + projectId: 'eclair-website-387316', + storageBucket: 'eclair-website-387316.appspot.com', + messagingSenderId: '664767979379', + appId: '1:664767979379:web:7904edda15a1350c3b6f06', + measurementId: 'G-XVQ8FB05W1', }; +initializeApp(firebaseConfig); - -// Initialize Firebase -const app = initializeApp(firebaseConfig); - -const homepage = () => { - return -} -const about = () => { - return +// ─── Scroll to top on route change ───────────────────────────────────────── +function ScrollToTop() { + const { pathname } = useLocation(); + useEffect(() => { window.scrollTo(0, 0); }, [pathname]); + return null; } -const members = () => { - return -} -const projects = () => { - return -} -const contact = () => { - return -} - - -const App: React.FC = () => { - const [isMobile, setIsMobile] = useState(false); - const [isSmol, setIsSmol] = useState(false); +// ─── App shell ───────────────────────────────────────────────────────────── +function AppShell() { + useCursor(); - useEffect(() => { - const handleResize = () => { - - setIsSmol(window.innerWidth < 1000); - }; - const userAgent = navigator.userAgent.toLowerCase(); + return ( + <> + {/* Atmosphere layers */} +
+
+
+ + {/* Custom cursor */} +
+
+ +