Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,274 changes: 2,086 additions & 1,188 deletions package-lock.json

Large diffs are not rendered by default.

62 changes: 42 additions & 20 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Route, BrowserRouter as Router, Routes } from 'react-router-dom'
import { ThemeProvider } from '@/components/ThemeProvider'

import Home from '@/pages/Home'
import CareersHub from '@/pages/CareersHub'
Expand All @@ -8,28 +9,49 @@ import PreviousEvents from '@/pages/PreviousEvents'
import PreviousEvent from '@/pages/PreviousEvent'
import NotFound from '@/pages/NotFound'

// Redesign pages
import HomePage from '@/pages/HomePage'
import AboutPage from '@/pages/AboutPage'
import ProgramsPage from '@/pages/ProgramsPage'
import CommunityPage from '@/pages/CommunityPage'
import EventsPage from '@/pages/EventsPage'
import GetInvolvedPage from '@/pages/GetInvolvedPage'
import ResourcesPage from '@/pages/ResourcesPage'

function App() {
return (
<Router>
<div role="document">
{/* Skip Link - First element for accessibility */}
<a
className="absolute left-[6px] top-[-60px] z-[100] bg-white px-2 py-1 text-black focus:top-[6px]"
href="#main-content"
>
Skip to main content
</a>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/careers-hub" element={<CareersHub />} />
<Route path="/connections" element={<ConnectionsPage />} />
<Route path="/media" element={<MediaPage />} />
<Route path="/previous-events" element={<PreviousEvents />} />
<Route path="/previous-events/:year" element={<PreviousEvent />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
<ThemeProvider>
<Router>
<div role="document">
{/* Skip Link - First element for accessibility */}
<a
className="absolute left-[6px] top-[-60px] z-[100] bg-white px-2 py-1 text-black focus:top-[6px]"
href="#main-content"
>
Skip to main content
</a>
<Routes>
{/* New redesign routes */}
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/programs" element={<ProgramsPage />} />
<Route path="/community" element={<CommunityPage />} />
<Route path="/events" element={<EventsPage />} />
<Route path="/get-involved" element={<GetInvolvedPage />} />
<Route path="/resources" element={<ResourcesPage />} />

{/* Legacy routes (existing pages still accessible) */}
<Route path="/legacy" element={<Home />} />
<Route path="/careers-hub" element={<CareersHub />} />
<Route path="/connections" element={<ConnectionsPage />} />
<Route path="/media" element={<MediaPage />} />
<Route path="/previous-events" element={<PreviousEvents />} />
<Route path="/previous-events/:year" element={<PreviousEvent />} />
<Route path="*" element={<NotFound />} />
</Routes>
</div>
</Router>
</ThemeProvider>
)
}

Expand Down
Binary file added src/assets/fonts/Inter-VariableFont.woff2
Binary file not shown.
110 changes: 110 additions & 0 deletions src/components/SiteFooter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { Link } from 'react-router-dom'
import { ReactComponent as CompassLogo } from '@/assets/images/compass-logo.svg'

const footerPrograms = [
{ label: 'Innovation Summits', to: '/programs' },
{ label: 'Hack Michigan', to: '/programs' },
{ label: 'Michigan DevFest', to: '/programs' },
{ label: 'Career Pathways', to: '/programs' },
]

const footerCommunity = [
{ label: 'For Navigators', to: '/community' },
{ label: 'For Employers', to: '/community' },
{ label: 'For Partners', to: '/community' },
{ label: 'Our Collective', to: '/about' },
]

export default function SiteFooter() {
return (
<footer
role="contentinfo"
className="border-t border-[var(--border)] bg-[var(--surface-footer)]"
>
<div className="mx-auto max-w-[1200px] px-6 py-16">
{/* Logo */}
<div className="mb-12">
<CompassLogo
className="h-28 w-auto"
aria-label="Compass Detroit logo"
/>
</div>
<div className="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-4 lg:gap-12">
{/* Brand */}
<div className="sm:col-span-2 lg:col-span-1">
<p className="max-w-[280px] text-[13px] leading-relaxed text-gray-600">
Collective of Minority Professionals and STEAM Societies. A
501(c)(3) nonprofit building career infrastructure for
underrepresented tech talent in Michigan.
</p>
</div>

{/* Programs */}
<div>
<h3 className="mb-4 text-xs font-bold uppercase tracking-wider text-gray-500">
Programs
</h3>
<div className="flex flex-col gap-2.5">
{footerPrograms.map((link) => (
<Link
key={link.label}
to={link.to}
className="text-[13px] text-gray-600 transition-colors hover:text-gray-400"
>
{link.label}
</Link>
))}
</div>
</div>

{/* Community */}
<div>
<h3 className="mb-4 text-xs font-bold uppercase tracking-wider text-gray-500">
Community
</h3>
<div className="flex flex-col gap-2.5">
{footerCommunity.map((link) => (
<Link
key={link.label}
to={link.to}
className="text-[13px] text-gray-600 transition-colors hover:text-gray-400"
>
{link.label}
</Link>
))}
</div>
</div>

{/* Contact */}
<div>
<h3 className="mb-4 text-xs font-bold uppercase tracking-wider text-gray-500">
Contact
</h3>
<div className="flex flex-col gap-2.5">
<a
href="mailto:jritten@compass-detroit.com"
className="text-[13px] text-gray-600 transition-colors hover:text-gray-400"
>
jritten@compass-detroit.com
</a>
<span className="text-[13px] text-gray-600">810-441-3259</span>
<span className="text-[13px] text-gray-600">
Detroit, Michigan
</span>
</div>
</div>
</div>

{/* Bottom bar */}
<div className="mt-10 flex flex-col items-center justify-between gap-2 border-t border-surface pt-6 sm:flex-row">
<span className="text-xs text-gray-700">
© {new Date().getFullYear()} COMPASS. All rights reserved.
</span>
<span className="text-xs text-gray-700">
501(c)(3) Nonprofit Organization
</span>
</div>
</div>
</footer>
)
}
97 changes: 97 additions & 0 deletions src/components/SiteNavbar.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { useState } from 'react'
import { Link, useLocation } from 'react-router-dom'
import { FaBars, FaXmark } from 'react-icons/fa6'
import { ReactComponent as CompassLogo } from '@/assets/images/compass-logo.svg'
import ThemeSwitcher from '@/components/ui/ThemeSwitcher'
import FontSwitcher from '@/components/ui/FontSwitcher'

const navLinks = [
{ to: '/about', label: 'About' },
{ to: '/programs', label: 'Programs' },
{ to: '/community', label: 'Community' },
{ to: '/events', label: 'Events' },
{ to: '/resources', label: 'Resources' },
{ to: '/get-involved', label: 'Get Involved' },
]

export default function SiteNavbar() {
const [mobileOpen, setMobileOpen] = useState(false)
const location = useLocation()

return (
<nav
className="bg-[var(--surface)]/95 sticky top-0 z-50 border-b border-[var(--border)] backdrop-blur-md"
role="navigation"
aria-label="Main navigation"
>
<div className="mx-auto flex max-w-[1200px] items-center justify-between px-6 py-5">
{/* Logo */}
<Link
to="/"
className="flex items-center gap-2"
aria-label="COMPASS home"
>
<CompassLogo
className="h-28 w-auto"
aria-label="Compass Detroit logo"
/>
</Link>

{/* Desktop links */}
<div className="hidden items-center gap-8 md:flex">
{navLinks.map((link) => (
<Link
key={link.to}
to={link.to}
className={`text-sm transition-colors duration-200 ${
location.pathname === link.to
? 'text-[var(--text-primary)]'
: 'text-[var(--text-muted)] hover:text-[var(--text-primary)]'
}`}
>
{link.label}
</Link>
))}
<FontSwitcher />
<ThemeSwitcher />
</div>

{/* Mobile toggle */}
<div className="flex items-center gap-3 md:hidden">
<FontSwitcher />
<ThemeSwitcher />
<button
className="text-[var(--text-primary)]"
onClick={() => setMobileOpen(!mobileOpen)}
aria-expanded={mobileOpen}
aria-label={mobileOpen ? 'Close menu' : 'Open menu'}
>
{mobileOpen ? <FaXmark size={22} /> : <FaBars size={22} />}
</button>
</div>
</div>

{/* Mobile menu */}
{mobileOpen && (
<div className="border-t border-[var(--border)] bg-[var(--surface)] px-6 pb-6 md:hidden">
<div className="flex flex-col gap-1 pt-2">
{navLinks.map((link) => (
<Link
key={link.to}
to={link.to}
onClick={() => setMobileOpen(false)}
className={`rounded-lg px-4 py-3 text-sm transition-colors ${
location.pathname === link.to
? 'bg-primary/10 text-primary'
: 'text-[var(--text-muted)] hover:bg-[var(--card-hover-bg)] hover:text-[var(--text-primary)]'
}`}
>
{link.label}
</Link>
))}
</div>
</div>
)}
</nav>
)
}
93 changes: 93 additions & 0 deletions src/components/ThemeProvider.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { createContext, useContext, useEffect, useState } from 'react'
import PropTypes from 'prop-types'

const ThemeContext = createContext()

const THEME_KEY = 'compass-theme'
const FONT_KEY = 'compass-font'

export const FONT_OPTIONS = [
{
id: 'montserrat',
label: 'Montserrat',
family: "Montserrat, 'Open Sans', Helvetica, Arial, sans-serif",
heading: 'BioRhyme, serif',
},
{
id: 'inter',
label: 'Inter',
family: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif',
heading: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif',
},
{
id: 'biorhyme',
label: 'BioRhyme',
family: 'BioRhyme, Georgia, serif',
heading: 'BioRhyme, Georgia, serif',
},
{
id: 'orbitron',
label: 'Orbitron',
family: 'Orbitron, monospace',
heading: 'Orbitron, monospace',
},
{
id: 'asimovian',
label: 'Asimovian',
family: "Asimovian, Georgia, 'Times New Roman', serif",
heading: "Asimovian, Georgia, 'Times New Roman', serif",
},
]

export function ThemeProvider({ children }) {
const [mode, setMode] = useState(() => {
const saved = localStorage.getItem(THEME_KEY)
if (saved === 'light' || saved === 'dark') return saved
return window.matchMedia('(prefers-color-scheme: light)').matches
? 'light'
: 'dark'
})

const [font, setFont] = useState(() => {
const saved = localStorage.getItem(FONT_KEY)
if (FONT_OPTIONS.some((f) => f.id === saved)) return saved
return 'montserrat'
})

useEffect(() => {
const root = document.documentElement
root.classList.remove('light', 'dark')
root.classList.add(mode)
localStorage.setItem(THEME_KEY, mode)
}, [mode])

useEffect(() => {
const selected = FONT_OPTIONS.find((f) => f.id === font)
if (selected) {
document.documentElement.style.setProperty('--site-font', selected.family)
document.documentElement.style.setProperty(
'--heading-font',
selected.heading
)
}
localStorage.setItem(FONT_KEY, font)
}, [font])

const toggle = () => setMode((m) => (m === 'dark' ? 'light' : 'dark'))

return (
<ThemeContext.Provider value={{ mode, setMode, toggle, font, setFont }}>
{children}
</ThemeContext.Provider>
)
}

ThemeProvider.propTypes = {
children: PropTypes.node.isRequired,
}

export function useTheme() {
const ctx = useContext(ThemeContext)
if (!ctx) throw new Error('useTheme must be used within ThemeProvider')
return ctx
}
2 changes: 1 addition & 1 deletion src/components/Yoda404.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const Yoda404 = () => {
<div className="flex min-h-screen flex-col items-center justify-center gap-8 bg-gradient-to-br from-emerald-50 to-primary-100 p-8 text-center">
{/* 404 Error Display */}
<div className="mb-4">
<h1 className="font-biorhyme text-8xl font-bold text-emerald-800">
<h1 className="font-heading text-8xl font-bold text-emerald-800">
404
</h1>
<h2 className="mt-2 text-2xl text-gray-800">Page Not Found</h2>
Expand Down
2 changes: 1 addition & 1 deletion src/components/careers/ForHire.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function ForHire() {
id="for-hire"
className="flex flex-col justify-center bg-yellow-50 p-8 py-24 sm:px-10 md:px-14 lg:px-16"
>
<h2 className="w-full text-center font-biorhyme text-4xl text-black md:text-5xl lg:text-6xl">
<h2 className="w-full text-center font-heading text-4xl text-black md:text-5xl lg:text-6xl">
For Hire
</h2>

Expand Down
Loading