Skip to content

Conversation

@rintumerin-aot
Copy link
Contributor

@rintumerin-aot rintumerin-aot commented Nov 25, 2025

User description

📝 Pull Request Summary

Description:
Navbar updated with hover toggle and toggle button

Related Jira Ticket:
https://aottech.atlassian.net/browse/FWF-5586

Type of Change:

  • ✨ Feature
  • 🐞 Bug Fix
  • ♻️ Refactor
  • 🧹 Code Cleanup
  • 🧪 Test Addition / Update
  • 📦 Dependency Update
  • 📘 Documentation Update
  • 🚀 Deployment / Config / Security Updates

🧩 Microfrontends Affected

Please select all microfrontends or modules that are part of this change:

  • forms-flow-admin
  • forms-flow-components
  • forms-flow-integration
  • forms-flow-nav
  • forms-flow-review
  • forms-flow-service
  • forms-flow-submissions
  • forms-flow-theme
  • scripts
  • Others (please specify below)

Details (if Others selected):


🧠 Summary of Changes


🧪 Testing Details

Testing Performed:

Screenshots (if applicable):
Screenshot 2025-11-21 134914
Screenshot 2025-11-21 134922


✅ Checklist

  • Code builds successfully without lint or type errors
  • Unit tests added or updated
  • Integration or end-to-end tests validated
  • UI verified
  • Documentation updated (README / Confluence / UI Docs)
  • No sensitive information (keys, passwords, secrets) committed
  • I have updated the CHANGELOG with relevant details
  • I have given a clear and meaningful PR title and description
  • I have verified cross-repo dependencies (if any)
  • I have confirmed backward compatibility with previous releases
  • Verified changes across all selected microfrontends

👥 Reviewer Notes


PR Type

Enhancement


Description

  • Add persistent hover-toggle sidebar behavior

  • Introduce clickable menu toggle icon

  • Responsive collapse on viewport resize

  • Update styles for toggle and layout


Diagram Walkthrough

flowchart LR
  Sidebar["Sidebar.jsx"]
  SCSS["Sidebar.scss"]
  Icons["SvgIcons/index.tsx"]

  Sidebar -- "imports" --> Icons
  Sidebar -- "adds hover + persistent state" --> SCSS
  Sidebar -- "renders toggle button" --> Icons
  SCSS -- "styles .menu-toggle-icon, layout" --> Sidebar
Loading

File Walkthrough

Relevant files
Enhancement
index.tsx
Add MenuToggleIcon SVG component                                                 

forms-flow-components/src/components/SvgIcons/index.tsx

  • Add MenuToggleIcon SVG component.
  • Export new icon alongside existing icons.
+7/-0     
Sidebar.scss
Style menu toggle icon and layout tweaks                                 

forms-flow-nav/src/sidenav/Sidebar.scss

  • Add .menu-toggle-icon styles and rotation on open.
  • Adjust options container bottom margin to auto.
  • Maintain collapsed hover width behavior.
+17/-4   
Sidebar.jsx
Add persistent hover-toggle and responsive sidebar             

forms-flow-nav/src/sidenav/Sidebar.jsx

  • Implement persistent collapsed with hover toggle state.
  • Add resize listener to set collapsed responsively.
  • Render clickable .menu-toggle-icon using MenuToggleIcon.
  • Inline --navbar-width style based on collapsed state.
+56/-11 

@github-actions
Copy link

github-actions bot commented Nov 25, 2025

PR Reviewer Guide 🔍

(Review updated until commit 0d3a717)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Issue

The computed collapsed state is derived from persistentCollapsed !== hoverToggled. This XOR-like logic can be hard to reason about and may lead to unexpected toggling when state updates race (e.g., resize + hover). Validate that the sidebar never ends up in a stuck state and that keyboard/screen-reader users can still toggle reliably.

const [persistentCollapsed, setPersistentCollapsed] = useState(getInitialCollapsedState());
const [hoverToggled, setHoverToggled] = useState(false);
const collapsed = persistentCollapsed !== hoverToggled;
const sidebarRef = useRef(null);
const hoverTimeout = useRef(null);
Accessibility

The .menu-toggle-icon div is clickable with role="button" but lacks keyboard handlers and ARIA state. Add tabIndex, aria-pressed/aria-expanded, and handle Enter/Space to ensure accessibility.

<div className={`menu-toggle-icon${collapsed ? "" : " open"}`} onClick={handleToggleClick} role="button">
  <MenuToggleIcon />
</div>
UX Consistency

The rotation of the toggle icon uses a class .open based on the collapsed state. Double-check the mapping so the rotation direction matches the visual expand/collapse action to avoid confusing cues.

  &.open svg {
    transform: rotate(180deg);
  }
}

@github-actions
Copy link

github-actions bot commented Nov 25, 2025

PR Code Suggestions ✨

Latest suggestions up to 0d3a717
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Avoid SSR window access

Guard against server-side rendering by avoiding direct access to window during
initialization. Use a safe default and compute on mount instead. This prevents
runtime errors in non-browser environments and improves hydration stability.

forms-flow-nav/src/sidenav/Sidebar.jsx [143-145]

 const getInitialCollapsedState = () => {
+  if (typeof window === "undefined") return true;
   return window.innerWidth <= 1200;
 };
Suggestion importance[1-10]: 7

__

Why: Correctly guards against window being undefined during SSR by adding a typeof check, preventing runtime errors without altering behavior in-browser.

Medium
General
Move CSS var out of inline style

Avoid setting CSS custom properties inline as they can be harder to override and may
cause unnecessary re-renders. Update the root variable via effect when collapsed
changes to keep behavior consistent with prior implementation.

forms-flow-nav/src/sidenav/Sidebar.jsx [406-415]

+useEffect(() => {
+  document.documentElement.style.setProperty("--navbar-width", collapsed ? "3rem" : "10rem");
+}, [collapsed]);
+
 <div
   className={sidebarClass}
-  style={{ height: sidenavHeight, "--navbar-width": collapsed ? "3rem" : "10rem" }}
+  style={{ height: sidenavHeight }}
   data-testid="sidenav"
   ref={sidebarRef}
   onMouseEnter={handleMouseEnter}
   onMouseLeave={handleMouseLeave}
   role="button"
 >
Suggestion importance[1-10]: 6

__

Why: Restores prior pattern of updating --navbar-width via effect, aiding overrideability and avoiding inline CSS variables; moderate improvement with accurate code.

Low
Clarify collapsed computation

The derived collapsed state flips based on hover, which can be confusing and
brittle. Replace with an explicit computed value for readability and to avoid logic
errors when states change rapidly.

forms-flow-nav/src/sidenav/Sidebar.jsx [147-149]

 const [persistentCollapsed, setPersistentCollapsed] = useState(getInitialCollapsedState());
 const [hoverToggled, setHoverToggled] = useState(false);
-const collapsed = persistentCollapsed !== hoverToggled;
+const collapsed = persistentCollapsed && !hoverToggled ? true : !persistentCollapsed && hoverToggled ? false : persistentCollapsed;
Suggestion importance[1-10]: 2

__

Why: The proposed ternary chain is overly complex and functionally equivalent to current logic, reducing readability without fixing a concrete issue.

Low

Previous suggestions

Suggestions up to commit c5dee4b
CategorySuggestion                                                                                                                                    Impact
Possible issue
Prevent queued hover timeouts

Clear any existing timeout before setting a new one to avoid multiple queued timers
causing flicker or stale updates. Also clear the timeout on unmount to prevent
leaks.

forms-flow-nav/src/sidenav/Sidebar.jsx [167-173]

 const handleMouseLeave = () => {
-  if (persistentCollapsed) {
-    hoverTimeout.current = setTimeout(() => {
-      setHoverToggled(false);
-    }, 120);
+  if (!persistentCollapsed) return;
+  if (hoverTimeout.current) {
+    clearTimeout(hoverTimeout.current);
   }
+  hoverTimeout.current = window.setTimeout(() => {
+    setHoverToggled(false);
+    hoverTimeout.current = null;
+  }, 120);
 };
 
+useEffect(() => {
+  return () => {
+    if (hoverTimeout.current) {
+      clearTimeout(hoverTimeout.current);
+    }
+  };
+}, []);
+
Suggestion importance[1-10]: 7

__

Why: Clearing existing timeouts before setting a new one and on unmount prevents flicker and leaks; this is accurate and improves robustness with the newly added hover-delay logic.

Medium
Fix state initialization and cleanup

Initialize useState with getInitialCollapsedState() to avoid passing the function
reference as the initial state. Also, clear any pending hover timeout on unmount to
prevent memory leaks and state updates after unmount.

forms-flow-nav/src/sidenav/Sidebar.jsx [147-151]

-const [persistentCollapsed, setPersistentCollapsed] = useState(getInitialCollapsedState);
+const [persistentCollapsed, setPersistentCollapsed] = useState(getInitialCollapsedState());
 const [hoverToggled, setHoverToggled] = useState(false);
 const collapsed = persistentCollapsed !== hoverToggled;
 const sidebarRef = useRef(null);
-const hoverTimeout = useRef(null);
+const hoverTimeout = useRef<number | null>(null);
Suggestion importance[1-10]: 6

__

Why: Initializing useState with getInitialCollapsedState() avoids unintended lazy init semantics and the cleanup for hoverTimeout is a reasonable enhancement, though the added TS type is not applicable in JSX and cleanup isn’t shown in the PR context.

Low
General
Keep toggle always accessible

Ensure the toggle control remains visible and clickable when the sidebar is
collapsed by positioning it consistently. Add a higher z-index and explicit width to
prevent it being overlapped or clipped during transitions.

forms-flow-nav/src/sidenav/Sidebar.scss [82-95]

 .menu-toggle-icon {
-  padding: 0.87rem 0.75rem;
-  padding-bottom: 0;
+  padding: 0.87rem 0.75rem 0 0.75rem;
   cursor: pointer;
   transition: transform 0.3s ease;
+  position: sticky;
+  top: 0;
+  z-index: 2;
+  width: 100%;
+  background: inherit;
 
   svg {
     transition: transform 0.3s ease;
+    display: block;
+    margin: 0 auto;
   }
 
   &.open svg {
     transform: rotate(180deg);
   }
 }
Suggestion importance[1-10]: 5

__

Why: Making the toggle sticky with z-index can improve usability during collapse/expand, but it's a stylistic/layout change with potential side effects and is not strictly required for correctness.

Low

@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
B Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

@github-actions
Copy link

Persistent review updated to latest commit 0d3a717

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants