-
Notifications
You must be signed in to change notification settings - Fork 0
Rename package category, create hero section with banner.svg, and implement accessible theme toggle #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… theme toggle Co-authored-by: AFeuerpfeil <36232041+AFeuerpfeil@users.noreply.github.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
manybodylabwebsite | 866d78c | Dec 24 2025, 11:11 PM |
Co-authored-by: AFeuerpfeil <36232041+AFeuerpfeil@users.noreply.github.com>
Removed icons from categories in packages.ts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements three key improvements to the ManyBodyLab website: renaming the package category for better clarity, simplifying the banner section, and adding a theme switcher for light/dark mode support.
- Renamed "Generic Julia Packages" to "Utility Libraries" with corresponding emoji icons added to all categories
- Simplified the banner from a rotating carousel to a clean, static banner with gradient background
- Implemented a complete light/dark mode theme system with toggle button, localStorage persistence, and system preference detection
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/data/packages.ts | Updated category name from "Generic Julia Packages" to "Utility Libraries" and added emoji icons (⚛️, 🕸️, 🔧) to all three categories |
| src/app/theme-provider.tsx | Created theme context provider with localStorage persistence, input validation, and system preference fallback |
| src/app/theme-toggle.tsx | Added theme toggle button component with sun/moon icons and hydration safety checks |
| src/app/page.tsx | Simplified rotating banner to static banner, added ThemeToggle to header navigation, and removed banner carousel logic |
| src/app/layout.tsx | Wrapped application in ThemeProvider to enable theme context throughout the app |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const toggleTheme = () => { | ||
| const newTheme = theme === "light" ? "dark" : "light"; | ||
| setTheme(newTheme); | ||
| localStorage.setItem("theme", newTheme); | ||
| document.documentElement.classList.toggle("dark", newTheme === "dark"); | ||
| }; |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toggleTheme function should check if window is defined before accessing localStorage and document, similar to the useEffect. This prevents potential SSR errors if the function is somehow called during server-side rendering.
src/app/theme-toggle.tsx
Outdated
| <button | ||
| onClick={toggleTheme} | ||
| className="p-2 rounded-lg bg-gray-100 dark:bg-gray-800 hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors" | ||
| aria-label="Toggle theme" |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The theme toggle button should have an aria-pressed attribute or similar ARIA attribute to indicate the current theme state to screen readers. Consider adding aria-pressed={theme === "dark"} or updating the aria-label to indicate the current state, such as aria-label={Switch to ${theme === "light" ? "dark" : "light"} mode}.
| aria-label="Toggle theme" | |
| aria-pressed={theme === "dark"} | |
| aria-label={`Switch to ${theme === "light" ? "dark" : "light"} mode`} |
src/app/theme-toggle.tsx
Outdated
| // Prevent hydration mismatch by not rendering until mounted | ||
| if (!mounted) { | ||
| return ( | ||
| <div className="p-2 rounded-lg bg-gray-100 dark:bg-gray-800 w-9 h-9" /> |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder div uses dark mode classes (dark:bg-gray-800) but during SSR/initial render, the dark class won't be applied to the html element yet. This could cause a visual inconsistency during hydration. Consider using a neutral background color that works in both themes, or matching the expected initial theme state.
| <div className="p-2 rounded-lg bg-gray-100 dark:bg-gray-800 w-9 h-9" /> | |
| <div className="p-2 rounded-lg bg-gray-100 w-9 h-9" /> |
src/app/theme-provider.tsx
Outdated
| const [theme, setTheme] = useState<Theme>("light"); | ||
|
|
||
| useEffect(() => { | ||
| // Ensure we're on the client side | ||
| if (typeof window === 'undefined') return; | ||
|
|
||
| // Check localStorage for saved theme with validation | ||
| const savedTheme = localStorage.getItem("theme"); | ||
| if (savedTheme === "light" || savedTheme === "dark") { | ||
| setTheme(savedTheme); | ||
| document.documentElement.classList.toggle("dark", savedTheme === "dark"); | ||
| } else { | ||
| // Fall back to system preference | ||
| const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; | ||
| const initialTheme = isDark ? "dark" : "light"; | ||
| setTheme(initialTheme); | ||
| document.documentElement.classList.toggle("dark", isDark); | ||
| } | ||
| }, []); | ||
|
|
||
| const toggleTheme = () => { | ||
| const newTheme = theme === "light" ? "dark" : "light"; | ||
| setTheme(newTheme); | ||
| localStorage.setItem("theme", newTheme); | ||
| document.documentElement.classList.toggle("dark", newTheme === "dark"); |
Copilot
AI
Dec 24, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The theme state is initialized to "light" (line 15) but then immediately changed in the useEffect based on localStorage or system preference. This could cause a flash of light theme before switching to dark theme. Consider using a lazy initializer or storing the theme in a cookie/header to enable SSR with the correct initial theme, or add a script tag in the HTML head to apply the theme class before React hydration.
| const [theme, setTheme] = useState<Theme>("light"); | |
| useEffect(() => { | |
| // Ensure we're on the client side | |
| if (typeof window === 'undefined') return; | |
| // Check localStorage for saved theme with validation | |
| const savedTheme = localStorage.getItem("theme"); | |
| if (savedTheme === "light" || savedTheme === "dark") { | |
| setTheme(savedTheme); | |
| document.documentElement.classList.toggle("dark", savedTheme === "dark"); | |
| } else { | |
| // Fall back to system preference | |
| const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; | |
| const initialTheme = isDark ? "dark" : "light"; | |
| setTheme(initialTheme); | |
| document.documentElement.classList.toggle("dark", isDark); | |
| } | |
| }, []); | |
| const toggleTheme = () => { | |
| const newTheme = theme === "light" ? "dark" : "light"; | |
| setTheme(newTheme); | |
| localStorage.setItem("theme", newTheme); | |
| document.documentElement.classList.toggle("dark", newTheme === "dark"); | |
| const [theme, setTheme] = useState<Theme>(() => { | |
| if (typeof window === "undefined") { | |
| return "light"; | |
| } | |
| const savedTheme = window.localStorage.getItem("theme"); | |
| if (savedTheme === "light" || savedTheme === "dark") { | |
| return savedTheme; | |
| } | |
| const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; | |
| return isDark ? "dark" : "light"; | |
| }); | |
| useEffect(() => { | |
| if (typeof window === "undefined") return; | |
| document.documentElement.classList.toggle("dark", theme === "dark"); | |
| }, [theme]); | |
| const toggleTheme = () => { | |
| const newTheme = theme === "light" ? "dark" : "light"; | |
| setTheme(newTheme); | |
| if (typeof window !== "undefined") { | |
| window.localStorage.setItem("theme", newTheme); | |
| } |
|
@copilot |
Co-authored-by: AFeuerpfeil <36232041+AFeuerpfeil@users.noreply.github.com>
Done! The website now uses the banner.svg file. The banner displays beautifully with "From First Principles to Scalable Computation" and the wave visualization. Changes committed in e0cdf48. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot |
Co-authored-by: AFeuerpfeil <36232041+AFeuerpfeil@users.noreply.github.com>
Done! The banner is now integrated as a hero section with content overlaid on it. The banner scrolls behind the sticky header as you scroll down the page. Changes committed in c3f7b5f. Banner scrolling behind the sticky header: Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot |
Co-authored-by: AFeuerpfeil <36232041+AFeuerpfeil@users.noreply.github.com>
Fixed! The hero content is now positioned on the left side, leaving the middle and right areas clear for the banner's text. The overlaid content no longer interferes with the banner's "From First Principles to Scalable Computation" text. Changes committed in 866d78c. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|







Addresses three UX improvements: better category naming, hero banner implementation with content overlay, and light/dark mode switching with enhanced accessibility.
Changes
Category rename:
Generic Julia Packages→Utility LibrariesHero banner implementation: Integrated banner.svg as a hero section with content overlay
Theme toggle: Added accessible light/dark mode switcher in header
ThemeProvider: React context with lazy state initialization to prevent theme flashThemeToggle: Button component with sun/moon icons and enhanced accessibilityaria-pressedattribute indicates current theme statearia-labelannounces the toggle action to screen readersScreenshots
Hero Banner - Light Mode (Content positioned left):

Hero Banner - Dark Mode (Content positioned left):

Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.