refactor(web): modularize main.js into focused ES6 modules (#874)#946
Conversation
|
@nishtha-agarwal-211 is attempting to deploy a commit to the Anuj's projects Team on Vercel. A member of the Team first needs to authorize it. |
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
This PR refactors the web app’s front-end bootstrapping by converting the monolithic main.js into ES modules and normalizing the HTML structure/formatting across category pages.
Changes:
- Converted
js/main.jsinto an ES module and split functionality intojs/modules/*(theme, sidebar, search, modal, utils). - Updated multiple HTML pages to use
type="module"formain.jsand applied consistent HTML formatting/structure. - Added shared utilities for filtering project cards and handling reduced-motion behavior.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web-app/js/main.js | Replaced large inline script with a module-based orchestrator that composes new feature modules. |
| web-app/js/modules/utils.js | Introduces shared helpers (debounce, reduced motion detection, unified card filtering). |
| web-app/js/modules/theme.js | Centralizes theme persistence, toggle UI updates, and theme-color meta syncing. |
| web-app/js/modules/sidebar.js | Moves sidebar + category navigation + stats logic into a dedicated module. |
| web-app/js/modules/search.js | Adds modular search dropdown, suggestions, history, and keyboard navigation. |
| web-app/js/modules/modal.js | Modularizes modal open/close, focus trap, inert handling, and info modal wiring. |
| web-app/index.html | Loads main.js as an ES module. |
| web-app/games.html | HTML formatting cleanup + loads main.js as an ES module. |
| web-app/math.html | HTML formatting cleanup + loads main.js as an ES module. |
| web-app/utilities.html | HTML formatting cleanup + loads main.js as an ES module. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| document.addEventListener("click", (e) => { | ||
| if ( | ||
| mainSidebar.classList.contains("open") && | ||
| !mainSidebar.contains(e.target) && | ||
| e.target !== mobileSidebarToggle | ||
| ) { | ||
| mainSidebar.classList.remove("open"); | ||
| mobileSidebarToggle.setAttribute("aria-expanded", "false"); | ||
| const icon = mobileSidebarToggle.querySelector("i"); | ||
| if (icon) icon.className = "fas fa-bars"; | ||
| } | ||
| }); |
| sidebar.js - Sidebar layout, category tabs, and mobile drawers. | ||
| */ | ||
|
|
||
| import { debounce } from "./utils.js"; |
| if (!overlay || !titleEl || !listEl) return; | ||
|
|
||
| titleEl.textContent = title; | ||
| listEl.innerHTML = steps.map((step) => "<li>" + step + "</li>").join(""); |
| function triggerSearch(query) { | ||
| if (query) { | ||
| recentSearches = recentSearches.filter((s) => s !== query); | ||
| recentSearches.unshift(query); | ||
| recentSearches = recentSearches.slice(0, 10); | ||
| localStorage.setItem("recentSearches", JSON.stringify(recentSearches)); | ||
| } | ||
| onSearchChange(query); | ||
| } | ||
|
|
||
| const debouncedSearch = debounce((query) => { | ||
| renderSuggestions(query); | ||
| }, 200); | ||
|
|
||
| searchInput.addEventListener("input", (e) => { | ||
| const query = e.target.value.trim(); | ||
| if (searchLoader) searchLoader.style.display = query ? "block" : "none"; | ||
| debouncedSearch(query); | ||
| triggerSearch(query); | ||
| }); |
| window.addEventListener( | ||
| "scroll", | ||
| () => { | ||
| const navH = navbar ? navbar.getBoundingClientRect().height : 72; | ||
| stickyFilterBar.style.top = `${navH + 16}px`; | ||
| }, | ||
| { passive: true } | ||
| ); |
|
🎉 Thank you for your contribution! Your Pull Request has been merged successfully. We appreciate the time and effort you put into improving this project. Contributions like yours help the repository grow and stay useful for everyone. If you'd like to contribute again, please check the open issues and make sure you are assigned before opening another Pull Request. Thanks again for your support! 🙌 |
Fixes #874
Description
This PR resolves issue #874 by refactoring the monolithic and highly complex
web-app/js/main.jsfile (~2,100 lines) into modern, focused, and maintainable ES6 Modules.Previously,
main.jssuffered from overlapping responsibilities, duplicate/unnecessary event listeners, and duplicate helper definitions (like duplicateprefersReducedMotionordebouncedeclarations).By extracting these concerns into modular single-responsibility components and upgrading our pages to load modules natively, we have drastically improved code readability, maintainability, and load times.
Architecture & Modules Introduced
A new
web-app/js/modules/directory was created to host the following decoupled components:utils.js:prefersReducedMotion,debounce,safeRun,escapeHtml).updateProjectVisibility(currentCategory, currentSearchQuery)which solves search query and category filtering combinations in a single pass.theme.js:search.js:Ctrl+Kkeybindings.modal.js:trapFocus).openProjectSafeandcloseProjectSafeglobally to thewindowobject to ensure backward compatibility for other scripts or inline HTML references.sidebar.js:Entry Point and HTML Upgrades
main.js: Rewritten as a clean and beautiful orchestrator that imports and initializes each of these modules. It handlesTimeline Serpentine SVG winding path calculations, back-to-top buttons, and sharing toast alerts.<script>tags totype="module"in all page files to natively support ES6 imports:index.htmlgames.htmlmath.htmlutilities.html