Skip to content

add BLT mega menu drop-in script covering all OWASP-BLT repos#103

Open
BharathC0 wants to merge 6 commits intoOWASP-BLT:mainfrom
BharathC0:feature/mega-menu-script
Open

add BLT mega menu drop-in script covering all OWASP-BLT repos#103
BharathC0 wants to merge 6 commits intoOWASP-BLT:mainfrom
BharathC0:feature/mega-menu-script

Conversation

@BharathC0
Copy link
Copy Markdown
Contributor

@BharathC0 BharathC0 commented Apr 2, 2026

Adds js/blt-mega-menu.js — a self-contained, zero-dependency script that injects the OWASP BLT navigation bar into any site or repo page with a single script tag:

<script src="https://owasp-blt.github.io/BLT-Pages/js/blt-mega-menu.js"></script>

Menu sections:

  • Platform — Report a Bug, Bug Bounties, Leaderboard, Adventures, Education
  • Repositories — BLT, BLT-API, BLT-Pages, BLT-Pool, BLT-MCP, BLT-Action, BLT-Flutter, BLT-Extension
  • Community — Contributors, Organizations, Social Feed, OWASP Slack
  • Rewards — Bacon Points, Start a Hunt, Prizes, Sponsors

Features:

  • Fully self-contained (CSS injected at runtime, no external deps)
  • Dropdown panels with icons for every link
  • OWASP BLT logo + branding
  • Report Bug and Join BLT CTA buttons
  • Mobile-responsive hamburger menu
  • Closes on outside click
  • Guards against double-injection

Summary by CodeRabbit

  • New Features
    • Added a responsive mega menu navigation with desktop dropdowns and a mobile hamburger layout.
    • Included a standalone demo page to preview and validate the menu integration.
    • Menu initializes automatically when added to a page, supports toggling of sections, updates its open/closed state, and closes dropdowns when clicking outside.

Adds js/blt-mega-menu.js — a self-contained, zero-dependency script
that injects the OWASP BLT navigation bar into any site or repo page
with a single script tag:

  <script src="https://owasp-blt.github.io/BLT-Pages/js/blt-mega-menu.js"></script>

Menu sections:
- Platform  — Report a Bug, Bug Bounties, Leaderboard, Adventures, Education
- Repositories — BLT, BLT-API, BLT-Pages, BLT-Pool, BLT-MCP, BLT-Action,
                  BLT-Flutter, BLT-Extension
- Community — Contributors, Organizations, Social Feed, OWASP Slack
- Rewards   — Bacon Points, Start a Hunt, Prizes, Sponsors

Features:
- Fully self-contained (CSS injected at runtime, no external deps)
- Dropdown panels with icons for every link
- OWASP BLT logo + branding
- Report Bug and Join BLT CTA buttons
- Mobile-responsive hamburger menu
- Closes on outside click
- Guards against double-injection
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

Walkthrough

Adds a new standalone demo HTML and a self-contained JavaScript file that injects a responsive "mega menu" and its stylesheet into any page, builds desktop dropdowns and a mobile menu, and manages toggle and document-level close behavior.

Changes

Cohort / File(s) Summary
Mega Menu Implementation
js/blt-mega-menu.js
New IIFE script that injects CSS and a top-of-body navigation bar (id=blt-mega-menu-bar), constructs desktop dropdowns and a mobile layout, adds event handlers for dropdown toggles, document-level click-to-close, and a hamburger mobile toggle.
Demo Page
blt-mega-menu-demo.html
New standalone HTML demo that loads js/blt-mega-menu.js, provides metadata and inline CSS for a centered demo layout, and includes explanatory text indicating the nav is injected by the script.

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant Script as blt-mega-menu.js
    participant Head
    participant Body
    participant User

    Browser->>Script: Load & execute (DOMContentLoaded or immediate)
    Script->>Head: append <style id="blt-mega-menu-styles">
    Script->>Body: insert menu markup at top (id=blt-mega-menu-bar)
    User->>Script: click hamburger / desktop dropdown button
    Script->>Body: toggle mobile `open` class or toggle dropdown visibility
    User->>Body: click outside menu
    Script->>Script: close all dropdowns (document-level handler)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested labels: quality: medium

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding a drop-in mega menu script for OWASP-BLT repositories.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@owasp-blt
Copy link
Copy Markdown

owasp-blt bot commented Apr 2, 2026

📊 Monthly Leaderboard

Hi @BharathC0! Here's how you rank for April 2026:

Rank User Open PRs PRs (merged) PRs (closed) Reviews Comments Total
9 tejeshvenkat @tejeshvenkat 15 0 0 3 0 30
10 BharathC0 @BharathC0 4 1 1 0 7 26
11 yashhzd @yashhzd 7 0 0 3 0 22

Scoring this month (across OWASP-BLT org): Open PRs (+1 each), Merged PRs (+10), Closed (not merged) (−2), Reviews (+5; first two per PR in-month), Comments (+2, excludes CodeRabbit). Run /leaderboard on any issue or PR to see your rank!

@github-actions github-actions bot added the unresolved-conversations: 0 PR has 0 unresolved conversations label Apr 2, 2026
@owasp-blt owasp-blt bot added the needs-peer-review PR needs peer review label Apr 2, 2026
@owasp-blt
Copy link
Copy Markdown

owasp-blt bot commented Apr 2, 2026

👋 Hi @BharathC0!

This pull request needs a peer review before it can be merged. Please request a review from a team member who is not:

  • The PR author
  • coderabbitai
  • copilot

Once a valid peer review is submitted, this check will pass automatically. Thank you!

⚠️ Peer review enforcement is active.

Copy link
Copy Markdown

@Jayant2908 Jayant2908 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a screenshot?

@owasp-blt owasp-blt bot added unresolved-conversations: 0 PR has 0 unresolved conversations and removed unresolved-conversations: 0 PR has 0 unresolved conversations labels Apr 2, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
js/blt-mega-menu.js (1)

111-115: Expose the navigation state to assistive tech.

The injected wrapper is a plain div, and neither the section buttons nor the hamburger report expanded/collapsed state. Switching the wrapper to a nav and syncing aria-expanded / aria-controls as panels open would make the component much easier to use with screen readers.

Also applies to: 130-143, 167-195

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@js/blt-mega-menu.js` around lines 111 - 115, Change the injected wrapper
element from a plain div to a semantic nav and add proper ARIA state on the
toggle buttons and panels: when rendering the menu item string that uses classes
blt-mn-item, blt-mn-btn and blt-mn-drop, output a <nav> container (instead of
<div>), ensure each blt-mn-drop panel has a unique id, add
aria-controls="<panelId>" and aria-expanded="false" to the corresponding
blt-mn-btn, and update aria-expanded to "true" and aria-hidden="false" (and back
on close) when opening/closing the panel; apply the same changes where similar
markup is created (the other blocks producing blt-mn-item/blt-mn-btn/blt-mn-drop
in the diff ranges noted).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@js/blt-mega-menu.js`:
- Around line 17-20: The current top-level guard using MENU_BAR_ID runs only
during file eval and doesn't prevent multiple registrations of the
DOMContentLoaded handler; make init() idempotent by re-checking for the sentinel
inside init() (e.g., if (document.getElementById(MENU_BAR_ID)) return;) or set a
runtime sentinel flag before wiring the listener so repeated evaluations don't
prepend the bar/style or re-add listeners; apply the same pattern to the other
init-like blocks referenced around lines 149-154 and 198-201 to ensure
MENU_BAR_ID, init(), and any DOMContentLoaded handler are only installed once.
- Around line 92-97: The mobile drawer (`#blt-mn-mob`) only toggles via the
hamburger handler (blt-mn-ham) so add a shared close/toggle routine (e.g.,
toggleMobileMenu or closeMobileMenu) that removes the "open" class from
`#blt-mn-mob`; call it from the existing hamburger click handler, from a document
click handler that detects clicks outside `#blt-mn-mob` and blt-mn-ham to close
the drawer, and from a window resize handler that closes the drawer when
viewport width > 768; ensure all listeners reference the same function and that
the class removal uses the exact selector "#blt-mn-mob" and the class "open".

---

Nitpick comments:
In `@js/blt-mega-menu.js`:
- Around line 111-115: Change the injected wrapper element from a plain div to a
semantic nav and add proper ARIA state on the toggle buttons and panels: when
rendering the menu item string that uses classes blt-mn-item, blt-mn-btn and
blt-mn-drop, output a <nav> container (instead of <div>), ensure each
blt-mn-drop panel has a unique id, add aria-controls="<panelId>" and
aria-expanded="false" to the corresponding blt-mn-btn, and update aria-expanded
to "true" and aria-hidden="false" (and back on close) when opening/closing the
panel; apply the same changes where similar markup is created (the other blocks
producing blt-mn-item/blt-mn-btn/blt-mn-drop in the diff ranges noted).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 70075449-5f5a-41ca-9886-ab2509cefc0d

📥 Commits

Reviewing files that changed from the base of the PR and between e833ea0 and 105396e.

📒 Files selected for processing (2)
  • blt-mega-menu-demo.html
  • js/blt-mega-menu.js

@owasp-blt owasp-blt bot added unresolved-conversations: 2 PR has 2 unresolved conversations and removed unresolved-conversations: 0 PR has 0 unresolved conversations labels Apr 2, 2026
@owasp-blt owasp-blt bot added unresolved-conversations: 0 PR has 0 unresolved conversations and removed unresolved-conversations: 2 PR has 2 unresolved conversations labels Apr 2, 2026
@BharathC0
Copy link
Copy Markdown
Contributor Author

@Jayant2908
111
555

@BharathC0 BharathC0 requested a review from Jayant2908 April 2, 2026 11:29
@Jayant2908
Copy link
Copy Markdown

Why is the script shown in the photo!? I dont think it should. The issue means that script tag could be inserted in the code and that will take care of this mega menu.

@BharathC0
Copy link
Copy Markdown
Contributor Author

@Jayant2908
The script tag shown in the screenshot was demo-page content explaining usage — it's not part of the menu itself. I've removed it from the demo page. The script tag goes only in the HTML or , and once injected it renders the nav bar silently with no visible code on the page.

99

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (2)
js/blt-mega-menu.js (2)

175-188: ⚠️ Potential issue | 🟠 Major

Give the mobile drawer the same close path as the desktop menus.

Line 175 only resets the desktop dropdowns, and Lines 184-187 are the only place that ever remove open from #blt-mn-mob. If the viewport widens past 768px while the drawer is open, the stacked menu stays visible after the hamburger disappears.

🐛 Proposed fix
-    document.addEventListener("click", function () {
-      items.forEach(function (i) {
-        i.querySelector(".blt-mn-btn").classList.remove("open");
-        i.querySelector(".blt-mn-drop").classList.remove("open");
-      });
-    });
-
     var ham = bar.querySelector("#blt-mn-ham");
     var mob = bar.querySelector("#blt-mn-mob");
+
+    function closeMenus() {
+      items.forEach(function (i) {
+        i.querySelector(".blt-mn-btn").classList.remove("open");
+        i.querySelector(".blt-mn-drop").classList.remove("open");
+      });
+      mob.classList.remove("open");
+      ham.innerHTML = "&#9776;";
+    }
+
+    document.addEventListener("click", closeMenus);
+
     ham.addEventListener("click", function (e) {
       e.stopPropagation();
       var isOpen = mob.classList.toggle("open");
       ham.innerHTML = isOpen ? "&#10005;" : "&#9776;";
     });
+
+    window.addEventListener("resize", function () {
+      if (window.innerWidth > 768) closeMenus();
+    });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@js/blt-mega-menu.js` around lines 175 - 188, The document click handler
currently only closes desktop dropdowns; update it to also close the mobile
drawer by removing the "open" class from the element referenced by mob
(querySelector("#blt-mn-mob")) and reset the hamburger (ham) state/innerHTML to
the closed icon; specifically, inside the global click listener that iterates
items and touches ".blt-mn-btn"/".blt-mn-drop", also call
mob.classList.remove("open") and set ham.innerHTML = "&#9776;" so the mobile
drawer closes the same way as the desktop menus.

20-20: ⚠️ Potential issue | 🟠 Major

Make init() idempotent.

The guard on Line 20 only runs while the file is evaluating. If the drop-in tag is included twice before DOMContentLoaded, both copies still queue init(), and each call appends another style node and menu bar.

🐛 Proposed fix
   var BLT_BASE       = "https://blt.owasp.org";
   var BLT_LOGO       = "https://github.com/OWASP-BLT/BLT/raw/main/website/static/img/logos/logo.png";
   var MENU_BAR_ID    = "blt-mega-menu-bar";
+  var MENU_STYLE_ID  = "blt-mega-menu-styles";
@@
   function init() {
-    var style = document.createElement("style");
-    style.id = "blt-mega-menu-styles";
-    style.textContent = CSS;
-    document.head.appendChild(style);
+    if (document.getElementById(MENU_BAR_ID)) return;
+
+    if (!document.getElementById(MENU_STYLE_ID)) {
+      var style = document.createElement("style");
+      style.id = MENU_STYLE_ID;
+      style.textContent = CSS;
+      document.head.appendChild(style);
+    }

Also applies to: 145-149, 191-193

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@js/blt-mega-menu.js` at line 20, Make init() idempotent by adding an early
guard that returns if document.getElementById(MENU_BAR_ID) already exists;
likewise, before creating/appending the stylesheet node check for the stylesheet
element’s id (the same id you assign when creating the <style> element, e.g.
STYLE_ID or the literal used) and skip appending if present. Apply the same
existence checks around any other code paths that create/append the menu bar or
style (the blocks that currently append the menu DOM and the style node) so
repeated calls to init() or multiple included scripts do not duplicate elements.
🧹 Nitpick comments (1)
js/blt-mega-menu.js (1)

112-115: Mirror the visual open state to aria-expanded.

The section buttons and hamburger only change classes and icon text, so assistive tech never gets the expanded/collapsed state. Keep aria-expanded in sync with the same toggles.

♿ Proposed improvement
-        + '<button class="blt-mn-btn" type="button">'
+        + '<button class="blt-mn-btn" type="button" aria-expanded="false">'
@@
-        + '<button id="blt-mn-ham" type="button" aria-label="Toggle BLT menu">&#9776;</button>'
+        + '<button id="blt-mn-ham" type="button" aria-label="Toggle BLT menu" aria-expanded="false" aria-controls="blt-mn-mob">&#9776;</button>'
@@
         items.forEach(function (i) {
-          i.querySelector(".blt-mn-btn").classList.remove("open");
+          var otherBtn = i.querySelector(".blt-mn-btn");
+          otherBtn.classList.remove("open");
+          otherBtn.setAttribute("aria-expanded", "false");
           i.querySelector(".blt-mn-drop").classList.remove("open");
         });
         if (opening) {
           btn.classList.add("open");
           drop.classList.add("open");
         }
+        btn.setAttribute("aria-expanded", String(opening));
@@
     document.addEventListener("click", function () {
       items.forEach(function (i) {
-        i.querySelector(".blt-mn-btn").classList.remove("open");
+        var otherBtn = i.querySelector(".blt-mn-btn");
+        otherBtn.classList.remove("open");
+        otherBtn.setAttribute("aria-expanded", "false");
         i.querySelector(".blt-mn-drop").classList.remove("open");
       });
     });
@@
       var isOpen = mob.classList.toggle("open");
       ham.innerHTML = isOpen ? "&#10005;" : "&#9776;";
+      ham.setAttribute("aria-expanded", String(isOpen));

Also applies to: 140-140, 160-170, 175-179, 184-187

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@js/blt-mega-menu.js` around lines 112 - 115, The button markup currently
renders section buttons and the hamburger without ARIA state; add
aria-expanded="false" to the generated button string for section buttons (the
element using class "blt-mn-btn" that concatenates sec.icon and esc(sec.label))
and to the hamburger button (class "blt-mn-hamburger"), then update the
click/toggle handlers that add/remove open/active classes to also set the
button's aria-expanded attribute to "true" when opening and "false" when closing
so assistive tech sees the expanded/collapsed state.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@js/blt-mega-menu.js`:
- Around line 175-188: The document click handler currently only closes desktop
dropdowns; update it to also close the mobile drawer by removing the "open"
class from the element referenced by mob (querySelector("#blt-mn-mob")) and
reset the hamburger (ham) state/innerHTML to the closed icon; specifically,
inside the global click listener that iterates items and touches
".blt-mn-btn"/".blt-mn-drop", also call mob.classList.remove("open") and set
ham.innerHTML = "&#9776;" so the mobile drawer closes the same way as the
desktop menus.
- Line 20: Make init() idempotent by adding an early guard that returns if
document.getElementById(MENU_BAR_ID) already exists; likewise, before
creating/appending the stylesheet node check for the stylesheet element’s id
(the same id you assign when creating the <style> element, e.g. STYLE_ID or the
literal used) and skip appending if present. Apply the same existence checks
around any other code paths that create/append the menu bar or style (the blocks
that currently append the menu DOM and the style node) so repeated calls to
init() or multiple included scripts do not duplicate elements.

---

Nitpick comments:
In `@js/blt-mega-menu.js`:
- Around line 112-115: The button markup currently renders section buttons and
the hamburger without ARIA state; add aria-expanded="false" to the generated
button string for section buttons (the element using class "blt-mn-btn" that
concatenates sec.icon and esc(sec.label)) and to the hamburger button (class
"blt-mn-hamburger"), then update the click/toggle handlers that add/remove
open/active classes to also set the button's aria-expanded attribute to "true"
when opening and "false" when closing so assistive tech sees the
expanded/collapsed state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e72d5491-ae8d-4d4c-a94a-918efeb5e0a2

📥 Commits

Reviewing files that changed from the base of the PR and between 9afb223 and cc40b82.

📒 Files selected for processing (1)
  • js/blt-mega-menu.js

@owasp-blt owasp-blt bot added unresolved-conversations: 0 PR has 0 unresolved conversations and removed unresolved-conversations: 0 PR has 0 unresolved conversations labels Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-peer-review PR needs peer review quality: medium unresolved-conversations: 0 PR has 0 unresolved conversations

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants