Skip to content

[change] Eliminate redundancy of header HTML #314#1080

Open
kunalverma2512 wants to merge 4 commits into
openwisp:masterfrom
kunalverma2512:eliminate-redundancy-of-header-html
Open

[change] Eliminate redundancy of header HTML #314#1080
kunalverma2512 wants to merge 4 commits into
openwisp:masterfrom
kunalverma2512:eliminate-redundancy-of-header-html

Conversation

@kunalverma2512
Copy link
Copy Markdown

Checklist

  • I have read the OpenWISP Contributing Guidelines.
  • I have manually tested the changes proposed in this pull request.
  • I have written new test cases for new code and/or updated existing tests for changes to existing code.
  • I have updated the documentation.(Note: Since this is a code refactor and doesn't change user-facing docs, checking this is standard).

Reference to Existing Issue

Closes #314.

Description of Changes

I have refactored the Header component to fix the issue where the desktop and mobile navigation were being rendered as two completely separate blocks of HTML. By moving the nav links and language buttons into shared constants within the render method, I was able to unify the entire header into a single JSX structure that handles different screen sizes purely through CSS media queries. This makes the code a lot easier to maintain because we no longer have to update links in two different places, and it also slightly reduces the DOM weight for the browser. I specifically kept the .header-mobile-menu class on the container to make sure the organization-specific background colors and themes still apply correctly on mobile, so there are no visual regressions from the original design.

Screenshot

1.Before change
in web view
image

in phone view (Toggled opened)
Screenshot 2026-03-28 at 12 37 00 AM

2.After change
in web view
Screenshot 2026-03-28 at 12 38 02 AM

in phone view (Toggled opened)
Screenshot 2026-03-28 at 12 38 33 AM

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The header component was refactored to remove duplicated desktop/mobile markup: languageButtons and navLinks are computed once and rendered in a unified structure. Navigation items now render either an internal Link or an external <a> depending on internal-link detection; active state compares pathname === link.url.replace("{orgSlug}", orgSlug). Viewport-specific wrapper and class modifiers were removed or replaced (e.g., header-container, header-row-2 ${menu ? "display-flex" : "mobile-hidden"}), and CSS was updated with .header-unified-nav, .header-hamburger, and .mobile-languages-row plus responsive rules.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title '[change] Eliminate redundancy of header HTML #314' directly addresses the linked issue #314, uses the correct 'change' type prefix, and accurately describes the main refactoring objective.
Description check ✅ Passed The description includes all required template sections: completed checklist, reference to issue #314, detailed explanation of changes, and multiple before/after screenshots demonstrating the visual outcome.
Linked Issues check ✅ Passed The code changes fully satisfy issue #314's requirements: HTML duplication is eliminated by unifying nav links and language buttons into shared constants, responsive behavior is handled via CSS media queries instead of separate structures, and DOM weight is reduced.
Out of Scope Changes check ✅ Passed All changes directly support the stated objective of eliminating header HTML redundancy; modifications to header.js, header.test.js, and index.css are all scoped to unifying the header structure and updating corresponding tests and styles.
Bug Fixes ✅ Passed This custom check is not applicable to this pull request because the PR is a refactoring/enhancement effort, not a bug fix. The PR closes issue #314, which is a feature request to eliminate redundant header HTML and rely on CSS media queries for responsiveness.

✏️ 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.

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from 36e1be5 to d6ef743 Compare March 27, 2026 19:23
@openwisp-companion
Copy link
Copy Markdown

Test and Commit Message Failures

Hello @kunalverma2512,
(Analysis for commit d6ef743)

  1. Test Failure: The Header component tests are failing due to snapshot mismatches. This indicates that the rendered output of the Header component has changed unexpectedly.
  • Fix: Review the changes in the Header component and update the snapshots by running yarn run coverage -u in your local environment.
  1. Commit Message Failure: The commit message does not follow the required format.
  • Fix: Ensure your commit message includes the issue number in the body, even if it's referenced in the title. For example:
[change] Eliminate redundancy of header HTML #314

This commit addresses redundancy in the header HTML structure.

Fixes #314

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from d6ef743 to 7858dfd Compare March 27, 2026 19:27
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/components/header/header.js`:
- Around line 80-91: The header language button markup (generated by
languages.map in languageButtons and the onClick setLanguage handler) no longer
includes the header-desktop-language-btn class; update the corresponding browser
tests to use the new selector shape by removing header-desktop-language-btn from
the button selectors (i.e., match button.header-language-btn and the specific
header-language-btn-<slug> classes such as header-language-btn-it and
header-language-btn-en) so the tests target the current DOM structure.

In `@client/components/header/header.test.js`:
- Around line 108-109: The test incorrectly expects isInternalLink to be called
three times even though props.header.links contains only one link; update the
expectation in the test to expect one call instead of three (change the
isInternalLink toHaveBeenCalledTimes assertion from 3 to 1) — this corresponds
to the single call performed inside the links.map() in the Header component
where isInternalLink is invoked for each entry in props.header.links.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 4b7bcb2a-4f7e-44cd-b1db-4b79f1c311c7

📥 Commits

Reviewing files that changed from the base of the PR and between 1d0f214 and d6ef743.

📒 Files selected for processing (3)
  • client/components/header/header.js
  • client/components/header/header.test.js
  • client/components/header/index.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests and Coverage
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}

📄 CodeRabbit inference engine (Custom checks)

**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}: Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations
Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred
General: Ensure tests cover the happy path, error paths, boundary values, and unusual inputs

Files:

  • client/components/header/header.test.js
🧠 Learnings (4)
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-25T00:22:16.841Z
Learnt from: nemesifier
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: :0-0
Timestamp: 2026-03-25T00:22:16.841Z
Learning: In `openwisp/openwisp-wifi-login-pages` browser tests (e.g., `browser-test/mobile-verfication.test.js`), fixed delay waits (e.g., `driver.sleep()`) are intentionally used instead of `driver.wait()` for toast message animations. This is because the JS animation on toast messages does not expose a reliable DOM state to poll against, and testing confirmed that fixed waits are more robust in this context. Do not flag these as flaky-by-design without considering this justification.

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-18T17:34:09.903Z
Learnt from: prathmeshkulkarni-coder
Repo: openwisp/openwisp-wifi-login-pages PR: 1063
File: client/components/status/status.test.js:2890-2916
Timestamp: 2026-03-18T17:34:09.903Z
Learning: Do not rely on mocking or altering window.location in Jest/JSDOM for this project. Since window.location is non-configurable in the test environment and attempts to redefine or delete it can cause state leaks across tests, avoid hacks like delete window.location or Object.defineProperty(window, 'location', ...) in tests. Instead, migrate detection-related tests to React Testing Library (RTL) and use RTL-friendly patterns (e.g., render components and inspect behavior via UI, or mock network/detection logic with explicit dependency injection or module mocks). This pattern should apply to all test files under client/components (any .test.js) where window.location might be interacted with.

Applied to files:

  • client/components/header/header.test.js
🔇 Additional comments (7)
client/components/header/header.js (2)

93-128: Clean consolidation of nav links rendering.

The unified navLinks computation correctly handles:

  • shouldLinkBeShown for auth/verification checks
  • isInternalLink for routing decisions
  • Placeholder replacement with {orgSlug}
  • Active state based on pathname comparison

130-186: Well-structured unified header layout.

The refactored JSX correctly:

  • Renders languageButtons in both desktop-languages and mobile-languages-row containers
  • Uses CSS classes (mobile-hidden, display-flex) for responsive behavior
  • Preserves header-mobile-menu class for organization-specific styling compatibility (per context snippet from organizations/default/client_assets/index.css)
client/components/header/header.test.js (2)

156-161: Test expectations correctly updated for unified header.

  • 4 language buttons (2 in .desktop-languages + 2 in .mobile-languages-row) ✓
  • 2 active English buttons (one per container) ✓
  • 0 active Italian buttons ✓

236-239: Language button interaction tests properly updated.

Using .at(0) and .at(1) correctly targets the duplicate Italian buttons in separate containers and validates that setLanguage is called for each click.

Based on learnings: "Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior" - this change appropriately covers the new dual-button structure.

client/components/header/index.css (3)

117-122: Correct default-hidden state for mobile-only elements.

Setting display: none by default for .header-hamburger and .mobile-languages-row ensures they only appear within the mobile media query, delegating responsive behavior entirely to CSS as intended by the PR objectives.


159-164: Appropriate visibility toggling for responsive layout.

  • .desktop-languages hidden on mobile ✓
  • .mobile-hidden utility with !important ensures elements stay hidden regardless of inline styles ✓

This enables the unified JSX to render both desktop and mobile language buttons once, with CSS controlling visibility.


169-191: Mobile nav styling correctly targets unified structure.

The responsive rules for .header-unified-nav and .header-unified-nav > .header-link properly handle:

  • Column layout with centered alignment
  • Full-width links with appropriate spacing
  • Language row visibility and centering

Comment thread client/components/header/header.test.js
@openwisp-companion
Copy link
Copy Markdown

Test Snapshot Failures in Header Component

Hello @kunalverma2512,
(Analysis for commit 7858dfd)

There are 4 test snapshot failures in the Header component. This indicates that the rendered output of the component has changed and no longer matches the previously saved snapshot.

To fix this, you need to update the snapshots to reflect the current state of the component. Run the following command in your terminal:

yarn run coverage -u

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from 7858dfd to 4ff455d Compare March 27, 2026 19:34
@openwisp-companion
Copy link
Copy Markdown

Test Failure in Language Change

Hello @kunalverma2512,
(Analysis for commit 4ff455d)

  • Test Failure: The browser-test/language-change.test.js test failed because the element button.header-language-btn.header-desktop-language-btn.header-language-btn-it could not be located within the timeout period. This indicates a potential issue with the element's visibility or the test's timing.

  • Fix: Review the browser-test/language-change.test.js test to ensure the element selector is correct and that there are adequate waits for the element to be present and interactable before attempting to click it.

  • Test Failure: The test should render login page and submit login form failed with a TypeError: Cannot read properties of undefined (reading 'click'). This occurred when trying to click the Italian language button.

  • Fix: This is likely related to the previous failure. Ensure the Italian language button is correctly identified and available before the click() method is called. Check the test logic in browser-test/language-change.test.js for proper element handling.

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from 4ff455d to 4329f78 Compare March 28, 2026 03:59
@openwisp-companion
Copy link
Copy Markdown

Test Failure in Password Expiration Test

Hello @kunalverma2512,
(Analysis for commit 4329f78)

  • Test Failure: The test browser-test/password-expired.test.js failed because the expected warning message "Your password has expired, please update it." was not received. Instead, an empty string was received. This indicates that the warning toast message element was not found or did not contain the expected text.

  • Fix: Review the browser-test/password-expired.test.js test file. Ensure that the warningToastMessage element is correctly identified and that the application is displaying the expected message when a password has expired. You may need to adjust the selector for warningToastMessage or verify the application's behavior.

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

♻️ Duplicate comments (1)
client/components/header/header.test.js (1)

108-109: ⚠️ Potential issue | 🟠 Major

Fix the expected call count for isInternalLink — should be 1, not 3.

The test sets up only one link in props.header.links (lines 100-105), and isInternalLink is called once per link in the links.map() at line 100 of header.js. The expected call count should be 1, not 3.

🐛 Proposed fix
-    expect(isInternalLink).toHaveBeenCalledTimes(3);
+    expect(isInternalLink).toHaveBeenCalledTimes(1);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/components/header/header.test.js` around lines 108 - 109, The test
incorrectly expects isInternalLink to be called three times; update the
assertion in header.test.js to expect a single call: change the expect for
isInternalLink call count from 3 to 1 so it matches the single link in
props.header.links and the single invocation in the links.map() inside header.js
(where isInternalLink is called).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/components/header/header.js`:
- Around line 80-91: The language button class list in the languageButtons JSX
(inside the languages.map callback that renders buttons and calls setLanguage)
still includes "header-desktop-language-btn" even when those buttons are used in
mobile contexts; to address this, either (preferred for a quick follow-up)
replace "header-desktop-language-btn" with a neutral, unified class name (e.g.,
"header-language-btn-platform") across the map and where selectors/tests rely on
it, or if you must keep the existing class for backward-compatible test
selectors, add a one-line clarifying comment directly above the languageButtons
declaration explaining that "header-desktop-language-btn" is intentionally
preserved for backward compatibility with browser tests even though the buttons
are reused in mobile, so future cleanup can rename it safely.

In `@client/components/header/index.css`:
- Around line 197-204: Remove the redundant CSS override inside the media query:
the global rule .header-desktop-language-btn already sets display: inline-block,
so delete the block targeting .mobile-languages-row .header-desktop-language-btn
within the `@media` (max-width: 767px) section to avoid duplicate rules and keep
the stylesheet clean.

---

Duplicate comments:
In `@client/components/header/header.test.js`:
- Around line 108-109: The test incorrectly expects isInternalLink to be called
three times; update the assertion in header.test.js to expect a single call:
change the expect for isInternalLink call count from 3 to 1 so it matches the
single link in props.header.links and the single invocation in the links.map()
inside header.js (where isInternalLink is called).
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 8bdf353d-c157-4916-a1bb-31c16f574412

📥 Commits

Reviewing files that changed from the base of the PR and between d6ef743 and 4329f78.

⛔ Files ignored due to path filters (1)
  • client/components/header/__snapshots__/header.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • client/components/header/header.js
  • client/components/header/header.test.js
  • client/components/header/index.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests and Coverage
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}

📄 CodeRabbit inference engine (Custom checks)

**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}: Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations
Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred
General: Ensure tests cover the happy path, error paths, boundary values, and unusual inputs

Files:

  • client/components/header/header.test.js
🧠 Learnings (5)
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior

Applied to files:

  • client/components/header/header.js
  • client/components/header/header.test.js
📚 Learning: 2026-03-25T00:22:16.841Z
Learnt from: nemesifier
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: :0-0
Timestamp: 2026-03-25T00:22:16.841Z
Learning: In `openwisp/openwisp-wifi-login-pages` browser tests (e.g., `browser-test/mobile-verfication.test.js`), fixed delay waits (e.g., `driver.sleep()`) are intentionally used instead of `driver.wait()` for toast message animations. This is because the JS animation on toast messages does not expose a reliable DOM state to poll against, and testing confirmed that fixed waits are more robust in this context. Do not flag these as flaky-by-design without considering this justification.

Applied to files:

  • client/components/header/header.js
  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Bug Fixes: If the bug affects the user interface, a Selenium browser test should be included

Applied to files:

  • client/components/header/header.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-18T17:34:09.903Z
Learnt from: prathmeshkulkarni-coder
Repo: openwisp/openwisp-wifi-login-pages PR: 1063
File: client/components/status/status.test.js:2890-2916
Timestamp: 2026-03-18T17:34:09.903Z
Learning: Do not rely on mocking or altering window.location in Jest/JSDOM for this project. Since window.location is non-configurable in the test environment and attempts to redefine or delete it can cause state leaks across tests, avoid hacks like delete window.location or Object.defineProperty(window, 'location', ...) in tests. Instead, migrate detection-related tests to React Testing Library (RTL) and use RTL-friendly patterns (e.g., render components and inspect behavior via UI, or mock network/detection logic with explicit dependency injection or module mocks). This pattern should apply to all test files under client/components (any .test.js) where window.location might be interacted with.

Applied to files:

  • client/components/header/header.test.js
🔇 Additional comments (7)
client/components/header/header.js (2)

93-128: LGTM! Navigation link rendering logic is correct.

The unified navLinks computation properly:

  • Filters links based on shouldLinkBeShown with authentication/verification state
  • Uses isInternalLink correctly with link.url (matching the function signature in check-internal-links.js)
  • Conditionally renders Link vs a based on internal/external status
  • Applies active state when pathname matches the resolved URL

178-185: LGTM! Unified nav structure preserves organization theming.

The header-mobile-menu class is retained alongside the new header-unified-nav class, which maintains compatibility with organization-specific CSS overrides (e.g., organizations/default/client_assets/index.css line 148 targets .header-mobile-menu for background styling). The mobile-hidden class toggle correctly works with the CSS to show/hide on mobile.

client/components/header/header.test.js (3)

153-161: LGTM! Test selectors correctly updated for unified structure.

The test assertions properly reflect the new unified rendering:

  • Line 154: Uses .header-link (unified) instead of desktop-specific selector
  • Line 157: Expects 4 language buttons (2 languages × 2 locations = 4)
  • Lines 160-161: Active state assertions account for both desktop and mobile instances

163-175: LGTM! Logo selector tests updated correctly.

The selector change from .header-logo-image.header-desktop-logo-image to .header-logo-image correctly matches the simplified class structure in the component.


235-240: LGTM! Language button interaction tests updated correctly.

The test now uses .at(0) and .at(1) to select specific buttons from the unified rendering, and the assertion progression (1 → 2 calls) correctly validates that both button instances trigger setLanguage.

client/components/header/index.css (2)

67-78: LGTM! Unified nav styling properly replaces the previous desktop-specific selector.

The .header-unified-nav selector correctly inherits the flexbox layout styling previously applied to .header-row-2-inner, maintaining the same max-width and alignment for both desktop and mobile contexts.


117-122: LGTM! Default hidden state for mobile-only elements.

Setting .header-hamburger and .mobile-languages-row to display: none by default ensures they're hidden on desktop and only revealed via the mobile media query.

Comment thread client/components/header/header.js
Comment thread client/components/header/index.css Outdated
@openwisp-companion
Copy link
Copy Markdown

Test Failure in Password Expired Test

Hello @kunalverma2512,
(Analysis for commit d8bab6c)

  • Test Failure: The test browser-test/password-expired.test.js failed because the expected warning message "Your password has expired, please update it." was not found. The received message was an empty string. This indicates that the warning toast message element was either not present or not populated as expected during the test.

  • Fix: Review the logic in browser-test/password-expired.test.js around line 43. Ensure that the warningToastMessage element is correctly identified and that its text is being set as expected by the application under test. If the element is correct, check the application's behavior to see why the message is not being displayed.

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch 2 times, most recently from ad5b926 to 9d7893d Compare March 28, 2026 06:29
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/components/header/header.js`:
- Around line 106-131: The Link rendering has an extra trailing space in its
className template ("button ") causing inconsistent class attribute compared to
the anchor branch ("button"); update the Link JSX in the map (the Link element
that uses pathname === link.url.replace("{orgSlug}", orgSlug) ? "active" : "")
to remove the trailing space so both branches use "button" consistently.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 88e9398f-7062-48d3-864c-6c2e136414be

📥 Commits

Reviewing files that changed from the base of the PR and between 4329f78 and 9d7893d.

📒 Files selected for processing (2)
  • client/components/header/header.js
  • client/components/header/index.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests and Coverage
🔇 Additional comments (7)
client/components/header/index.css (5)

67-78: LGTM!

Clean refactor: unifying the .header-unified-nav and .sticky-container .inner selectors with shared flex layout properties is a good approach for consistent styling and maintainability.


117-122: LGTM!

Properly hiding hamburger and mobile language row by default, with media query revealing them on mobile. This follows mobile-first/desktop-first responsive patterns correctly.


159-164: The !important declaration is acceptable here for mobile hiding.

Using !important on .mobile-hidden (line 163) ensures this utility class reliably hides elements on mobile regardless of other display rules. This is a valid use case for overriding dynamic inline styles or component-level rules.


169-184: LGTM!

The mobile-specific styles for .header-unified-nav properly override the desktop flex layout with column direction, centered alignment, and full-width link styling. The margin-right: 0 on line 183 correctly resets the desktop margin.


197-199: LGTM!

This rule ensures language buttons display correctly as inline-block elements. The previous redundant media query override was correctly removed per past review feedback.

client/components/header/header.js (2)

79-94: LGTM!

Good refactor: computing languageButtons once and reusing it in both desktop and mobile contexts eliminates the previous duplication. The comment explaining the header-desktop-language-btn class retention for Selenium backward compatibility is helpful.


133-192: LGTM! Clean unified header structure.

The refactored render method successfully:

  • Eliminates duplicate desktop/mobile header markup
  • Computes navLinks and languageButtons once
  • Preserves header-mobile-menu class for organization-specific styling
  • Uses CSS-driven responsive behavior via mobile-hidden and desktop-languages containers

This aligns well with the PR objectives of reducing DOM duplication while maintaining visual consistency.

Comment thread client/components/header/header.js
@openwisp-companion
Copy link
Copy Markdown

Code Style Failure

Hello @kunalverma2512,
(Analysis for commit 9d7893d)

The CI failed due to code style issues detected by Prettier in client/components/header/header.js.

Fix: Run yarn prettier --write "**/*.+(js|jsx|json|css|md)" to automatically format the code.

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from 9d7893d to d556dfe Compare March 28, 2026 06:35
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)
client/components/header/header.js (1)

106-131: ⚠️ Potential issue | 🟡 Minor

Fix trailing space in className for consistency.

Line 112 has a trailing space after button (button ) while line 123 has button without the trailing space. This creates inconsistent whitespace in the rendered class attribute.

🔧 Proposed fix
           return (
             <Link
               className={`header-link header-link-${index + 1} ${
                 pathname === link.url.replace("{orgSlug}", orgSlug)
                   ? "active"
                   : ""
-              } button `}
+              } button`}
               to={link.url.replace("{orgSlug}", orgSlug)}
               key={index}
             >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/components/header/header.js` around lines 106 - 131, The Link element
in the header component returns className={`header-link header-link-${index + 1}
${ pathname === link.url.replace("{orgSlug}", orgSlug) ? "active" : "" } button
` which includes a trailing space after "button" causing inconsistent class
attributes compared to the anchor branch; remove the trailing space so the
className ends with "button" (update the JSX in the Link return where className
is constructed, referencing link, index, pathname, orgSlug and getText to locate
the exact spot).
client/components/header/header.test.js (1)

108-109: ⚠️ Potential issue | 🟡 Minor

Fix the expected call count for isInternalLink.

The test sets up only one link in props.header.links but expects isInternalLink to be called 3 times. Since isInternalLink is called once per link in the links.map() at line 103 of header.js, and there's only 1 link, the expected call count should be 1.

🔧 Proposed fix
     wrapper = shallow(<Header {...props} />);
-    expect(isInternalLink).toHaveBeenCalledTimes(3);
+    expect(isInternalLink).toHaveBeenCalledTimes(1);
     expect(isInternalLink).toHaveBeenCalledWith("/default/login");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/components/header/header.test.js` around lines 108 - 109, The test's
expectation for isInternalLink call count is wrong because props.header.links
contains only one link; update the assertion in header.test.js to expect a
single call (change expect(isInternalLink).toHaveBeenCalledTimes(3) to
expect(isInternalLink).toHaveBeenCalledTimes(1)) while keeping the existing
expect(isInternalLink).toHaveBeenCalledWith("/default/login") so it still
verifies the argument from the links.map() invocation in header.js.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@client/components/header/header.js`:
- Around line 106-131: The Link element in the header component returns
className={`header-link header-link-${index + 1} ${ pathname ===
link.url.replace("{orgSlug}", orgSlug) ? "active" : "" } button ` which includes
a trailing space after "button" causing inconsistent class attributes compared
to the anchor branch; remove the trailing space so the className ends with
"button" (update the JSX in the Link return where className is constructed,
referencing link, index, pathname, orgSlug and getText to locate the exact
spot).

In `@client/components/header/header.test.js`:
- Around line 108-109: The test's expectation for isInternalLink call count is
wrong because props.header.links contains only one link; update the assertion in
header.test.js to expect a single call (change
expect(isInternalLink).toHaveBeenCalledTimes(3) to
expect(isInternalLink).toHaveBeenCalledTimes(1)) while keeping the existing
expect(isInternalLink).toHaveBeenCalledWith("/default/login") so it still
verifies the argument from the links.map() invocation in header.js.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fdf49064-137d-4cc3-8489-f49ae385bbe4

📥 Commits

Reviewing files that changed from the base of the PR and between 9d7893d and d556dfe.

⛔ Files ignored due to path filters (1)
  • client/components/header/__snapshots__/header.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • client/components/header/header.js
  • client/components/header/header.test.js
  • client/components/header/index.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests and Coverage
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}

📄 CodeRabbit inference engine (Custom checks)

**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}: Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations
Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred
General: Ensure tests cover the happy path, error paths, boundary values, and unusual inputs

Files:

  • client/components/header/header.test.js
🧠 Learnings (4)
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-18T17:34:09.903Z
Learnt from: prathmeshkulkarni-coder
Repo: openwisp/openwisp-wifi-login-pages PR: 1063
File: client/components/status/status.test.js:2890-2916
Timestamp: 2026-03-18T17:34:09.903Z
Learning: Do not rely on mocking or altering window.location in Jest/JSDOM for this project. Since window.location is non-configurable in the test environment and attempts to redefine or delete it can cause state leaks across tests, avoid hacks like delete window.location or Object.defineProperty(window, 'location', ...) in tests. Instead, migrate detection-related tests to React Testing Library (RTL) and use RTL-friendly patterns (e.g., render components and inspect behavior via UI, or mock network/detection logic with explicit dependency injection or module mocks). This pattern should apply to all test files under client/components (any .test.js) where window.location might be interacted with.

Applied to files:

  • client/components/header/header.test.js
🔇 Additional comments (6)
client/components/header/header.js (1)

79-94: Good addition of backward compatibility comment.

The comment clearly documents why header-desktop-language-btn class is preserved despite being used in both desktop and mobile contexts. This addresses the semantic naming concern while maintaining Selenium test compatibility.

client/components/header/index.css (3)

67-78: LGTM!

The .header-unified-nav selector correctly replaces the previous .header-row-2-inner while maintaining the same flexbox layout properties. The unified styling supports both desktop and mobile navigation in a single structure.


117-122: Good approach: default-hidden with mobile media query override.

Setting .header-hamburger and .mobile-languages-row to display: none by default and then revealing them in the mobile media query is a clean responsive pattern that avoids JavaScript-based visibility toggling.


197-199: LGTM!

The .header-desktop-language-btn rule is correctly placed outside the media query as a global style. The previously flagged redundant media query override has been removed.

client/components/header/header.test.js (2)

156-161: LGTM!

The updated expectations correctly reflect the unified header structure:

  • 4 language buttons (2 languages × 2 render locations: desktop + mobile)
  • 2 active English buttons (one in each location)

This aligns with the component rendering languageButtons in both .desktop-languages and .mobile-languages-row.


235-240: LGTM!

The interaction test correctly targets both Italian language button instances (.at(0) and .at(1)) to verify that clicking either the desktop or mobile button triggers the setLanguage callback. This ensures both button locations are functional.

@kunalverma2512 kunalverma2512 force-pushed the eliminate-redundancy-of-header-html branch from d556dfe to e173689 Compare March 28, 2026 06:47
@openwisp-companion
Copy link
Copy Markdown

Test Failures in Browser Tests

Hello @kunalverma2512,
(Analysis for commit e173689)

  • browser-test/mobile-phone-change.test.js Failure: The test timed out waiting for a success toast element to appear. This indicates that the expected success message was not displayed after an action, or it appeared too late.

  • Fix: Investigate why the success toast is not appearing or is delayed. This might involve checking the application logic that triggers the toast or increasing the wait time in the test if it's a minor timing issue.

  • browser-test/password-reset.test.js Failure 1: The test should send password reset email failed because the received text for the success toast was an empty string, while it expected "Password reset e-mail has been sent.".

  • Fix: Ensure that the password reset functionality correctly displays the success toast message. This could be an issue with the backend not returning the expected confirmation or the frontend not rendering the toast correctly.

  • browser-test/password-reset.test.js Failure 2: The test should show not found on password confirm failed with a TypeError: Cannot read properties of undefined (reading 'isDisplayed'). This occurred when trying to wait for a success toast element.

  • Fix: This error suggests that the successToastDiv element was not found, leading to undefined when isDisplayed was called. This could be due to the "Not found." message not being displayed as expected, or the selector for the toast being incorrect. Review the test logic and the element selectors.

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 (1)
client/components/header/header.test.js (1)

108-109: ⚠️ Potential issue | 🟠 Major

Fix the expected call count for isInternalLink — this test will fail.

The test configures props.header.links with only 1 link (lines 100-105), but expects isInternalLink to be called 3 times. Looking at header.js, isInternalLink is called once per link inside links.map() (line 103). With 1 link, the expected call count should be 1, not 3.

-    expect(isInternalLink).toHaveBeenCalledTimes(3);
+    expect(isInternalLink).toHaveBeenCalledTimes(1);

,

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

In `@client/components/header/header.test.js` around lines 108 - 109, The test's
expected call count for isInternalLink is wrong: it configures
props.header.links with a single link but asserts isInternalLink was called 3
times; update the assertion in client/components/header/header.test.js to expect
1 call (i.e., change expect(isInternalLink).toHaveBeenCalledTimes(3) to
toHaveBeenCalledTimes(1)) since header.js calls isInternalLink once per entry in
links.map().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@client/components/header/header.test.js`:
- Around line 108-109: The test's expected call count for isInternalLink is
wrong: it configures props.header.links with a single link but asserts
isInternalLink was called 3 times; update the assertion in
client/components/header/header.test.js to expect 1 call (i.e., change
expect(isInternalLink).toHaveBeenCalledTimes(3) to toHaveBeenCalledTimes(1))
since header.js calls isInternalLink once per entry in links.map().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 15756221-d348-4ace-96fc-5fd38ceceefb

📥 Commits

Reviewing files that changed from the base of the PR and between d556dfe and c4ddbc3.

⛔ Files ignored due to path filters (1)
  • client/components/header/__snapshots__/header.test.js.snap is excluded by !**/*.snap
📒 Files selected for processing (3)
  • client/components/header/header.js
  • client/components/header/header.test.js
  • client/components/header/index.css
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Tests and Coverage
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}

📄 CodeRabbit inference engine (Custom checks)

**/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go}: Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations
Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior
Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred
General: Ensure tests cover the happy path, error paths, boundary values, and unusual inputs

Files:

  • client/components/header/header.test.js
🧠 Learnings (5)
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Changes: Tests must be updated to cover non-trivial changes and ensure proper validation of modified behavior

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-25T00:22:16.841Z
Learnt from: nemesifier
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: :0-0
Timestamp: 2026-03-25T00:22:16.841Z
Learning: In `openwisp/openwisp-wifi-login-pages` browser tests (e.g., `browser-test/mobile-verfication.test.js`), fixed delay waits (e.g., `driver.sleep()`) are intentionally used instead of `driver.wait()` for toast message animations. This is because the JS animation on toast messages does not expose a reliable DOM state to poll against, and testing confirmed that fixed waits are more robust in this context. Do not flag these as flaky-by-design without considering this justification.

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Bug Fixes: Tests must be deterministic and not flaky, avoiding dependencies on timing, sleeps, specific timezones, system time, randomness without fixed seeds, race conditions, concurrency timing, network access, external services, filesystem state, environment-specific configuration, execution order, shared global state, hardcoded ports, or unawaited async operations

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-19T22:44:00.665Z
Learnt from: CR
Repo: openwisp/openwisp-wifi-login-pages PR: 0
File: coderabbit-custom-pre-merge-checks-unique-id-file-non-traceable-F7F2B60C-1728-4C9A-8889-4F2235E186CA.txt:0-0
Timestamp: 2026-03-19T22:44:00.665Z
Learning: Applies to **/*.{test,spec}.{js,ts,jsx,tsx,py,java,rb,go} : Features: Tests must be added with coverage that does not decrease significantly; for UI features, Selenium browser tests are preferred

Applied to files:

  • client/components/header/header.test.js
📚 Learning: 2026-03-18T17:34:09.903Z
Learnt from: prathmeshkulkarni-coder
Repo: openwisp/openwisp-wifi-login-pages PR: 1063
File: client/components/status/status.test.js:2890-2916
Timestamp: 2026-03-18T17:34:09.903Z
Learning: Do not rely on mocking or altering window.location in Jest/JSDOM for this project. Since window.location is non-configurable in the test environment and attempts to redefine or delete it can cause state leaks across tests, avoid hacks like delete window.location or Object.defineProperty(window, 'location', ...) in tests. Instead, migrate detection-related tests to React Testing Library (RTL) and use RTL-friendly patterns (e.g., render components and inspect behavior via UI, or mock network/detection logic with explicit dependency injection or module mocks). This pattern should apply to all test files under client/components (any .test.js) where window.location might be interacted with.

Applied to files:

  • client/components/header/header.test.js
🔇 Additional comments (11)
client/components/header/header.test.js (3)

156-161: LGTM!

The test correctly expects 4 language buttons (2 languages × 2 render locations) and 2 active English buttons (one in desktop, one in mobile context). This aligns with the unified rendering approach where languageButtons is rendered in both .desktop-languages and .mobile-languages-row.


235-240: LGTM!

The interaction test correctly targets both Italian language button instances (.at(0) and .at(1)) in the unified rendering structure and verifies that setLanguage is called the expected number of times.


153-155: LGTM!

The selector update from desktop-specific to unified .header-link correctly reflects the refactored component structure.

client/components/header/index.css (4)

67-78: LGTM!

The unified .header-unified-nav selector correctly replaces the previous desktop-specific selector, matching the new DOM structure in header.js. The flex layout rules are appropriate for the navigation container.


117-122: LGTM!

The default display: none for .header-hamburger and .mobile-languages-row correctly establishes the desktop baseline where these mobile-specific elements should be hidden.


159-164: LGTM!

The mobile media query correctly hides .desktop-languages and uses !important on .mobile-hidden to override any dynamically-applied display-flex utility class.


197-199: LGTM!

The .header-desktop-language-btn rule placed outside the media query ensures consistent visibility across viewports for the language buttons.

client/components/header/header.js (4)

79-94: LGTM!

The backward-compatibility comment (lines 80-82) clearly documents why header-desktop-language-btn is preserved despite being used in both viewports. The languageButtons array is cleanly computed once and ready for reuse in both desktop and mobile locations.


96-131: LGTM!

The unified navLinks logic correctly:

  • Filters links using shouldLinkBeShown before rendering
  • Uses isInternalLink to determine routing approach
  • Renders internal links as <Link> with active state detection
  • Renders external links as <a> with proper security attributes (target="_blank", rel="noreferrer noopener")

181-188: LGTM!

The unified structure elegantly handles responsive behavior:

  • header-row-2 toggles visibility via mobile-hidden class based on menu state
  • header-unified-nav header-mobile-menu dual class preserves organization-specific theming while applying unified nav styles
  • navLinks and languageButtons are rendered once and reused, eliminating the previous duplication

140-148: LGTM!

The logo rendering correctly uses the unified header-logo-image class without viewport-specific modifiers, simplifying the CSS selectors and DOM structure.

@kunalverma2512
Copy link
Copy Markdown
Author

@nemesifier All checks have passed and the PR is approved. It is ready for merge.
please let me know if any further changes are needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[change] Eliminate redundancy of header HTML

1 participant