Skip to content

Comments

Feature/sidebar menu improvement#336

Open
priscilladeroode wants to merge 3 commits intomasterfrom
feature/sidebar-menu-improvement
Open

Feature/sidebar menu improvement#336
priscilladeroode wants to merge 3 commits intomasterfrom
feature/sidebar-menu-improvement

Conversation

@priscilladeroode
Copy link
Contributor

@priscilladeroode priscilladeroode commented Jan 28, 2026

Acceptance Criteria
Feature: Refactor Sidebar Menu for Accessibility, Composability, and Flexible Visibility
As a developer,
I want to refactor the Sidebar Menu component using the composition pattern,
So that it is accessible, modular, and supports flexible visibility logic based on contextual rules.

Scenario: Improve accessibility of the Sidebar Menu

Given I am refactoring the component

When I inspect and update it

Then all interactive items should be keyboard-navigable

And proper semantic roles and ARIA attributes should be applied

And tab order should be logical and follow accessibility standards

Scenario: Build the Sidebar using the composition pattern

Given I am building the Sidebar component

When I structure its internal elements

Then it should be composed of atomic subcomponents (e.g., MenuItem, MenuSection)

And each subcomponent should be reusable independently

And the component should not rely on inheritance or a tightly coupled structure

Scenario: Export atomic components used within the Sidebar

Given I build atomic components for the Sidebar (e.g., , )

When I export them

Then they should be available for other developers to build custom layouts

Scenario: Support flexible visibility rules

Given I define a menu item in the sidebar

When I want to conditionally render it

Then I should be able to pass a visibleIf function

And this function should accept a generic layout context

And the item should only render if the function returns true

Scenario: Avoid opinionated visibility logic

Given visibility logic is context-specific

When I implement conditional rendering

Then I should not hardcode logic for auth, roles, or specific cases

And the logic should be extensible and unopinionated

Scenario: Customize display options for MenuItem

Given I render a component

When I configure its props

Then I should be able to:

Show or hide text

Include or omit an icon

Add or skip section titles

Enable or disable submenus

Add an optional badge

Add an optional info element (number or ReactNode)

Scenario: Allow styling overrides for the Sidebar and subcomponents

Given I use the Sidebar or its atomic components

When I pass className or style props

Then the component should apply the overrides

And support CSS variables or design tokens if applicable

Approvd
https://app.approvd.io/silverlogic/BA/stories/44869

Summary by CodeRabbit

  • New Features

    • Introduced navigations-v2 system with sidebar, horizontal, and vertical layout options.
    • Added sidebar navigation with collapsible drawer support for mobile devices.
    • Added ArrowIosForwardIcon for navigation indicators.
    • Added LogoContainer component for flexible logo rendering.
  • UI/Style Updates

    • Added "sidebar" layout option to theme configuration.
    • Added collapsedSidebar setting to control sidebar visibility state.

@changeset-bot
Copy link

changeset-bot bot commented Jan 28, 2026

⚠️ No Changeset found

Latest commit: 860bcc3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

📝 Walkthrough

Walkthrough

A new navigations-v2 web module is introduced, providing sidebar, vertical, and horizontal navigation layouts with composable components, type-safe props, and supporting constants. Related design system enhancements include new icon exports, logo container component, and theme layout type extensions.

Changes

Cohort / File(s) Summary
Navigations V2 Layout Components
packages/components/modules/navigations-v2/web/layouts/...
Three layout implementations (Sidebar, Vertical, Horizontal) with corresponding types and props interfaces for composing navigation layouts with customizable slots.
Sidebar Navigation Components
packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/...
Complete sidebar navigation system with root, header, footer, menu root, toggle button, and layout sub-components; supports drawer toggling and responsive behavior.
Sidebar Menu Primitives
packages/components/modules/navigations-v2/web/primitives/SidebarMenuNav*/...
Low-level navigation item and group primitives (SidebarMenuNavItem, SidebarMenuNavGroup) with sub-components (Root, Title, Icon, Arrow, Content, Header) and comprehensive prop typing.
Navigation Data Structures & Utilities
packages/components/modules/navigations-v2/web/types.ts, constants.ts, __shared__/useActiveLink.ts, SidebarMenu.../utils.tsx
Navigation data type definitions (NavItemData, NavListData, NavGroupData), layout constants (HEADER_HEIGHT, NAV_WIDTH, NAV_PADDING_*), data type literals, and renderNav utility function.
Shared Navigation Components
packages/components/modules/navigations-v2/web/__shared__/... (HeaderNavigation, NavigationDrawer, MainContainer, NavigationLayout)
Reusable navigation components for headers, drawers, main content containers, and top-level navigation layout selection based on theme layout type.
Design System Enhancements
packages/design-system/components/web/icons/ArrowIosForwardIcon, packages/design-system/components/web/logos/LogoContainer
New ArrowIosForwardIcon SVG component and LogoContainer wrapper for logo presentation with optional homepage link; includes Storybook documentation and stories.
Type System & Configuration Updates
packages/design-system/styles/web/types.ts, packages/design-system/hooks/web/useUISettings/constants.ts, packages/utils/types/typescript.ts
Extended ThemeLayout to include 'sidebar' variant with deprecation notices, added collapsedSidebar to UISettings, introduced NonUndefined utility type.
API Extensions & Barrel Exports
packages/components/package.json, packages/components/modules/navigations-v2/web/index.ts, packages/design-system/components/web/logos/index.ts
New public exports for navigations-v2, LogoContainer, and icon; package.json updated with new export paths.
Component Refinements
packages/components/modules/navigations/web/NavigationLayout/MainContainer/index.tsx, packages/components/modules/navigations/web/__shared__/NavToggleButton/types.ts
Minor formatting adjustment to existing MainContainer; extended NavToggleButtonProps with optional onClick prop.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Unread chats tab #136: Introduces navigation layout constants (NAV_WIDTH, NAV_PADDING_*) and updates NavToggleButton types, aligning with this PR's navigation architecture foundation.

Suggested labels

needs review

Suggested reviewers

  • priscilladeroode
  • nossila

Poem

🐰 Hop along the navigation path so new,
With sidebars, verticals, horizontals too!
Composable slots and types so grand,
A navigation system, carefully planned! 🧭✨

🚥 Pre-merge checks | ❌ 3
❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description provides extensive acceptance criteria and scenarios but lacks a proper changelog format matching the required template structure (package name, version, changelog items). Restructure the description to follow the template format: '- package_name package update - v X.X.X' with concise changelog items summarizing the key changes instead of detailed acceptance criteria.
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.
Title check ❓ Inconclusive The title 'Feature/sidebar menu improvement' is vague and generic. It describes a general area of change but lacks specificity about what the actual improvement entails, making it unclear what the main objective is. Revise the title to be more specific and descriptive of the primary change, such as 'Add composition-based sidebar navigation with v2 implementation' or 'Introduce navigations-v2 with sidebar layout and atomic components'.

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/sidebar-menu-improvement

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.

Copy link

@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: 17

🤖 Fix all issues with AI agents
In
`@packages/components/modules/navigations/web/__shared__/NavToggleButton/types.ts`:
- Around line 3-5: The NavToggleButtonProps interface incorrectly narrows
IconButtonProps.onClick to VoidFunction, removing the event parameter; restore
compatibility by removing the redeclared onClick or change its type to
React.MouseEventHandler<HTMLButtonElement> so it matches IconButtonProps (update
NavToggleButtonProps to stop shadowing onClick or explicitly use the same
signature) and ensure any components using NavToggleButtonProps accept the event
argument.

In `@packages/components/modules/new-navigations/web/createNavRenderer.tsx`:
- Around line 13-22: The NavGroup branch uses a static fallback key 'group'
which can cause React key collisions; update the key generation in the
NAV_DATA_TYPE.group case (where NavGroup is returned for NavGroupData) to use a
guaranteed-unique value (for example prefer a stable id on NavGroupData like
nav.id or fall back to a derived unique string such as `group-${index}` or a
UUID) so each NavGroup rendered by renderNav has a distinct key prop.

In `@packages/components/modules/new-navigations/web/index.ts`:
- Around line 49-50: The public export has a typo: rename the misspelled export
identifier "ToogleButton" to "ToggleButton" so the module correctly re-exports
the default from './SidebarMenu/ToggleButton'; also verify the corresponding
type export line remains correct ("export type * from
'./SidebarMenu/ToggleButton/types'") and update any imports elsewhere that
reference the old "ToogleButton" symbol to use "ToggleButton".

In
`@packages/components/modules/new-navigations/web/NavigationLayout/VerticalLayout/index.tsx`:
- Around line 7-19: ESLint rule arrow-body-style flags the verbose body in the
VerticalLayout arrow function; change VerticalLayout (the const declaration) to
use an implicit return instead of a block body with return — remove the
surrounding { return ( ... ) } and replace with a single parenthesized JSX
expression (keeping the Box props spread, sx prop and {children}). This
satisfies arrow-body-style without changing behavior.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuContent/index.tsx`:
- Line 6: SidebarMenuContent currently destructures children from its
PropsWithChildren but never renders it; either stop claiming children in the
component type/props or render it. Fix option A: remove children from the
component signature and from the type (remove PropsWithChildren usage) so
SidebarMenuContentProps no longer implies children. Fix option B: keep
PropsWithChildren and include {children} in the JSX returned by
SidebarMenuContent (for example render children after or alongside
navData-driven nodes), ensuring children is placed inside the component's root
element and respects existing sx/props handling; update the component signature
to remain FC<SidebarMenuContentProps> and remove the unused variable warning if
you choose option A.
- Line 4: The import cycle arises because SidebarMenuContent imports
createNavRenderer which imports SidebarNavigation/types that in turn imports
SidebarMenu; break this by moving shared type definitions out of
SidebarNavigation/types (the types referenced by createNavRenderer and
SidebarMenu) into a new common module (e.g., navigation/types or
SidebarNavigation/sharedTypes) and update createNavRenderer,
SidebarNavigation/types, SidebarMenu, and SidebarMenuContent to import those
shared types from the new module instead of importing SidebarMenu; ensure
exported type names remain unchanged so functions like createNavRenderer and the
SidebarMenu component keep their existing signatures while removing any direct
import of SidebarMenu from the types file.
- Line 20: createNavRenderer is being called for every item in navData causing
unnecessary work; compute the renderer once before mapping instead of inside the
map. Create a single renderer value (e.g., const renderNav =
createNavRenderer(slots ?? {})) outside the navData?.map(...) and then call
renderNav(nav, idx) for each item; if the slots object can change, wrap the
renderer creation in useMemo keyed on slots to avoid recreating it each render.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuContent/types.ts`:
- Around line 1-4: There are duplicate imports from "react" — combine them into
a single import: replace separate imports of PropsWithChildren and ElementType
with one import statement that imports both (e.g., import { PropsWithChildren,
ElementType } from "react") so the file only imports React symbols once; keep
the other imports (ScrollbarProps, NavigationData) unchanged and ensure no other
references are altered.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuFooter/index.tsx`:
- Around line 6-8: The SidebarMenuFooter component incorrectly treats falsy
children (like 0 or "") as absent by using if (!children); update the presence
check in SidebarMenuFooter to only bail out for null or undefined (e.g.,
children == null or children === null || children === undefined) so legitimate
falsy children render, and leave the Box return (with sx and props) unchanged.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuHeader/index.tsx`:
- Line 6: Remove the debug console.log in SidebarMenuHeader (the statement
console.log('children', children)) so it doesn't pollute production; locate the
SidebarMenuHeader component in index.tsx and delete that console.log or replace
it with a proper debug-only logger gated by an environment flag if you need
runtime inspection.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupContent/index.tsx`:
- Around line 11-16: The component currently uses a block body with an explicit
return; simplify the arrow function to an implicit return by removing the curly
braces and return statement so it directly returns the JSX element (Collapse
with props and children). Update the function that references open, props,
children and the Collapse component (SidebarMenuNavGroupContent) to use the
concise arrow syntax.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupHeader/index.tsx`:
- Around line 7-12: The SidebarMenuNavGroupHeader component currently
destructures unused props `children` and `disabled`; either remove them from the
prop destructuring in the SidebarMenuNavGroupHeader function signature, prefix
them with an underscore (e.g., `_children`, `_disabled`) if you want to reserve
them for future use to satisfy the linter, or actually use them (e.g., render
`children` alongside `title` and apply `disabled` to conditional
className/aria-disabled). Update the SidebarMenuNavGroupHeaderProps usage
accordingly so no unused variables remain.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupRoot/types.ts`:
- Around line 4-5: The type SidebarMenuNavGroupRootProps references
React.ReactNode but React is not imported; update the imports so the type
resolves (either import React as a namespace or import ReactNode directly) and
ensure SidebarMenuNavGroupRootProps still extends Omit<StackProps, 'children'>
with children: (props: { open: boolean; handleToggle: () => void }) =>
React.ReactNode; modify the top-of-file imports to include React or { ReactNode
} from 'react' accordingly.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavItem/SidebarMenuNavItemIcon/index.tsx`:
- Around line 7-9: Remove the invalid null default for the Icon prop in the
SidebarMenuNavItemIcon component: update the function signature in
SidebarMenuNavItemIcon to stop assigning Icon = null (leave it as { Icon, sx,
...props }) because Icon is already typed as optional (Icon?: FC<SvgIconProps>)
and null is not assignable under strict mode; keep the existing null check (if
(!Icon) return null) to handle the absent prop.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavItem/SidebarMenuNavItemRoot/index.tsx`:
- Around line 20-31: The rel attribute only sets 'noopener' for external links,
which still leaks referrer data; update the logic in SidebarMenuNavItemRoot so
when componentType === 'externalLink' the rel value includes both 'noopener
noreferrer' (e.g., adjust the rel assignment referenced by rel and used on the
ListItemButton component) and keep target set to '_blank'; ensure the change
affects the ListItemButton props (component, href, target, rel) so external
links get "noopener noreferrer".

In
`@packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/index.tsx`:
- Line 10: ToggleButtonProps declares iconProps but ToggleButton doesn't accept
or forward them; update the ToggleButton function signature to destructure
iconProps from props (e.g., { sx, onClick, Icon, iconProps, ...other }) and then
pass those through to the rendered icon component (the Icon / IconComponent
usage) by spreading iconProps onto it (e.g., <Icon {...iconProps} />) so the SVG
props are applied; ensure the prop name matches ToggleButtonProps and types
remain intact.

In
`@packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/types.ts`:
- Line 16: The renderNav type uses React.Key and React.ReactNode but the React
namespace isn't imported; fix by either adding a namespace import (import React
from 'react') so React.Key/React.ReactNode resolve, or change the signature to
use direct type imports (import type { Key, ReactNode } from 'react' and update
renderNav to use Key and ReactNode). Update the types file where renderNav is
declared to include one of these imports and ensure the function signature
references the imported types (renderNav).
🧹 Nitpick comments (21)
packages/components/modules/new-navigations/web/constants.ts (1)

43-47: Consider adding as const for stricter type inference.

Adding as const to NAV_DATA_TYPE enables literal type inference, which improves type safety when using these values as discriminators.

💡 Suggested improvement
 export const NAV_DATA_TYPE = {
   item: 'item',
   list: 'list',
   group: 'group',
-}
+} as const
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx (2)

7-7: Import path points to old navigations module.

This imports NAV_WIDTH from the old navigations/web/constants module rather than the new new-navigations/web/constants. This could lead to maintenance issues if constants diverge between modules. Consider using the local constants from ../../constants for consistency within the new module.

Suggested fix
-import { NAV_WIDTH } from '../../../../navigations/web/constants'
+import { NAV_WIDTH } from '../../constants'

44-68: Remove unnecessary React fragment.

The fragment wrapper <>...</> contains only a single child element (Box), making it redundant.

Suggested fix
   return (
-    <>
-      <Box
-        sx={{
-          flexShrink: { lg: 0 },
-          width: { lg: NAV_WIDTH.VERTICAL },
-          display: { xs: 'none', lg: 'flex' },
-        }}
-      >
-        <Stack
-          {...ContainerProps}
-          sx={{
-            height: 1,
-            position: 'fixed',
-            width: NAV_WIDTH.VERTICAL,
-            borderRight: (theme) => `solid 1px ${theme.palette.divider}`,
-            paddingX: (theme) => theme.spacing(2),
-            ...ContainerProps?.sx,
-          }}
-        >
-          {collapsible && <ToggleButton {...ToggleButtonProps} />}
-          {children}
-        </Stack>
-      </Box>
-    </>
+    <Box
+      sx={{
+        flexShrink: { lg: 0 },
+        width: { lg: NAV_WIDTH.VERTICAL },
+        display: { xs: 'none', lg: 'flex' },
+      }}
+    >
+      <Stack
+        {...ContainerProps}
+        sx={{
+          height: 1,
+          position: 'fixed',
+          width: NAV_WIDTH.VERTICAL,
+          borderRight: (theme) => `solid 1px ${theme.palette.divider}`,
+          paddingX: (theme) => theme.spacing(2),
+          ...ContainerProps?.sx,
+        }}
+      >
+        {collapsible && <ToggleButton {...ToggleButtonProps} />}
+        {children}
+      </Stack>
+    </Box>
   )
packages/components/modules/new-navigations/web/types.ts (2)

16-20: Redundant children property declaration.

NavListData already inherits children?: NavItemData[] from NavItemData (via Omit<NavItemData, 'dataType'>). Re-declaring it with the same type is redundant and could cause confusion during future maintenance.

Suggested fix
 export interface NavListData extends Omit<NavItemData, 'dataType'> {
   dataType: "list"
-  children?: NavItemData[]
-
 }

4-14: Consider adding visibleIf to support conditional visibility.

Per the PR objectives, the component should "support flexible, unopinionated visibility rules by allowing a visibleIf function on menu items." The current hide boolean is static. Consider adding an optional visibleIf function that accepts a generic context for dynamic visibility control.

Example enhancement
 export interface NavItemData {
   title: string
   caption?: string
   icon?: FC<SvgIconProps>
   path?: string
   disabled?: boolean
   externalLink?: boolean
   children?: NavItemData[]
   dataType: "item"
   hide?: boolean
+  visibleIf?: <T>(context: T) => boolean
 }
packages/components/modules/new-navigations/web/NavigationLayout/types.ts (2)

10-10: Consider avoiding any for better type safety.

Using VariantComponent<any> loses type information for component props. If full generics are complex, consider using unknown or a base props type to maintain some type safety.

Example
-export type NavigationVariants = Partial<Record<LayoutVariant, VariantComponent<any>>>
+export type NavigationVariants = Partial<Record<LayoutVariant, VariantComponent<unknown>>>

12-16: Consider defining slot types explicitly.

Using any for slot values loses type safety. Consider defining a base slot type or using specific types for each slot option.

Example enhancement
+export type SlotValue = React.ReactNode | React.ComponentType<unknown>
+
 export interface NavigationLayout2Props extends PropsWithChildren {
   variants?: NavigationVariants
-  slots?: Partial<Record<SlotsOptions, any>>
+  slots?: Partial<Record<SlotsOptions, SlotValue>>
   navData?: NavigationData
 }
packages/design-system/components/web/icons/ArrowIosForwardIcon/index.tsx (1)

5-10: Remove nested <svg> and pass children directly to SvgIcon.
MUI SvgIcon should use only shape elements (<path>, <circle>, etc.) as direct children, not a nested <svg>. Set viewBox on the SvgIcon component instead.

♻️ Proposed refactor
-const ArrowIosForwardIcon: FC<SvgIconProps> = ({ sx, ...props }) => (
-    <SvgIcon sx={{ fontSize: 24, ...sx }} {...props}>
-        <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
-            <path d="M9.99981 18.9999C9.76616 19.0004 9.53972 18.919 9.35981 18.7699C9.1553 18.6004 9.02666 18.3564 9.00227 18.0919C8.97788 17.8274 9.05975 17.564 9.22981 17.3599L13.7098 11.9999L9.38981 6.62994C9.22204 6.42335 9.14354 6.1584 9.17169 5.89376C9.19985 5.62912 9.33233 5.38662 9.53981 5.21994C9.74898 5.03591 10.0254 4.94747 10.3026 4.97594C10.5797 5.00442 10.8324 5.14722 10.9998 5.36994L15.8298 11.3699C16.1331 11.7389 16.1331 12.2709 15.8298 12.6399L10.8298 18.6399C10.6263 18.8854 10.318 19.0191 9.99981 18.9999Z" fill="currentColor"/>
-        </svg>
-    </SvgIcon>
-)
+const ArrowIosForwardIcon: FC<SvgIconProps> = ({ sx, ...props }) => (
+  <SvgIcon sx={{ fontSize: 24, ...sx }} {...props}>
+    <path d="M9.99981 18.9999C9.76616 19.0004 9.53972 18.919 9.35981 18.7699C9.1553 18.6004 9.02666 18.3564 9.00227 18.0919C8.97788 17.8274 9.05975 17.564 9.22981 17.3599L13.7098 11.9999L9.38981 6.62994C9.22204 6.42335 9.14354 6.1584 9.17169 5.89376C9.19985 5.62912 9.33233 5.38662 9.53981 5.21994C9.74898 5.03591 10.0254 4.94747 10.3026 4.97594C10.5797 5.00442 10.8324 5.14722 10.9998 5.36994L15.8298 11.3699C16.1331 11.7389 16.1331 12.2709 15.8298 12.6399L10.8298 18.6399C10.6263 18.8854 10.318 19.0191 9.99981 18.9999Z" fill="currentColor"/>
+  </SvgIcon>
+)
packages/components/modules/new-navigations/web/NavigationLayout/index.tsx (1)

20-23: Consider strengthening type safety in variant resolution.

The type assertion as LayoutVariant on line 20 could mask invalid values from settings.themeLayout. If the settings contain an unexpected layout value, this will silently fail to match any variant and fall through to SidebarNavigation. This is likely acceptable as a fallback behavior, but the & any on line 23 undermines type safety.

♻️ Suggested improvement
-  const Variant = (variants?.[variant] ??
-    defaultVariants[variant] ??
-    SidebarNavigation) as VariantComponent<PropsWithChildren & any>
+  const Variant: VariantComponent<NavigationLayout2Props> = 
+    variants?.[variant] ?? defaultVariants[variant] ?? SidebarNavigation

Alternatively, if the component signatures vary, consider defining a more specific union type rather than using any.

packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavItem/index.tsx (2)

1-4: Minor: Import organization.

The FC import could be grouped with React-related imports for consistency, and there's a leading blank line.

♻️ Suggested fix
-
-import SidebarMenuNavItem from '../../SidebarMenu/SidebarMenuNavItem'
-import { DefaultNavItemProps } from './types'
 import { FC } from 'react'
+
+import SidebarMenuNavItem from '../../SidebarMenu/SidebarMenuNavItem'
+import { DefaultNavItemProps } from './types'

9-11: Remove unnecessary key prop.

The key prop on line 10 has no effect here since Root is not being rendered within a list iteration (e.g., .map()). React keys are only meaningful for reconciliation when rendering arrays of elements. Using key outside this context is misleading and has no functional benefit.

♻️ Suggested fix
   return (
     <Root
-      key={title}
       {...props}
     >
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupRoot/types.ts (1)

2-2: Unused import: PropsWithChildren.

PropsWithChildren is imported but not used in the interface definition.

🧹 Proposed fix
 import { StackProps } from "@mui/material"
-import { PropsWithChildren } from "react"
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavList/index.tsx (1)

1-5: Remove leading empty line.

Minor style issue: there's an unnecessary empty line at the start of the file.

🧹 Proposed fix
-
 import SidebarMenuNavGroup from "../SidebarMenuNavGroup"
packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/index.tsx (1)

14-14: Unnecessary key prop on Root.

The key prop on Root is unnecessary here since this component isn't being rendered as part of a list/array. The key is only meaningful when React needs to differentiate between sibling elements.

🧹 Proposed fix
-    <Root key={navGroup.subheader}>
+    <Root>
packages/components/modules/new-navigations/web/createNavRenderer.tsx (1)

8-9: Redundant nullish coalescing on required parameter.

The slots parameter is required (not optional), so slots ?? {} is unnecessary. If the intent is to allow undefined, consider making the parameter optional in the signature.

 export const createNavRenderer = (slots: SidebarDefaultNavigationSlots) => {
-    const { NavItem = DefaultNavItem, NavList = DefaultNavList, NavGroup = DefaultNavGroup } = slots ?? {}
+    const { NavItem = DefaultNavItem, NavList = DefaultNavList, NavGroup = DefaultNavGroup } = slots
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupHeader/index.tsx (1)

14-41: Unnecessary fragment wrapper and accessibility concern.

  1. The <>...</> fragment is unnecessary since there's only one child element.
  2. cursor: 'pointer' suggests the element is clickable, but there's no click handler. This may confuse users and screen readers expecting interactivity.
Suggested fix
   return (
-    <>
-      <ListSubheader
-        disableGutters
-        disableSticky
-        sx={{
-          fontSize: 11,
-          cursor: 'pointer',
+      <ListSubheader
+        disableGutters
+        disableSticky
+        sx={{
+          fontSize: 11,
           typography: 'overline',
           ...
         }}
         {...props}
       >
         {title}
       </ListSubheader>
-    </>
   )
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavItem/SidebarMenuNavItemArrow/index.tsx (1)

15-26: Prefer specific transition property over all.

Using transition: 'all' can cause unintended animations and is slightly less performant. Since only transform is being animated, specify it explicitly.

       sx={{
         fontSize: '16px',
         transform: `rotate(${isExpanded ? '-90deg' : '0deg'})`,
-        transition: 'all 0.25s linear',
+        transition: 'transform 0.25s linear',
         color: 'text.secondary',
         ...sx,
       }}
packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/index.tsx (1)

45-45: Line exceeds typical length and uses transition: 'all'.

Consider breaking this into multiple lines for readability and using a specific transition property.

-      <IconComponent sx={{ fontSize: '20px', transform: `rotate(${deg})`, transition: 'all 0.25s linear',}} />
+      <IconComponent
+        sx={{
+          fontSize: '20px',
+          transform: `rotate(${deg})`,
+          transition: 'transform 0.25s linear',
+        }}
+      />
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/types.ts (2)

8-16: Confusing DrawerProps usage - both extended and as property.

The interface extends PropsWithChildren<DrawerProps> but also has a DrawerProps?: DrawerProps property. This creates ambiguity about which props apply where. Consider clarifying the intent:

  • If DrawerProps property is meant for additional/override props to the internal Drawer, consider renaming it (e.g., drawerOverrides or DrawerSlotProps)
  • If it's redundant, remove one of them
 export interface SidebarMenuRootProps extends PropsWithChildren<DrawerProps> {
   open: boolean
   onClose: () => void
   collapsible?: boolean
   ToggleButton?: typeof NavToggleButton
   ToggleButtonProps?: NavToggleButtonProps
-  DrawerProps?: DrawerProps
+  DrawerSlotProps?: Partial<DrawerProps>
   ContainerProps?: StackProps
 }

5-6: Consider re-exporting NavToggleButton from a shared location to reduce import fragility.

The deep relative import path (../../../../navigations/web/__shared__/NavToggleButton) creates coupling between new-navigations and navigations modules. Since path aliases are not configured in the project, extracting NavToggleButton to packages/components/modules/__shared__/NavToggleButton and re-exporting it from both modules would eliminate the fragile multi-level path traversal and make the import clearer.

packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavList/index.tsx (1)

9-33: Reuse the filtered list to avoid duplicate filtering.

This avoids re-filtering and guarantees hasChildren and render use the same list.

♻️ Suggested refactor
-  const filteredChildren = navList.children?.filter((child) => !child.hide)
-  const hasChildren = filteredChildren?.length && filteredChildren.length > 0
+  const filteredChildren = navList.children?.filter((child) => !child.hide) ?? []
+  const hasChildren = filteredChildren.length > 0
...
-          {navList.children?.filter((child) => !child.hide).map((child) => (
+          {filteredChildren.map((child) => (
             <ListItem.Root key={child.title} {...child} >
               <ListItem.Icon Icon={child.icon} />
               <ListItem.Title title={child.title} caption={child.caption} />
             </ListItem.Root>
           ))}

Comment on lines +3 to +5
export interface NavToggleButtonProps extends IconButtonProps {
onClick?: VoidFunction
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

MUI material-ui IconButtonProps onClick type signature current documentation

💡 Result:

In current MUI Material UI (v7), IconButtonProps doesn’t declare its own onClick—it inherits all ButtonBase + native root-element props, so onClick’s type depends on the root component you’re rendering. [1]

Default (<button>)

IconButton’s default root component is 'button'. [2]
So the default onClick type is the native button handler:

(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void
// i.e.
React.MouseEventHandler<HTMLButtonElement>

If you override component

Because IconButtonProps is an overridable type (via OverrideProps/ExtendButtonBase), onClick changes with the root element you choose. [2][3]

Example:

type DefaultClick = IconButtonProps['onClick'];      // MouseEventHandler<HTMLButtonElement>
type AnchorClick  = IconButtonProps<'a'>['onClick']; // MouseEventHandler<HTMLAnchorElement>

Sources: IconButton API (inheritance) [1]; IconButton.d.ts type map (default 'button', overridable) [2]; ButtonBase.d.ts (overridable base) [3].


🏁 Script executed:

cat -n packages/components/modules/navigations/web/__shared__/NavToggleButton/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 257


Avoid narrowing onClick from MUI IconButtonProps.
IconButtonProps defines onClick as React.MouseEventHandler<HTMLButtonElement> (i.e., (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void). Redeclaring it as onClick?: VoidFunction removes the event parameter, creating an incompatible intersection that breaks handlers expecting the event argument.

🔧 Proposed fix
-export interface NavToggleButtonProps extends IconButtonProps {
-  onClick?: VoidFunction
-}
+export interface NavToggleButtonProps extends IconButtonProps {}
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations/web/__shared__/NavToggleButton/types.ts`
around lines 3 - 5, The NavToggleButtonProps interface incorrectly narrows
IconButtonProps.onClick to VoidFunction, removing the event parameter; restore
compatibility by removing the redeclared onClick or change its type to
React.MouseEventHandler<HTMLButtonElement> so it matches IconButtonProps (update
NavToggleButtonProps to stop shadowing onClick or explicitly use the same
signature) and ensure any components using NavToggleButtonProps accept the event
argument.

Comment on lines 13 to 22
case NAV_DATA_TYPE.group: {
const groupNav = nav as NavGroupData
return (
<NavGroup
key={groupNav.subheader ?? key ?? 'group'}
navGroup={groupNav}
slots={slots}
renderNav={renderNav}
/>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential React key collision with fallback value.

If multiple NavGroupData items lack a subheader and no explicit key is provided, they will all receive the static key 'group', causing React reconciliation issues.

Consider using a more unique fallback or requiring a key/id field on the data types.

-                        key={groupNav.subheader ?? key ?? 'group'}
+                        key={key ?? groupNav.subheader ?? groupNav.id}
🤖 Prompt for AI Agents
In `@packages/components/modules/new-navigations/web/createNavRenderer.tsx` around
lines 13 - 22, The NavGroup branch uses a static fallback key 'group' which can
cause React key collisions; update the key generation in the NAV_DATA_TYPE.group
case (where NavGroup is returned for NavGroupData) to use a guaranteed-unique
value (for example prefer a stable id on NavGroupData like nav.id or fall back
to a derived unique string such as `group-${index}` or a UUID) so each NavGroup
rendered by renderNav has a distinct key prop.

Comment on lines 49 to 50
export { default as ToogleButton } from './SidebarMenu/ToggleButton'
export type * from './SidebarMenu/ToggleButton/types'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix public export typo (Line 49).

ToogleButton is likely a misspelling of ToggleButton and will leak into the public API.

🛠️ Suggested fix
-export { default as ToogleButton } from './SidebarMenu/ToggleButton'
+export { default as ToggleButton } from './SidebarMenu/ToggleButton'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export { default as ToogleButton } from './SidebarMenu/ToggleButton'
export type * from './SidebarMenu/ToggleButton/types'
export { default as ToggleButton } from './SidebarMenu/ToggleButton'
export type * from './SidebarMenu/ToggleButton/types'
🤖 Prompt for AI Agents
In `@packages/components/modules/new-navigations/web/index.ts` around lines 49 -
50, The public export has a typo: rename the misspelled export identifier
"ToogleButton" to "ToggleButton" so the module correctly re-exports the default
from './SidebarMenu/ToggleButton'; also verify the corresponding type export
line remains correct ("export type * from './SidebarMenu/ToggleButton/types'")
and update any imports elsewhere that reference the old "ToogleButton" symbol to
use "ToggleButton".

Comment on lines 7 to 19
const VerticalLayout: FC<VerticalLayoutProps> = ({ children, ...props }) => {
return (
<Box
sx={{
minHeight: 1,
display: 'flex',
flexDirection: { xs: 'column', lg: 'row' },
}}
{...props}
>
{children}
</Box>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix ESLint arrow-body-style to unblock the pipeline.

🔧 Proposed fix
-const VerticalLayout: FC<VerticalLayoutProps> = ({ children, ...props }) => {
-  return (
-    <Box
-      sx={{
-        minHeight: 1,
-        display: 'flex',
-        flexDirection: { xs: 'column', lg: 'row' },
-      }}
-      {...props}
-    >
-      {children}
-    </Box>
-  )
-}
+const VerticalLayout: FC<VerticalLayoutProps> = ({ children, ...props }) => (
+  <Box
+    sx={{
+      minHeight: 1,
+      display: 'flex',
+      flexDirection: { xs: 'column', lg: 'row' },
+    }}
+    {...props}
+  >
+    {children}
+  </Box>
+)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const VerticalLayout: FC<VerticalLayoutProps> = ({ children, ...props }) => {
return (
<Box
sx={{
minHeight: 1,
display: 'flex',
flexDirection: { xs: 'column', lg: 'row' },
}}
{...props}
>
{children}
</Box>
)
const VerticalLayout: FC<VerticalLayoutProps> = ({ children, ...props }) => (
<Box
sx={{
minHeight: 1,
display: 'flex',
flexDirection: { xs: 'column', lg: 'row' },
}}
{...props}
>
{children}
</Box>
)
🧰 Tools
🪛 GitHub Actions: Main Workflow

[error] 7-7: ESLint: Unexpected block statement surrounding arrow body; move the returned value immediately after the => (arrow-body-style).

🪛 GitHub Check: Build and Lint Packages

[failure] 7-7:
Unexpected block statement surrounding arrow body; move the returned value immediately after the =>

🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/NavigationLayout/VerticalLayout/index.tsx`
around lines 7 - 19, ESLint rule arrow-body-style flags the verbose body in the
VerticalLayout arrow function; change VerticalLayout (the const declaration) to
use an implicit return instead of a block body with return — remove the
surrounding { return ( ... ) } and replace with a single parenthesized JSX
expression (keeping the Box props spread, sx prop and {children}). This
satisfies arrow-body-style without changing behavior.

import { FC } from 'react'
import { Scrollbar } from '@baseapp-frontend/design-system/components/web/scrollbars'
import { SidebarMenuContentProps } from './types'
import { createNavRenderer } from '../../createNavRenderer'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -e

echo "=== Checking file structure ==="
cd packages/components/modules/new-navigations/web 2>/dev/null || echo "Directory not found"
pwd
echo ""

echo "=== File at SidebarMenu/SidebarMenuContent/index.tsx ==="
head -20 SidebarMenu/SidebarMenuContent/index.tsx 2>/dev/null || echo "File not found"
echo ""

echo "=== Checking if createNavRenderer exists ==="
find . -name "createNavRenderer*" -type f
echo ""

echo "=== Checking createNavRenderer imports ==="
fd -t f 'createNavRenderer' . --exec cat {} \; 2>/dev/null | head -30
echo ""

echo "=== Checking SidebarNavigation/types.ts ==="
find . -path "*/SidebarNavigation/*" -name "types.ts" -exec echo "File: {}" \; -exec cat {} \;
echo ""

echo "=== Checking SidebarMenu imports ==="
find ./SidebarMenu -type f -name "*.ts" -o -name "*.tsx" | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && head -20 {}'

Repository: silverlogic/baseapp-frontend

Length of output: 8424


Circular dependency detected in module imports.

The dependency cycle is confirmed: SidebarMenu/SidebarMenuContentcreateNavRendererSidebarNavigation/typesSidebarMenu. The root cause is SidebarNavigation/types.ts importing the SidebarMenu module. Extract shared type definitions to a common location (e.g., a types directory at the navigation module level) to break the cycle.

🧰 Tools
🪛 GitHub Check: Build and Lint Packages

[failure] 4-4:
Dependency cycle via ./SidebarNavigation/types:5=>../SidebarMenu:3

🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuContent/index.tsx`
at line 4, The import cycle arises because SidebarMenuContent imports
createNavRenderer which imports SidebarNavigation/types that in turn imports
SidebarMenu; break this by moving shared type definitions out of
SidebarNavigation/types (the types referenced by createNavRenderer and
SidebarMenu) into a new common module (e.g., navigation/types or
SidebarNavigation/sharedTypes) and update createNavRenderer,
SidebarNavigation/types, SidebarMenu, and SidebarMenuContent to import those
shared types from the new module instead of importing SidebarMenu; ensure
exported type names remain unchanged so functions like createNavRenderer and the
SidebarMenu component keep their existing signatures while removing any direct
import of SidebarMenu from the types file.

Comment on lines 4 to 5
export interface SidebarMenuNavGroupRootProps extends Omit<StackProps, 'children'> {
children: (props: { open: boolean, handleToggle: () => void }) => React.ReactNode
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

React.ReactNode used without importing React.

The type uses React.ReactNode but only PropsWithChildren is imported from react. Either import React as a namespace or import ReactNode directly.

🔧 Proposed fix
 import { StackProps } from "@mui/material"
-import { PropsWithChildren } from "react"
+import type { ReactNode } from "react"

 export interface SidebarMenuNavGroupRootProps extends Omit<StackProps, 'children'> {
- children: (props: { open: boolean, handleToggle: () => void }) => React.ReactNode
+ children: (props: { open: boolean, handleToggle: () => void }) => ReactNode
  defaultOpen?: boolean
  hide?: boolean
-
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface SidebarMenuNavGroupRootProps extends Omit<StackProps, 'children'> {
children: (props: { open: boolean, handleToggle: () => void }) => React.ReactNode
import { StackProps } from "@mui/material"
import type { ReactNode } from "react"
export interface SidebarMenuNavGroupRootProps extends Omit<StackProps, 'children'> {
children: (props: { open: boolean, handleToggle: () => void }) => ReactNode
defaultOpen?: boolean
hide?: boolean
}
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupRoot/types.ts`
around lines 4 - 5, The type SidebarMenuNavGroupRootProps references
React.ReactNode but React is not imported; update the imports so the type
resolves (either import React as a namespace or import ReactNode directly) and
ensure SidebarMenuNavGroupRootProps still extends Omit<StackProps, 'children'>
with children: (props: { open: boolean; handleToggle: () => void }) =>
React.ReactNode; modify the top-of-file imports to include React or { ReactNode
} from 'react' accordingly.

Comment on lines 20 to 31
const target = componentType === 'externalLink' ? '_blank' : undefined
const rel = componentType === 'externalLink' ? 'noopener' : undefined


if (hide) return null

return (
<ListItemButton
component={component}
href={path}
target={target}
rel={rel}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add noreferrer for external links.

Using only noopener still leaks referrer information; use noopener noreferrer when target="_blank".

🔒 Proposed fix
-  const rel = componentType === 'externalLink' ? 'noopener' : undefined
+  const rel = componentType === 'externalLink' ? 'noopener noreferrer' : undefined
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const target = componentType === 'externalLink' ? '_blank' : undefined
const rel = componentType === 'externalLink' ? 'noopener' : undefined
if (hide) return null
return (
<ListItemButton
component={component}
href={path}
target={target}
rel={rel}
const target = componentType === 'externalLink' ? '_blank' : undefined
const rel = componentType === 'externalLink' ? 'noopener noreferrer' : undefined
if (hide) return null
return (
<ListItemButton
component={component}
href={path}
target={target}
rel={rel}
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavItem/SidebarMenuNavItemRoot/index.tsx`
around lines 20 - 31, The rel attribute only sets 'noopener' for external links,
which still leaks referrer data; update the logic in SidebarMenuNavItemRoot so
when componentType === 'externalLink' the rel value includes both 'noopener
noreferrer' (e.g., adjust the rel assignment referenced by rel and used on the
ListItemButton component) and keep target set to '_blank'; ensure the change
affects the ListItemButton props (component, href, target, rel) so external
links get "noopener noreferrer".


import { ToggleButtonProps } from './types'

export default function ToggleButton({ sx, onClick, Icon, ...other }: ToggleButtonProps) {
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The iconProps defined in ToggleButtonProps is not destructured or used.

The type definition includes iconProps?: Partial<SvgIconProps>, but the component doesn't accept or forward these props to IconComponent.

-export default function ToggleButton({ sx, onClick, Icon, ...other }: ToggleButtonProps) {
+export default function ToggleButton({ sx, onClick, Icon, iconProps, ...other }: ToggleButtonProps) {

And apply to IconComponent on line 45:

-      <IconComponent sx={{ fontSize: '20px', transform: `rotate(${deg})`, transition: 'all 0.25s linear',}} />
+      <IconComponent sx={{ fontSize: '20px', transform: `rotate(${deg})`, transition: 'transform 0.25s linear'}} {...iconProps} />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export default function ToggleButton({ sx, onClick, Icon, ...other }: ToggleButtonProps) {
export default function ToggleButton({ sx, onClick, Icon, iconProps, ...other }: ToggleButtonProps) {
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/index.tsx`
at line 10, ToggleButtonProps declares iconProps but ToggleButton doesn't accept
or forward them; update the ToggleButton function signature to destructure
iconProps from props (e.g., { sx, onClick, Icon, iconProps, ...other }) and then
pass those through to the rendered icon component (the Icon / IconComponent
usage) by spreading iconProps onto it (e.g., <Icon {...iconProps} />) so the SVG
props are applied; ensure the prop name matches ToggleButtonProps and types
remain intact.

Content?: ElementType
}
navGroup: NavGroupData
renderNav: (nav: NavItemData | NavListData | NavGroupData, key?: React.Key) => React.ReactNode
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's check the actual file content and imports
cat -n packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 630


🏁 Script executed:

# Also check if there are any TypeScript configuration files that might affect type resolution
fd tsconfig.json -o package.json | head -5

Repository: silverlogic/baseapp-frontend

Length of output: 215


🏁 Script executed:

# Search for similar React.Key and React.ReactNode patterns in the codebase to see how they're typically handled
rg -n "React\.(Key|ReactNode)" packages/components/ --type=ts --type=tsx -A 2 | head -40

Repository: silverlogic/baseapp-frontend

Length of output: 99


🏁 Script executed:

# Check the TypeScript configuration to see if React types are globally available
find . -name "tsconfig.json" -type f | head -3 | xargs cat

Repository: silverlogic/baseapp-frontend

Length of output: 1443


🏁 Script executed:

# Check how other files in the same directory handle React types
ls -la packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/

Repository: silverlogic/baseapp-frontend

Length of output: 295


🏁 Script executed:

# Search for other uses of React.Key and React.ReactNode across TypeScript files
rg "React\.(Key|ReactNode)" --type ts packages/components/ -A 1 | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 1635


🏁 Script executed:

# Check if React types are globally available by looking at the extended tsconfig
cat `@baseapp-frontend/tsconfig/lib.json` 2>/dev/null || find . -path "*/node_modules/@baseapp-frontend/tsconfig*" -name "lib.json" | head -1 | xargs cat 2>/dev/null || echo "Extended config not found in repo"

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Check how other .ts files that use React.ReactNode handle imports
cat -n packages/components/modules/navigations/web/Header/AccountMenu/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 786


🏁 Script executed:

# Check the other types.ts file that uses React.ReactNode
cat -n packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupRoot/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 430


🏁 Script executed:

# Check if there's a global type definition file that might provide React types
fd -e "d.ts" packages/components/ | head -10 | xargs -I {} sh -c 'echo "=== {} ===" && head -30 {}'

Repository: silverlogic/baseapp-frontend

Length of output: 457


🏁 Script executed:

# Check the base tsconfig that extends
find . -path "*/@baseapp-frontend/tsconfig*" -type d 2>/dev/null | head -5

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Let's check if React is available globally via tsconfig or ambient types
rg "declare.*React" --type ts --type tsx packages/ | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 99


🏁 Script executed:

# Check if there are any .d.ts files that declare React globally
find packages -name "*.d.ts" -type f 2>/dev/null | xargs cat 2>/dev/null | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 730


🏁 Script executed:

# Look for jsx config in tsconfig or babel config that might affect React availability
rg "jsx|lib.*react" -i packages/components/tsconfig.json packages/components/babel.config.js 2>/dev/null

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Check what compilerOptions are set in the base tsconfig by examining the actual package
find node_modules/@baseapp-frontend/tsconfig -name "*.json" 2>/dev/null | head -3 | xargs cat 2>/dev/null

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Let's check if TypeScript actually complains about this by looking for any build configuration
find packages/components -name "tsconfig.json" -type f -exec head -20 {} \;

Repository: silverlogic/baseapp-frontend

Length of output: 503


🏁 Script executed:

# Check if there's a jest config or other test setup that might reveal type errors
cat packages/components/jest.config.ts 2>/dev/null || echo "No jest config found"

Repository: silverlogic/baseapp-frontend

Length of output: 302


🏁 Script executed:

# Let's verify by checking if React is imported anywhere as a namespace in similar .ts files
rg "^import React" packages/components/modules/new-navigations/web/ --type ts

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Check the package.json to see React version and if there are any special configurations
cat packages/components/package.json | grep -A 5 -B 5 '"react"'

Repository: silverlogic/baseapp-frontend

Length of output: 479


🏁 Script executed:

# Check if there are any ESLint or TypeScript configuration files that might affect this
find packages/components -maxdepth 2 -name ".eslintrc*" -o -name "eslint.config*" | xargs cat 2>/dev/null | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 159


🏁 Script executed:

# Let's check the actual base tsconfig configuration that's being extended
find . -path "*node_modules/@baseapp-frontend/tsconfig*" -name "*.json" 2>/dev/null | head -5 | xargs cat 2>/dev/null

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Check if there's a types declaration that globally declares React
rg "declare.*namespace.*React|global.*React" --type ts 2>/dev/null | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Verify if similar pattern (using React.SomeType without importing React namespace) exists in .tsx files too
rg "React\.(Key|ReactNode|Component)" packages/components/ --type ts -l | head -10

Repository: silverlogic/baseapp-frontend

Length of output: 586


🏁 Script executed:

# Let's double-check the file once more - maybe React is imported in a way we missed
cat -n packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/types.ts | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 630


🏁 Script executed:

# Check if there's any automatic import mechanism via TypeScript paths
find packages/components -name "tsconfig.json" -exec grep -l "paths\|baseUrl" {} \; | xargs cat 2>/dev/null | grep -A 20 "paths\|baseUrl" | head -30

Repository: silverlogic/baseapp-frontend

Length of output: 464


🏁 Script executed:

# Check other .ts files that use React.ReactNode to see if they import React
for file in $(rg "React\.(Key|ReactNode)" packages/components/ --type ts -l); do
  echo "=== $file ==="
  head -5 "$file"
  echo ""
done

Repository: silverlogic/baseapp-frontend

Length of output: 1655


Import React namespace or use direct type imports.

React.Key and React.ReactNode on line 16 require the React namespace to be in scope. Either add a namespace import or import the types directly.

💡 Option 1: Import React namespace
-import { ElementType } from "react"
+import React, { ElementType } from "react"
💡 Option 2: Import types directly
-import { ElementType } from "react"
+import { ElementType, Key, ReactNode } from "react"
 import { NavGroupData, NavItemData, NavListData } from "../../types"
 
 // ...
 
-  renderNav: (nav: NavItemData | NavListData | NavGroupData, key?: React.Key) => React.ReactNode
+  renderNav: (nav: NavItemData | NavListData | NavGroupData, key?: Key) => ReactNode
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavGroup/types.ts`
at line 16, The renderNav type uses React.Key and React.ReactNode but the React
namespace isn't imported; fix by either adding a namespace import (import React
from 'react') so React.Key/React.ReactNode resolve, or change the signature to
use direct type imports (import type { Key, ReactNode } from 'react' and update
renderNav to use Key and ReactNode). Update the types file where renderNav is
declared to include one of these imports and ensure the function signature
references the imported types (renderNav).

@priscilladeroode priscilladeroode force-pushed the feature/sidebar-menu-improvement branch from 5485352 to ed0e84f Compare January 28, 2026 00:41
Copy link

@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: 7

🤖 Fix all issues with AI agents
In `@packages/components/modules/new-navigations/web/createNavRenderer.tsx`:
- Around line 24-30: The key fallback for NavList and NavItem uses title which
can collide; change the key expression in the createNavRenderer render branches
so it prefers the optional path before title (e.g., use key ?? listNav.path ??
listNav.title and key ?? itemNav.path ?? itemNav.title) to give a more stable
React key for NavList and NavItem components while preserving the existing key
override.

In `@packages/components/modules/new-navigations/web/NavigationLayout/index.tsx`:
- Around line 1-5: This file calls the hook useUISettings inside the
NavigationLayout component and must be marked as a client component; add the
'use client' directive as the very first line of
packages/components/modules/new-navigations/web/NavigationLayout/index.tsx
(before any imports) so hooks like useUISettings work correctly when this
exported component is imported into server components—mirror the approach used
in SidebarNavigation and MainContainer.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupHeader/index.tsx`:
- Around line 19-33: The Header styling in SidebarMenuNavGroupHeader wrongly
always uses cursor: 'pointer' and hover color and ignores the disabled prop;
update the component so cursor is 'pointer' only when an onClick handler exists
(otherwise 'default'), and apply the disabled prop to the root element by adding
aria-disabled="true" when disabled, using a muted color and removing the
'&:hover' color change and pointer cursor (use 'default' or 'not-allowed' when
disabled); implement these conditional styles in the sx object and ensure any
click handler is guarded by the disabled flag (refer to
SidebarMenuNavGroupHeader, the sx prop, the disabled prop and the onClick
usage).

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx`:
- Line 7: The SidebarMenuRoot component imports NAV_WIDTH from the old
navigations module; update the import in SidebarMenuRoot/index.tsx to use the
NAV_WIDTH exported by the new-navigations package's local constants module
instead of '../../../../navigations/web/constants' so the component depends on
its local new-navigations constants and avoids cross-module coupling.
- Line 19: SidebarMenuRoot currently destructures DrawerProps but doesn't use
them; either remove that prop or forward it to the Drawer — update the
SidebarMenuRoot component to spread the received DrawerProps onto the Drawer
element (e.g., <Drawer {...DrawerProps}>) so any passed drawer-specific props
are applied, or eliminate DrawerProps from the destructuring if unused; locate
the destructuring in SidebarMenuRoot and ensure the Drawer component receives
the forwarded props.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/types.ts`:
- Around line 8-12: The SidebarMenuRootProps type narrows onClose to () => void
which breaks compatibility with MUI's DrawerProps; update the onClose
declaration in SidebarMenuRootProps to use the full MUI signature by typing it
as NonNullable<DrawerProps['onClose']> (keep other props like open, collapsible
and ToggleButton/NavToggleButton unchanged) so handlers that expect (event,
reason) are accepted.

In
`@packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/types.ts`:
- Around line 5-9: The ToggleButtonProps currently narrows onClick to
VoidFunction which conflicts with IconButtonProps; update the onClick signature
to accept the mouse event (e.g. use IconButtonProps['onClick'] or
React.MouseEventHandler<HTMLButtonElement>) or remove the onClick override so
the interface inherits the parent type; ensure the ToggleButton component
implementation (which discards the event) still compiles by accepting the event
parameter and ignoring it.
🧹 Nitpick comments (4)
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupRoot/index.tsx (1)

1-1: Remove unused import PropsWithChildren.

PropsWithChildren is imported but not used anywhere in this file.

🔧 Suggested fix
-import { FC, PropsWithChildren, useCallback, useState } from 'react'
+import { FC, useCallback, useState } from 'react'
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupHeader/index.tsx (1)

15-40: Remove unnecessary Fragment wrapper.

The Fragment (<>...</>) wrapping is not needed since there's only a single ListSubheader child element.

♻️ Suggested fix
-  return (
-    <>
-      <ListSubheader
-        disableGutters
-        disableSticky
-        sx={{
-          ...
-        }}
-        {...props}
-      >
-        {title}
-      </ListSubheader>
-    </>
-  )
+  return (
+    <ListSubheader
+      disableGutters
+      disableSticky
+      sx={{
+        ...
+      }}
+      {...props}
+    >
+      {title}
+    </ListSubheader>
+  )
packages/components/modules/new-navigations/web/SidebarNavigation/DefaultNavList/index.tsx (1)

6-33: Reuse filteredChildren and simplify hasChildren.

This avoids double filtering and keeps hasChildren strictly boolean.

♻️ Proposed refactor
-  const filteredChildren = navList.children?.filter((child) => !child.hide)
-  const hasChildren = filteredChildren?.length && filteredChildren.length > 0
+  const filteredChildren = navList.children?.filter((child) => !child.hide) ?? []
+  const hasChildren = filteredChildren.length > 0
@@
-        <ListRoot open={open} sx={{ paddingX: (theme) => theme.spacing(2) }}>
-          {navList.children?.filter((child) => !child.hide).map((child) => (
+        <ListRoot open={open} sx={{ paddingX: (theme) => theme.spacing(2) }}>
+          {filteredChildren.map((child) => (
             <ListItem.Root key={child.title} {...child} >
               <ListItem.Icon Icon={child.icon} />
               <ListItem.Title title={child.title} caption={child.caption} />
             </ListItem.Root>
           ))}
         </ListRoot>
packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx (1)

44-68: Unnecessary React fragment.

The fragment wrapper (<>...</>) around the single Box element is superfluous and can be removed.

♻️ Proposed simplification
   return (
-    <>
-      <Box
-        sx={{
-          flexShrink: { lg: 0 },
-          width: { lg: NAV_WIDTH.VERTICAL },
-          display: { xs: 'none', lg: 'flex' },
-        }}
-      >
-        <Stack
-          {...ContainerProps}
-          sx={{
-            height: 1,
-            position: 'fixed',
-            width: NAV_WIDTH.VERTICAL,
-            borderRight: (theme) => `solid 1px ${theme.palette.divider}`,
-            paddingX: (theme) => theme.spacing(2),
-            ...ContainerProps?.sx,
-          }}
-        >
-          {collapsible && <ToggleButton {...ToggleButtonProps} />}
-          {children}
-        </Stack>
-      </Box>
-    </>
+    <Box
+      sx={{
+        flexShrink: { lg: 0 },
+        width: { lg: NAV_WIDTH.VERTICAL },
+        display: { xs: 'none', lg: 'flex' },
+      }}
+    >
+      <Stack
+        {...ContainerProps}
+        sx={{
+          height: 1,
+          position: 'fixed',
+          width: NAV_WIDTH.VERTICAL,
+          borderRight: (theme) => `solid 1px ${theme.palette.divider}`,
+          paddingX: (theme) => theme.spacing(2),
+          ...ContainerProps?.sx,
+        }}
+      >
+        {collapsible && <ToggleButton {...ToggleButtonProps} />}
+        {children}
+      </Stack>
+    </Box>
   )

Comment on lines 24 to 30
case NAV_DATA_TYPE.list: {
const listNav = nav as NavListData
return <NavList key={key ?? listNav.title} navList={listNav} slots={slots} />
}
case NAV_DATA_TYPE.item: {
const itemNav = nav as NavItemData
return <NavItem key={key ?? itemNav.title} {...itemNav} slots={slots} />
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Search for NavListData and NavItemData type definitions
rg "type NavListData|interface NavListData|type NavItemData|interface NavItemData" -A 10

Repository: silverlogic/baseapp-frontend

Length of output: 1783


🏁 Script executed:

# Find the file and examine its imports and context
head -50 packages/components/modules/new-navigations/web/createNavRenderer.tsx

Repository: silverlogic/baseapp-frontend

Length of output: 1636


🏁 Script executed:

# Search for NAV_DATA_TYPE definition to understand the data structures
rg "NAV_DATA_TYPE" -B 2 -A 2

Repository: silverlogic/baseapp-frontend

Length of output: 2465


Prefer path as a stable key fallback for list and item nodes. Titles can collide and cause React reconciliation issues. Since path is available but optional on both NavListData and NavItemData, fall back to it before using title.

Suggested fix
-            return <NavList key={key ?? listNav.title} navList={listNav} slots={slots} />
+            return <NavList key={key ?? listNav.path ?? listNav.title} navList={listNav} slots={slots} />
...
-            return <NavItem key={key ?? itemNav.title} {...itemNav} slots={slots} />
+            return <NavItem key={key ?? itemNav.path ?? itemNav.title} {...itemNav} slots={slots} />
🤖 Prompt for AI Agents
In `@packages/components/modules/new-navigations/web/createNavRenderer.tsx` around
lines 24 - 30, The key fallback for NavList and NavItem uses title which can
collide; change the key expression in the createNavRenderer render branches so
it prefers the optional path before title (e.g., use key ?? listNav.path ??
listNav.title and key ?? itemNav.path ?? itemNav.title) to give a more stable
React key for NavList and NavItem components while preserving the existing key
override.

Comment on lines 1 to 5
import { PropsWithChildren } from 'react'

import { useUISettings } from '@baseapp-frontend/design-system/hooks/web'

import SidebarNavigation from '../SidebarNavigation'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the file exists and read its content
file_path="packages/components/modules/new-navigations/web/NavigationLayout/index.tsx"
echo "=== Checking file content ==="
if [ -f "$file_path" ]; then
    wc -l "$file_path"
    echo ""
    cat -n "$file_path"
else
    echo "File not found at $file_path"
fi

Repository: silverlogic/baseapp-frontend

Length of output: 1194


🏁 Script executed:

#!/bin/bash
# Check for 'use client' directive usage in similar files
echo "=== Checking for 'use client' in similar component files ==="
rg "'use client'" packages/components/modules/new-navigations/ -n -g '*.tsx'

Repository: silverlogic/baseapp-frontend

Length of output: 327


🏁 Script executed:

#!/bin/bash
# Find where NavigationLayout is imported
echo "=== Finding imports of NavigationLayout ==="
rg "NavigationLayout" --type tsx -n -C 2

Repository: silverlogic/baseapp-frontend

Length of output: 160


🏁 Script executed:

#!/bin/bash
# Check Next.js configuration to understand project setup
echo "=== Checking Next.js setup ==="
if [ -f "package.json" ]; then
    jq '.dependencies.next // .devDependencies.next // "not found"' package.json
fi
if [ -f "next.config.js" ] || [ -f "next.config.mjs" ] || [ -f "next.config.ts" ]; then
    echo "Next.js config file found"
fi

Repository: silverlogic/baseapp-frontend

Length of output: 114


🏁 Script executed:

#!/bin/bash
# Correct the file type flag and search for NavigationLayout imports
echo "=== Finding imports of NavigationLayout ==="
rg "NavigationLayout" -t typescript -n -C 2

Repository: silverlogic/baseapp-frontend

Length of output: 167


🏁 Script executed:

#!/bin/bash
# Double-check Next.js in package.json more directly
echo "=== Checking for Next.js in dependencies ==="
cat package.json | grep -A 20 '"dependencies"' | head -30
echo ""
cat package.json | grep -A 20 '"devDependencies"' | head -30

Repository: silverlogic/baseapp-frontend

Length of output: 628


🏁 Script executed:

#!/bin/bash
# Search for NavigationLayout without file type specification
echo "=== Finding imports of NavigationLayout ==="
rg "NavigationLayout" -n -C 2 | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 4670


🏁 Script executed:

#!/bin/bash
# Check if this is a Next.js project by looking at apps structure
echo "=== Checking apps directory ==="
ls -la apps/ 2>/dev/null || echo "No apps directory"
echo ""
echo "=== Looking for next.config files ==="
find . -name "next.config.*" -type f 2>/dev/null | head -10
echo ""
echo "=== Checking for Next.js in workspace packages ==="
rg '"next":' . --no-heading | head -10

Repository: silverlogic/baseapp-frontend

Length of output: 591


🏁 Script executed:

#!/bin/bash
# Check the SidebarNavigation file that has 'use client' to confirm pattern
echo "=== Checking SidebarNavigation for comparison ==="
cat packages/components/modules/new-navigations/web/SidebarNavigation/index.tsx | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 699


Add 'use client' directive to use hooks in Next.js app-dir.

useUISettings() is called on line 18 and requires client-side rendering. Since this component is exported as a public API and could be imported into server components, add the 'use client' directive at the top. This aligns with sibling components like SidebarNavigation and MainContainer, which already have this directive.

Suggested change
+'use client'
+
 import { PropsWithChildren } from 'react'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { PropsWithChildren } from 'react'
import { useUISettings } from '@baseapp-frontend/design-system/hooks/web'
import SidebarNavigation from '../SidebarNavigation'
'use client'
import { PropsWithChildren } from 'react'
import { useUISettings } from '@baseapp-frontend/design-system/hooks/web'
import SidebarNavigation from '../SidebarNavigation'
🤖 Prompt for AI Agents
In `@packages/components/modules/new-navigations/web/NavigationLayout/index.tsx`
around lines 1 - 5, This file calls the hook useUISettings inside the
NavigationLayout component and must be marked as a client component; add the
'use client' directive as the very first line of
packages/components/modules/new-navigations/web/NavigationLayout/index.tsx
(before any imports) so hooks like useUISettings work correctly when this
exported component is imported into server components—mirror the approach used
in SidebarNavigation and MainContainer.

Comment on lines 19 to 33
sx={{
fontSize: 11,
cursor: 'pointer',
typography: 'overline',
display: 'inline-flex',
color: 'text.disabled',
mb: (theme) => theme.spacing(0.5),
p: (theme) => theme.spacing(2, 1, 1, 1.5),
transition: (theme) =>
theme.transitions.create(['color'], {
duration: theme.transitions.duration.shortest,
}),
'&:hover': {
color: 'text.primary',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading cursor: 'pointer' on a non-interactive element and missing disabled state handling.

Two accessibility/UX concerns:

  1. Pointer cursor without interactivity: The header has cursor: 'pointer' and hover effects, but there's no onClick handler. This misleads users into thinking the element is clickable. If the header isn't meant to be interactive, use cursor: 'default'.

  2. disabled prop is ignored: The disabled prop is accepted but not applied. When disabled, the component should:

    • Apply aria-disabled="true" for screen readers
    • Remove hover effects and set cursor: 'default' or 'not-allowed'
    • Apply muted styling to indicate the disabled state
🛠️ Suggested fix applying the disabled state
 const SidebarMenuNavGroupHeader: FC<SidebarMenuNavGroupHeaderProps> = ({
   children,
   title,
   disabled = false,
   ...props
 }) => {
   return (
     <ListSubheader
       disableGutters
       disableSticky
+      aria-disabled={disabled}
       sx={{
         fontSize: 11,
-        cursor: 'pointer',
+        cursor: disabled ? 'default' : 'pointer',
         typography: 'overline',
         display: 'inline-flex',
         color: 'text.disabled',
         mb: (theme) => theme.spacing(0.5),
         p: (theme) => theme.spacing(2, 1, 1, 1.5),
         transition: (theme) =>
           theme.transitions.create(['color'], {
             duration: theme.transitions.duration.shortest,
           }),
-        '&:hover': {
-          color: 'text.primary',
-        },
+        ...(!disabled && {
+          '&:hover': {
+            color: 'text.primary',
+          },
+        }),
+        ...(disabled && {
+          opacity: 0.5,
+        }),
         ...props.sx,
       }}
       {...props}
     >
       {title}
+      {children}
     </ListSubheader>
   )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sx={{
fontSize: 11,
cursor: 'pointer',
typography: 'overline',
display: 'inline-flex',
color: 'text.disabled',
mb: (theme) => theme.spacing(0.5),
p: (theme) => theme.spacing(2, 1, 1, 1.5),
transition: (theme) =>
theme.transitions.create(['color'], {
duration: theme.transitions.duration.shortest,
}),
'&:hover': {
color: 'text.primary',
},
const SidebarMenuNavGroupHeader: FC<SidebarMenuNavGroupHeaderProps> = ({
children,
title,
disabled = false,
...props
}) => {
return (
<ListSubheader
disableGutters
disableSticky
aria-disabled={disabled}
sx={{
fontSize: 11,
cursor: disabled ? 'default' : 'pointer',
typography: 'overline',
display: 'inline-flex',
color: 'text.disabled',
mb: (theme) => theme.spacing(0.5),
p: (theme) => theme.spacing(2, 1, 1, 1.5),
transition: (theme) =>
theme.transitions.create(['color'], {
duration: theme.transitions.duration.shortest,
}),
...(!disabled && {
'&:hover': {
color: 'text.primary',
},
}),
...(disabled && {
opacity: 0.5,
}),
...props.sx,
}}
{...props}
>
{title}
{children}
</ListSubheader>
)
}
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuNavGroup/SidebarMenuNavGroupHeader/index.tsx`
around lines 19 - 33, The Header styling in SidebarMenuNavGroupHeader wrongly
always uses cursor: 'pointer' and hover color and ignores the disabled prop;
update the component so cursor is 'pointer' only when an onClick handler exists
(otherwise 'default'), and apply the disabled prop to the root element by adding
aria-disabled="true" when disabled, using a muted color and removing the
'&:hover' color change and pointer cursor (use 'default' or 'not-allowed' when
disabled); implement these conditional styles in the sx object and ensure any
click handler is guarded by the disabled flag (refer to
SidebarMenuNavGroupHeader, the sx prop, the disabled prop and the onClick
usage).


import { Box, Drawer, Stack } from '@mui/material'

import { NAV_WIDTH } from '../../../../navigations/web/constants'
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Importing from the wrong module.

This component lives in new-navigations but imports NAV_WIDTH from the old navigations/web/constants. According to the relevant code snippets, packages/components/modules/new-navigations/web/constants.ts already exports the same constant. Use the local module to avoid cross-module dependencies.

🛠️ Proposed fix
-import { NAV_WIDTH } from '../../../../navigations/web/constants'
+import { NAV_WIDTH } from '../../constants'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { NAV_WIDTH } from '../../../../navigations/web/constants'
import { NAV_WIDTH } from '../../constants'
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx`
at line 7, The SidebarMenuRoot component imports NAV_WIDTH from the old
navigations module; update the import in SidebarMenuRoot/index.tsx to use the
NAV_WIDTH exported by the new-navigations package's local constants module
instead of '../../../../navigations/web/constants' so the component depends on
its local new-navigations constants and avoids cross-module coupling.

ToggleButton = NavToggleButton,
ToggleButtonProps,
collapsible = true,
DrawerProps,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

DrawerProps is destructured but never used.

The prop is accepted and destructured but not spread onto the Drawer component. Either remove it from the destructuring or apply it to the Drawer.

🛠️ Proposed fix to spread DrawerProps
       <Drawer
         open={open}
         onClose={onClose}
         PaperProps={{
           sx: {
             width: 250,
             paddingX: 2,
           },
           ...PaperProps,
         }}
+        {...DrawerProps}
         {...props}
       >
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx`
at line 19, SidebarMenuRoot currently destructures DrawerProps but doesn't use
them; either remove that prop or forward it to the Drawer — update the
SidebarMenuRoot component to spread the received DrawerProps onto the Drawer
element (e.g., <Drawer {...DrawerProps}>) so any passed drawer-specific props
are applied, or eliminate DrawerProps from the destructuring if unused; locate
the destructuring in SidebarMenuRoot and ensure the Drawer component receives
the forwarded props.

Comment on lines 8 to 12
export interface SidebarMenuRootProps extends PropsWithChildren<DrawerProps> {
open: boolean
onClose: () => void
collapsible?: boolean
ToggleButton?: typeof NavToggleButton
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the file mentioned in the review comment
find . -type f -name "types.ts" | grep -i "sidebarmenuroot" | head -5

Repository: silverlogic/baseapp-frontend

Length of output: 158


🏁 Script executed:

# Also search for the file more broadly
fd "SidebarMenuRoot" -t f | head -10

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Check package.json to see MUI version
find . -name "package.json" -type f | xargs grep -l "@mui" | head -3

Repository: silverlogic/baseapp-frontend

Length of output: 173


🏁 Script executed:

# Look for types.ts in the path mentioned
fd "types.ts" -p "new-navigations"

Repository: silverlogic/baseapp-frontend

Length of output: 174


🏁 Script executed:

# Read the types file mentioned in the review
cat -n ./packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 753


🏁 Script executed:

# Check the MUI version in packages/components/package.json
cat ./packages/components/package.json | grep -A 5 -B 5 "@mui"

Repository: silverlogic/baseapp-frontend

Length of output: 749


🏁 Script executed:

# Search for DrawerProps usage or imports in the codebase
rg "DrawerProps" --type typescript --type tsx -A 2 -B 2 | head -30

Repository: silverlogic/baseapp-frontend

Length of output: 106


🏁 Script executed:

# Find the catalog file to see the MUI version
find . -name "pnpm-workspace.yaml" -o -name "package.json" | xargs grep -l "catalog:" | head -3

Repository: silverlogic/baseapp-frontend

Length of output: 160


🏁 Script executed:

# Search for DrawerProps usage with correct flags
rg "DrawerProps" -A 2 -B 2 | head -40

Repository: silverlogic/baseapp-frontend

Length of output: 4085


🏁 Script executed:

# Check where onClose is used in the codebase to see if this causes issues
rg "onClose" -t ts -t tsx --type-list | grep -E "^\s*(onClose|DrawerProps)" | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 461


🏁 Script executed:

# Look for the pnpm catalog definition
fd "pnpm-workspace.yaml" -o "pnpm-lock.yaml" | head -3

Repository: silverlogic/baseapp-frontend

Length of output: 219


🏁 Script executed:

# Check the root package.json for MUI catalog version
cat ./package.json | grep -A 50 "catalog:" | grep -E "material-ui|@mui"

Repository: silverlogic/baseapp-frontend

Length of output: 54


🏁 Script executed:

# Search for how SidebarMenuRoot uses onClose
rg "SidebarMenuRoot" -A 5 -B 5 | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 5330


🏁 Script executed:

# Check if there's a pnpm catalog file
cat ./pnpm-workspace.yaml 2>/dev/null || cat ./package.json | grep -A 100 "pnpmConfig\|catalog" | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 4778


🏁 Script executed:

# Check the SidebarMenuRoot implementation to see how onClose is used
cat -n ./packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/index.tsx | head -60

Repository: silverlogic/baseapp-frontend

Length of output: 1843


🏁 Script executed:

# Search for how onClose is passed to Drawer component
rg "onClose" -B 2 -A 2 | grep -A 3 -B 3 "SidebarMenuRoot"

Repository: silverlogic/baseapp-frontend

Length of output: 2178


🌐 Web query:

MUI 5.18.0 Drawer component onClose prop type signature

💡 Result:

In MUI v5.18.0, Drawer’s onClose matches Modal’s onClose and has the signature:

onClose?: (event: {}, reason: 'backdropClick' | 'escapeKeyDown') => void;

Docs describe it as function(event: object, reason: string) => void, with reason being "escapeKeyDown" or "backdropClick". [1][2]

Sources: [1] [2]


Align onClose type with MUI DrawerProps.

The narrowing of onClose to () => void breaks type compatibility with MUI's Drawer component. MUI's DrawerProps.onClose includes event and reason parameters: (event: {}, reason: 'backdropClick' | 'escapeKeyDown') => void. Handlers that accept these parameters will be rejected when passed to SidebarMenuRootProps.

Use NonNullable<DrawerProps['onClose']> to preserve the full MUI signature while making the prop required:

Suggested fix
 export interface SidebarMenuRootProps extends PropsWithChildren<DrawerProps> {
   open: boolean
-  onClose: () => void
+  onClose: NonNullable<DrawerProps['onClose']>
   collapsible?: boolean
   ToggleButton?: typeof NavToggleButton
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface SidebarMenuRootProps extends PropsWithChildren<DrawerProps> {
open: boolean
onClose: () => void
collapsible?: boolean
ToggleButton?: typeof NavToggleButton
export interface SidebarMenuRootProps extends PropsWithChildren<DrawerProps> {
open: boolean
onClose: NonNullable<DrawerProps['onClose']>
collapsible?: boolean
ToggleButton?: typeof NavToggleButton
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/SidebarMenuRoot/types.ts`
around lines 8 - 12, The SidebarMenuRootProps type narrows onClose to () => void
which breaks compatibility with MUI's DrawerProps; update the onClose
declaration in SidebarMenuRootProps to use the full MUI signature by typing it
as NonNullable<DrawerProps['onClose']> (keep other props like open, collapsible
and ToggleButton/NavToggleButton unchanged) so handlers that expect (event,
reason) are accepted.

Comment on lines 5 to 9
export interface ToggleButtonProps extends IconButtonProps {
onClick?: VoidFunction
Icon?: FC<SvgIconProps>
iconProps?: Partial<SvgIconProps>
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's look at the file in question
cat -n packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 424


🏁 Script executed:

# Search for IconButtonProps imports in the codebase
rg "IconButtonProps" packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/ -A 2 -B 2

Repository: silverlogic/baseapp-frontend

Length of output: 897


🏁 Script executed:

# Check what MUI exports for IconButtonProps and where it comes from
rg "from.*@mui" packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/types.ts

Repository: silverlogic/baseapp-frontend

Length of output: 183


🏁 Script executed:

# Search for VoidFunction type definition in the codebase
rg "VoidFunction" packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/ -B 2 -A 2

Repository: silverlogic/baseapp-frontend

Length of output: 630


🏁 Script executed:

# Look at the entire ToggleButton directory structure
find packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton -type f -name "*.ts*" | head -20

Repository: silverlogic/baseapp-frontend

Length of output: 236


🏁 Script executed:

# Check the ToggleButton implementation
cat -n packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/index.tsx

Repository: silverlogic/baseapp-frontend

Length of output: 1948


🏁 Script executed:

# Let's also check if there are any usages of ToggleButton in the codebase
rg "ToggleButton" packages/components/modules/new-navigations/web/SidebarMenu/ -A 3 -B 1 | head -50

Repository: silverlogic/baseapp-frontend

Length of output: 4753


🏁 Script executed:

# Search for how onClick is used in the ToggleButton component
rg "onClick" packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/ -B 2 -A 2

Repository: silverlogic/baseapp-frontend

Length of output: 2052


Avoid narrowing onClick from IconButtonProps.
Redefining onClick as VoidFunction creates a type incompatibility. MUI's IconButtonProps expects onClick to receive a MouseEvent parameter, but VoidFunction accepts no arguments. This violates type substitutability and will cause type errors when the component is used in contexts expecting IconButtonProps.

The implementation intentionally strips the event (line 20-25), so either remove the onClick override to use the parent type, or accept the event parameter in your signature:

Suggested fix
 export interface ToggleButtonProps extends IconButtonProps {
-  onClick?: VoidFunction
+  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
   Icon?: FC<SvgIconProps>
   iconProps?: Partial<SvgIconProps>
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface ToggleButtonProps extends IconButtonProps {
onClick?: VoidFunction
Icon?: FC<SvgIconProps>
iconProps?: Partial<SvgIconProps>
}
export interface ToggleButtonProps extends IconButtonProps {
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void
Icon?: FC<SvgIconProps>
iconProps?: Partial<SvgIconProps>
}
🤖 Prompt for AI Agents
In
`@packages/components/modules/new-navigations/web/SidebarMenu/ToggleButton/types.ts`
around lines 5 - 9, The ToggleButtonProps currently narrows onClick to
VoidFunction which conflicts with IconButtonProps; update the onClick signature
to accept the mouse event (e.g. use IconButtonProps['onClick'] or
React.MouseEventHandler<HTMLButtonElement>) or remove the onClick override so
the interface inherits the parent type; ensure the ToggleButton component
implementation (which discards the event) still compiles by accepting the event
parameter and ignoring it.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 9, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
8.6% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Copy link

@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: 19

🤖 Fix all issues with AI agents
In
`@packages/components/modules/navigations-v2/web/__shared__/MainContainer/index.tsx`:
- Around line 15-35: The BoxProps spread currently comes after component="main"
causing any component prop in BoxProps to override the semantic main landmark;
update the three JSX returns in MainContainer so the spread of BoxProps comes
before component="main" (i.e., <NavCenteredContainer {...BoxProps}
component="main" ...>, same for NavHorizontalContainer and NavVerticalContainer)
so component="main" always wins (alternatively filter out component from
BoxProps, but apply the spread-order change to NavCenteredContainer,
NavHorizontalContainer and NavVerticalContainer).

In
`@packages/components/modules/navigations-v2/web/__shared__/MainContainer/styled.tsx`:
- Around line 17-30: The up('lg') breakpoint in NavHorizontalContainer wrongly
reuses NAV_PADDING_DOWN_TO_LG.horizontal.top; change it to
NAV_PADDING_UP_TO_LG.horizontal.top so the large-screen override matches the
intended constant (similar to how paddingBottom uses NAV_PADDING_UP_TO_LG) —
update the object inside styled(CommonContainer) where
theme.breakpoints.up('lg') is defined to reference
NAV_PADDING_UP_TO_LG.horizontal.top instead of
NAV_PADDING_DOWN_TO_LG.horizontal.top.

In
`@packages/components/modules/navigations-v2/web/__shared__/NavigationDrawer/index.tsx`:
- Around line 10-17: The PaperProps spreading currently overwrites the default
sx because ...PaperProps is spread after defining sx; update the merge so the
consumer sx is merged with the defaults instead of replacing them: keep the
default sx object (width: NAV_WIDTH.VERTICAL, height, paddingX) and then merge
in any consumer PaperProps.sx (e.g., sx: { ...defaultSx, ...(PaperProps?.sx) })
while still spreading the rest of PaperProps (e.g., { ...PaperProps, sx:
mergedSx }) so consumers can override specific keys but not drop the defaults;
apply this change where PaperProps is constructed in NavigationDrawer (reference
PaperProps, sx, NAV_WIDTH.VERTICAL).

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/index.tsx`:
- Line 27: The renderer returned by createNavRenderer(slots ?? {}, slotProps ??
{}) is being recreated for every item in navData.map; hoist it once in
SidebarMenuContent by calling createNavRenderer(slots ?? {}, slotProps ?? {})
into a const (e.g., const renderNav = createNavRenderer(slots ?? {}, slotProps
?? {})) before the JSX/return and then use navData?.map((nav, idx) =>
renderNav(nav, idx)) so the closure is constructed only once per render.

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavList/index.tsx`:
- Around line 17-18: Replace the duplicate filtering of navList.children in the
render with the precomputed filteredChildren: use filteredChildren (and
hasChildren) instead of calling navList.children?.filter(...) again within the
render loop in SidebarMenuContent/NavList/index.tsx — update any places that
currently re-filter to reference filteredChildren and ensure null/undefined
checks (e.g., guarded map/rendering only when hasChildren is truthy) so
filtering logic is centralized and not duplicated.

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavList/types.ts`:
- Around line 7-19: NavListSlots has a type mismatch: update the Header and
ListItem slot types to point to the .Root subcomponent (i.e., change Header?:
typeof SidebarMenuNavItem to Header?: typeof SidebarMenuNavItem.Root and
ListItem?: typeof SidebarMenuNavItem to ListItem?: typeof
SidebarMenuNavItem.Root) so they align with NavListSlotProps (which uses
ComponentProps<typeof SidebarMenuNavItem.Root>) and with how the component
actually spreads props into Header.Root and ListItem.Root in SidebarMenuNavGroup
and SidebarMenuNavItem usage.

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/utils.tsx`:
- Around line 24-34: The code currently uses a static fallback key 'group' for
NavGroup in the NAV_DATA_TYPE.group branch, causing duplicate React keys when
multiple NavGroupData items lack subheader and key; update the component to use
a unique fallback (preferably an index supplied by the caller) instead of the
static string: have the caller pass an index into renderNav (e.g.,
renderNav(nav, i)) and then use that index as the fallback for the key in the
NavGroup render (replace the 'group' fallback with the provided index or a
deterministic unique id derived from groupNav); ensure you update the NavGroup
invocation here (the branch handling NAV_DATA_TYPE.group and the key expression)
to use that index/unique id rather than the literal 'group'.

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuHeader/index.tsx`:
- Around line 10-12: The destructuring in SidebarMenuHeader (component
SidebarMenuHeader) can yield Logo = undefined at runtime because slots is
optional; fix by providing a runtime default Logo component instead of relying
on the type cast: create or import a DefaultLogo component and change the
destructuring so Logo defaults to DefaultLogo (keep LogoContainer =
DefaultLogoContainer), remove the unsafe as NonUndefined cast, and ensure
SidebarMenuHeaderProps typing remains compatible (or alternatively make
slots.required in the props type if you prefer enforcing via types).

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuRoot/index.tsx`:
- Line 33: Remove the debug console.log in SidebarMenuRoot and wire the existing
isSidebarCollapsed value into the UI: delete the line "console.log('use
isSidebarCollapsed to adaptthe components below', isSidebarCollapsed)" and
update SidebarMenuRoot (and/or its immediate children) to consume
isSidebarCollapsed (e.g., by toggling className, width, collapsed CSS modifier,
or aria-expanded) so the collapsed state actually affects rendering; ensure any
props or callbacks passed down (from SidebarMenuRoot to child components)
reflect the collapsed state and remove any unused read-only variables.
- Around line 26-31: The drawer is using an incorrect prop for dismissal: in
SidebarMenuRoot where it returns <NavigationDrawer open={isDrawerOpen}
onClick={onDrawerToggle} {...NavigationDrawerProps}>, replace the onClick prop
with onClose so MUI's Drawer behavior is used; update the prop to
onClose={onDrawerToggle} (preserving isDrawerOpen, NavigationDrawerProps,
lgDown, onDrawerToggle, and children) so backdrop clicks and Escape key
dismissals work correctly.

In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/ToggleButton/index.tsx`:
- Around line 19-44: The IconButton spreads {...props} after the explicit sx
prop which allows a caller's props.sx to completely override the merged styles;
fix by either destructuring sx from props (const { sx, ...rest } = props) and
then merging caller sx into the existing sx object, or by moving {...props}
before the sx prop on the IconButton so the component's sx (including p, height,
width, top, right, border, bgBlur, hover) is applied last; locate the IconButton
usage in ToggleButton (referencing IconButton, props.sx, and the ChevronIcon/
settings.collapsedSidebar) and update accordingly.

In `@packages/components/modules/navigations-v2/web/__shared__/useActiveLink.ts`:
- Around line 10-13: The deepActive calculation (deepActive =
pathname.includes(path)) causes the root path (path === "/") to match every
route; update useActiveLink logic so that when path === "/" you only mark active
if pathname === "/", otherwise use a prefix check: keep normalActive as
(pathname === path) and replace deepActive with a conditional like (path === "/"
? pathname === "/" : pathname.startsWith(path)), then return deep ? deepActive :
normalActive so the root nav item no longer appears active on all pages.

In `@packages/components/modules/navigations-v2/web/NavigationLayout/index.tsx`:
- Around line 14-25: The LayoutComponent lookup in NavigationLayout can be
undefined when settings?.themeLayout is missing or not one of the expected
ThemeLayoutV2 values; update the component to guard and provide a safe fallback:
compute LayoutComponent from the map ({ sidebar, vertical, horizontal }) and if
it's falsy, either default to a known component (e.g., SidebarLayout) or return
a safe fallback UI (or null) while logging a concise error; ensure you also
avoid the unsafe type cast of settings?.themeLayout by validating it against the
allowed keys before using it and apply the chosen fallback when
assigning/returning LayoutComponent so the render never attempts to render
undefined.

In
`@packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavGroup/Header/index.tsx`:
- Around line 7-31: The Header component spreads {...props} after building an sx
object, which lets a caller-provided sx in props overwrite your merged defaults;
fix by destructuring sx from props in the Header signature (e.g., ({ title, sx,
...props })) and then pass a merged sx to ListSubheader that combines your
default sx with the caller's sx (e.g., defaultSx + sx) while still spreading the
remaining {...props} so consumer props don't clobber the merged sx; update
references to props.sx in the sx merge to use the destructured sx.

In
`@packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavItem/Root/index.tsx`:
- Around line 9-46: The Root component’s inline sx is being overwritten because
sx isn’t pulled out of props before spreading; destructure sx from the incoming
props in the Root signature (e.g., const Root = ({..., sx, ...props}) => { ...
}) and then merge the component’s computed sx with the consumer sx when
rendering ListItemButton (combine as an array or compose functions so the
active/default styles defined for ListItemButton are preserved and consumer sx
augments them), ensuring ListItemButton retains its active styling logic
(active, svg, .label) while allowing consumer overrides.

In
`@packages/design-system/components/web/logos/LogoContainer/__storybook__/LogoContainer.mdx`:
- Line 7: The MDX heading is incorrect—replace the "## Logo" heading with a
heading matching the component name used in the Meta (e.g., "## LogoContainer"
or "## Logo Container") so the documentation title aligns with the component;
update the heading in the LogoContainer story file (the MDX with Meta for
LogoContainer) to match the Meta title.
- Around line 33-41: The example in the LogoContainer story imports and renders
the wrong component: replace the import and usage of Logo with LogoContainer so
the story demonstrates the documented component; specifically update the import
to import LogoContainer from '@baseapp-frontend/design-system/web' and render
<LogoContainer disabledLink={false}><BaseAppLogoCondensed /></LogoContainer>
(keep BaseAppLogoCondensed and the disabledLink prop as-is).

In
`@packages/design-system/components/web/logos/LogoContainer/__storybook__/stories.tsx`:
- Around line 9-12: The Storybook title string for the LogoContainer story is
miscategorized and misspelled; update the title property in the Meta object
(currently set where Meta<LogoContainerProps> is defined and component is
declared as Logo as ComponentType<LogoContainerProps>) to use the correct
category and spelling, e.g. replace "Popvers/LogoContainer" with
"Logos/LogoContainer" so the story appears under designSystem/Logos in
Storybook.

In `@packages/design-system/components/web/logos/LogoContainer/types.ts`:
- Around line 1-6: LogoContainerProps uses React.ReactNode but React isn't
imported, causing TS errors; import the React types or use the standalone type
import. Update the file to either add an import for React (import React from
'react') or import the type directly (import type { ReactNode } from 'react')
and change LogoContainerProps.children to use ReactNode; ensure references to
LogoContainerProps, children, and React.ReactNode are updated accordingly.
🧹 Nitpick comments (20)
packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuHeader/types.ts (1)

7-10: Consider constraining the Logo slot type.

FC with no generic argument defaults to FC<{}>, which accepts any component regardless of its props. This is fine if the intent is maximum flexibility, but if the Logo component is expected to receive specific props (e.g., size, variant), a narrower type would catch misuse at compile time.

Given the slot pattern used here, this is likely intentional — just flagging for awareness.

packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuFooter/Content/index.tsx (1)

5-27: Placeholder content is excessive — reduce to a minimal stub.

The TODO indicates this is temporary, but 18 identical <Typography> lines is noisy. A single placeholder element (or a short note) would serve the same purpose and be easier to find/replace later.

♻️ Suggested simplification
-// TODO: Replace with actual footer content
-const Content: FC = () => (
-  <div>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-    <Typography variant="caption">Footer Content</Typography>
-  </div>
-)
+// TODO: Replace with actual footer content
+const Content: FC = () => (
+  <div>
+    <Typography variant="caption">Footer Content</Typography>
+  </div>
+)

Would you like me to open an issue to track replacing this placeholder with actual footer content?

packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavItem/Arrow/index.tsx (1)

12-15: Consider targeting transform instead of all in the transition, and verify rotation direction.

Two observations:

  1. transition: 'all' will animate every CSS property change (including color if overridden via sx). Narrowing to transform is more predictable and performant.
  2. Rotating a right-pointing arrow by -90deg when expanded makes it point upward. Conventionally, expanded = downward arrow (90deg). Verify this matches the intended design.
♻️ Suggested transition fix
-        transition: 'all 0.25s linear',
+        transition: 'transform 0.25s linear',
packages/components/modules/navigations-v2/web/NavigationLayout/types.ts (1)

3-5: Inconsistent import type usage — all three layout imports are type-only.

SidebarLayout uses import type but HorizontalLayout and VerticalLayout are regular imports, despite all three being used only in type positions (typeof, ComponentProps<typeof …>). Use import type for all to avoid pulling runtime modules into the bundle unnecessarily.

Proposed fix
-import HorizontalLayout from '../layouts/HorizontalLayout'
 import type SidebarLayout from '../layouts/SidebarLayout'
-import VerticalLayout from '../layouts/VerticalLayout'
+import type HorizontalLayout from '../layouts/HorizontalLayout'
+import type VerticalLayout from '../layouts/VerticalLayout'
packages/components/modules/navigations-v2/web/__shared__/MainContainer/types.ts (1)

5-10: Prop name BoxProps shadows its type — consider renaming.

BoxProps?: BoxProps (Line 9) uses the same identifier for both the prop name and the imported MUI type, which is confusing and can cause shadowing issues. A name like containerProps or boxProps (lowercase) would be clearer and conventional.

♻️ Suggested rename
 export interface MainContainerProps extends PropsWithChildren {
   isNavMini?: boolean
   isNavHorizontal?: boolean
   isNavCentered?: boolean
-  BoxProps?: BoxProps
+  containerProps?: BoxProps
 }

Note: this will require updating all consumers of MainContainerProps.BoxProps to use the new name.

packages/components/modules/navigations-v2/web/constants.ts (2)

42-46: Consider using as const for type-safe literal values.

Without as const, NAV_DATA_TYPE.item is typed as string rather than the literal 'item'. This weakens type checking wherever these values are compared against typed fields (e.g., dataType on navigation data).

♻️ Proposed fix
-export const NAV_DATA_TYPE = {
-  item: 'item',
-  list: 'list',
-  group: 'group',
-}
+export const NAV_DATA_TYPE = {
+  item: 'item',
+  list: 'list',
+  group: 'group',
+} as const

12-25: Naming convention UP_TO_LG / DOWN_TO_LG may cause confusion.

In the styled consumers, DOWN_TO_LG values are used as the base (mobile-first) styles and UP_TO_LG values inside breakpoints.up('lg'). The names read as directional ranges ("up to lg" / "down to lg") but UP_TO_LG is actually applied at and above lg, while DOWN_TO_LG is the default (below lg). Consider renaming to something like NAV_PADDING_SM / NAV_PADDING_LG or NAV_PADDING_BELOW_LG / NAV_PADDING_ABOVE_LG for clarity.

packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/Layout/index.tsx (1)

7-18: Consumer-provided sx will replace default layout styles instead of merging.

Since {...props} is spread after the inline sx, any sx passed by the consumer completely overrides minHeight, display, and flexDirection. This could silently break the layout.

Consider merging sx explicitly or using a styled component:

♻️ Proposed fix — merge sx
-const Layout: FC<LayoutProps> = ({ children, ...props }) => (
+const Layout: FC<LayoutProps> = ({ children, sx, ...props }) => (
   <Box
     sx={{
       minHeight: 1,
       display: 'flex',
       flexDirection: { xs: 'column', lg: 'row' },
+      ...sx,
     }}
     {...props}
   >
     {children}
   </Box>
 )
packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavGroup/Content/types.ts (1)

5-7: open overlaps with the inherited in prop from CollapseProps.

Since ContentProps extends CollapseProps, consumers can pass both open and in. If the component maps openin, consider documenting which takes precedence, or omit in from the extended type to avoid ambiguity:

export interface ContentProps extends PropsWithChildren<Omit<CollapseProps, 'in'>> {
  open?: boolean
}
packages/components/modules/navigations-v2/web/layouts/SidebarLayout/index.tsx (2)

11-12: Consider simplifying the fallback type assertion.

The as NonUndefined<SidebarLayoutSlots> cast on {} is safe but a bit noisy. A simpler alternative:

const SidebarNavigation = slots?.SidebarNavigation ?? DefaultSidebarNavigation

14-23: Slot props spread can silently override core layout state.

{...slotProps?.SidebarNavigation} is spread after isDrawerOpen, onDrawerToggle, and navData, meaning consumers can accidentally override the drawer state managed by useBoolean. If this is intentional (full override capability), a brief comment would help future maintainers understand the design choice.

packages/components/modules/navigations-v2/web/__shared__/HeaderNavigation/index.tsx (1)

5-7: Placeholder component — navData prop is accepted but unused.

This is clearly scaffolding, but worth noting that navData from HeaderNavigationProps is silently ignored. Consider adding a TODO comment so it's not forgotten.

packages/design-system/components/web/logos/LogoContainer/index.tsx (1)

9-37: Add displayName for the forwardRef component.

Components using forwardRef lose their name in React DevTools and error messages. Add a displayName for better debugging.

Proposed fix
 )
 
+LogoContainer.displayName = 'LogoContainer'
+
 export default LogoContainer
packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavGroup/index.tsx (1)

16-16: Unnecessary key prop on a non-list element.

key={navGroup.subheader} on Root has no effect here since Root is not rendered inside a .map() or array. The key for list reconciliation should be on the <NavGroup> element at the call site, not on Root internally.

packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavItem/index.tsx (1)

8-21: Unnecessary key on Root — keys are only meaningful in sibling lists.

key={title} on Line 16 has no effect here because Root is the sole top-level element returned by this component, not part of a .map() call. The parent rendering <NavItem> in a list is the correct place to set keys. This is harmless but misleading.

Suggested fix
-    <Root key={title} {...props} {...slotProps?.Root}>
+    <Root {...props} {...slotProps?.Root}>
packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavList/index.tsx (2)

36-39: slotProps?.ListRoot will clobber the default sx rather than merge it.

Spreading {...slotProps?.ListRoot} after the inline sx means a consumer providing slotProps.ListRoot.sx completely replaces the paddingX. In SidebarMenuRoot (Line 50 of that file) you merge with ...ContainerProps?.sx. Apply the same pattern here for consistency.

Suggested fix
          <ListRoot
            open={open}
+            {...slotProps?.ListRoot}
             sx={{
               paddingX: (theme) => theme.spacing(2),
+              ...slotProps?.ListRoot?.sx,
             }}
-            {...slotProps?.ListRoot}
           >

24-25: Unnecessary key on Header.Root.

Same as in NavItemkey={navList.title} is not inside a .map() here and has no effect.

Suggested fix
-          <Header.Root
-            key={navList.title}
-            onClick={handleToggle}
+          <Header.Root
+            onClick={handleToggle}
packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/utils.tsx (1)

12-20: Unnecessary fallback and type assertion on slots.

slots is a required parameter (not optional), so slots || ({} as ...) is only needed if callers pass undefined at runtime. If that's intentional, consider making the parameter optional (slots?: SidebarMenuContentSlots) to align the type with the runtime behavior.

packages/components/modules/navigations-v2/web/types.ts (1)

17-20: Redundant children redeclaration on NavListData.

NavListData already inherits children?: NavItemData[] from NavItemData (via Omit<NavItemData, 'dataType'>). The explicit redeclaration on line 19 is identical and redundant.

packages/components/modules/navigations-v2/web/index.ts (1)

11-14: Missing type re-exports for primitives — inconsistent with the rest of the barrel.

Every other component group (layouts, shared, root) re-exports types via export type * from '…/types', but SidebarMenuNavGroup and SidebarMenuNavItem do not. These are compound components with nested sub-component types (Root, Header, Content, etc.), so a root-level types.ts aggregating and re-exporting all sub-component types should be created for consistency with the other component groups.

♻️ Proposed fix

Create packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavGroup/types.ts:

export type * from './Root/types'
export type * from './Header/types'
export type * from './Content/types'

Create packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavItem/types.ts:

export type * from './Root/types'
export type * from './Title/types'
export type * from './Arrow/types'
export type * from './ItemIcon/types'

Then add the re-exports to the barrel:

 // primitives
 export { default as SidebarMenuNavGroup } from './primitives/SidebarMenuNavGroup'
+export type * from './primitives/SidebarMenuNavGroup/types'
 
 export { default as SidebarMenuNavItem } from './primitives/SidebarMenuNavItem'
+export type * from './primitives/SidebarMenuNavItem/types'

Comment on lines +15 to +35
if (isNavCentered) {
return (
<NavCenteredContainer component="main" {...BoxProps}>
{children}
</NavCenteredContainer>
)
}

if (isNavHorizontal) {
return (
<NavHorizontalContainer component="main" {...BoxProps}>
{children}
</NavHorizontalContainer>
)
}

return (
<NavVerticalContainer component="main" isNavMini={isNavMini} {...BoxProps}>
{children}
</NavVerticalContainer>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

{...BoxProps} spread can override component="main", losing the landmark role.

If a consumer passes component inside BoxProps, it silently overrides the semantic <main> element on all three container variants. This would break accessibility by removing the main landmark.

Consider either placing the spread before component="main" or explicitly excluding component from BoxProps.

🛡️ Simplest fix — spread BoxProps first so `component` always wins
-      <NavCenteredContainer component="main" {...BoxProps}>
+      <NavCenteredContainer {...BoxProps} component="main">

Apply the same reorder to NavHorizontalContainer (Line 25) and NavVerticalContainer (Line 32).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (isNavCentered) {
return (
<NavCenteredContainer component="main" {...BoxProps}>
{children}
</NavCenteredContainer>
)
}
if (isNavHorizontal) {
return (
<NavHorizontalContainer component="main" {...BoxProps}>
{children}
</NavHorizontalContainer>
)
}
return (
<NavVerticalContainer component="main" isNavMini={isNavMini} {...BoxProps}>
{children}
</NavVerticalContainer>
)
if (isNavCentered) {
return (
<NavCenteredContainer {...BoxProps} component="main">
{children}
</NavCenteredContainer>
)
}
if (isNavHorizontal) {
return (
<NavHorizontalContainer {...BoxProps} component="main">
{children}
</NavHorizontalContainer>
)
}
return (
<NavVerticalContainer {...BoxProps} component="main" isNavMini={isNavMini}>
{children}
</NavVerticalContainer>
)
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/__shared__/MainContainer/index.tsx`
around lines 15 - 35, The BoxProps spread currently comes after component="main"
causing any component prop in BoxProps to override the semantic main landmark;
update the three JSX returns in MainContainer so the spread of BoxProps comes
before component="main" (i.e., <NavCenteredContainer {...BoxProps}
component="main" ...>, same for NavHorizontalContainer and NavVerticalContainer)
so component="main" always wins (alternatively filter out component from
BoxProps, but apply the spread-order change to NavCenteredContainer,
NavHorizontalContainer and NavVerticalContainer).

Comment on lines +17 to +30
export const NavHorizontalContainer = styled(CommonContainer)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
minHeight: 1,
paddingBottom: NAV_PADDING_DOWN_TO_LG.horizontal.bottom,
paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
[theme.breakpoints.up('lg')]: {
paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
paddingBottom: NAV_PADDING_UP_TO_LG.horizontal.bottom,
},
[theme.breakpoints.down('sm')]: {
paddingBottom: 0,
},
}))
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Likely copy-paste bug: paddingTop in up('lg') uses the wrong constant.

Line 24 sets paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top inside the up('lg') breakpoint, which is the same value already applied as the base style on Line 22. This appears to be a mistake — it should likely use NAV_PADDING_UP_TO_LG.horizontal.top to apply a different padding for large screens, consistent with how paddingBottom (Line 25) and all other containers handle their up('lg') overrides.

🐛 Proposed fix
   [theme.breakpoints.up('lg')]: {
-    paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
+    paddingTop: NAV_PADDING_UP_TO_LG.horizontal.top,
     paddingBottom: NAV_PADDING_UP_TO_LG.horizontal.bottom,
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const NavHorizontalContainer = styled(CommonContainer)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
minHeight: 1,
paddingBottom: NAV_PADDING_DOWN_TO_LG.horizontal.bottom,
paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
[theme.breakpoints.up('lg')]: {
paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
paddingBottom: NAV_PADDING_UP_TO_LG.horizontal.bottom,
},
[theme.breakpoints.down('sm')]: {
paddingBottom: 0,
},
}))
export const NavHorizontalContainer = styled(CommonContainer)(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
minHeight: 1,
paddingBottom: NAV_PADDING_DOWN_TO_LG.horizontal.bottom,
paddingTop: NAV_PADDING_DOWN_TO_LG.horizontal.top,
[theme.breakpoints.up('lg')]: {
paddingTop: NAV_PADDING_UP_TO_LG.horizontal.top,
paddingBottom: NAV_PADDING_UP_TO_LG.horizontal.bottom,
},
[theme.breakpoints.down('sm')]: {
paddingBottom: 0,
},
}))
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/__shared__/MainContainer/styled.tsx`
around lines 17 - 30, The up('lg') breakpoint in NavHorizontalContainer wrongly
reuses NAV_PADDING_DOWN_TO_LG.horizontal.top; change it to
NAV_PADDING_UP_TO_LG.horizontal.top so the large-screen override matches the
intended constant (similar to how paddingBottom uses NAV_PADDING_UP_TO_LG) —
update the object inside styled(CommonContainer) where
theme.breakpoints.up('lg') is defined to reference
NAV_PADDING_UP_TO_LG.horizontal.top instead of
NAV_PADDING_DOWN_TO_LG.horizontal.top.

Comment on lines +10 to +17
PaperProps={{
sx: {
width: NAV_WIDTH.VERTICAL,
height: '100% !important',
paddingX: 2,
},
...PaperProps,
}}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Consumer PaperProps.sx will replace default Paper styles instead of merging.

Spreading ...PaperProps after the default sx means a consumer passing PaperProps={{ sx: { background: 'red' } }} loses the width, height, and paddingX defaults. Merge the sx explicitly:

🐛 Proposed fix
 const NavigationDrawer: FC<NavigationDrawerProps> = ({ children, PaperProps, ...props }) => (
   <Drawer
     PaperProps={{
+      ...PaperProps,
       sx: {
         width: NAV_WIDTH.VERTICAL,
         height: '100% !important',
         paddingX: 2,
+        ...PaperProps?.sx,
       },
-      ...PaperProps,
     }}
     {...props}
   >
     {children}
   </Drawer>
 )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
PaperProps={{
sx: {
width: NAV_WIDTH.VERTICAL,
height: '100% !important',
paddingX: 2,
},
...PaperProps,
}}
const NavigationDrawer: FC<NavigationDrawerProps> = ({ children, PaperProps, ...props }) => (
<Drawer
PaperProps={{
...PaperProps,
sx: {
width: NAV_WIDTH.VERTICAL,
height: '100% !important',
paddingX: 2,
...PaperProps?.sx,
},
}}
{...props}
>
{children}
</Drawer>
)
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/__shared__/NavigationDrawer/index.tsx`
around lines 10 - 17, The PaperProps spreading currently overwrites the default
sx because ...PaperProps is spread after defining sx; update the merge so the
consumer sx is merged with the defaults instead of replacing them: keep the
default sx object (width: NAV_WIDTH.VERTICAL, height, paddingX) and then merge
in any consumer PaperProps.sx (e.g., sx: { ...defaultSx, ...(PaperProps?.sx) })
while still spreading the rest of PaperProps (e.g., { ...PaperProps, sx:
mergedSx }) so consumers can override specific keys but not drop the defaults;
apply this change where PaperProps is constructed in NavigationDrawer (reference
PaperProps, sx, NAV_WIDTH.VERTICAL).

}}
{...props}
>
{navData?.map((nav, idx) => createNavRenderer(slots ?? {}, slotProps ?? {})(nav, idx))}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

createNavRenderer is re-created for every item in the list.

createNavRenderer(slots ?? {}, slotProps ?? {}) builds a new renderer closure on each iteration of .map(). Hoist it above the return so it's created once per render:

♻️ Proposed fix
 const SidebarMenuContent: FC<SidebarMenuContentProps> = ({
   slots,
   slotProps,
   navData,
   sx,
   ...props
-}) => (
-  <Scrollbar
+}) => {
+  const renderNav = createNavRenderer(slots ?? {}, slotProps ?? {})
+
+  return (
+    <Scrollbar
       sx={{
         height: 1,
         '& .simplebar-content': {
           height: 1,
           display: 'flex',
           flexDirection: 'column',
         },
         ...sx,
       }}
       {...props}
     >
-    {navData?.map((nav, idx) => createNavRenderer(slots ?? {}, slotProps ?? {})(nav, idx))}
-  </Scrollbar>
-)
+      {navData?.map((nav, idx) => renderNav(nav, idx))}
+    </Scrollbar>
+  )
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{navData?.map((nav, idx) => createNavRenderer(slots ?? {}, slotProps ?? {})(nav, idx))}
const SidebarMenuContent: FC<SidebarMenuContentProps> = ({
slots,
slotProps,
navData,
sx,
...props
}) => {
const renderNav = createNavRenderer(slots ?? {}, slotProps ?? {})
return (
<Scrollbar
sx={{
height: 1,
'& .simplebar-content': {
height: 1,
display: 'flex',
flexDirection: 'column',
},
...sx,
}}
{...props}
>
{navData?.map((nav, idx) => renderNav(nav, idx))}
</Scrollbar>
)
}
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/index.tsx`
at line 27, The renderer returned by createNavRenderer(slots ?? {}, slotProps ??
{}) is being recreated for every item in navData.map; hoist it once in
SidebarMenuContent by calling createNavRenderer(slots ?? {}, slotProps ?? {})
into a const (e.g., const renderNav = createNavRenderer(slots ?? {}, slotProps
?? {})) before the JSX/return and then use navData?.map((nav, idx) =>
renderNav(nav, idx)) so the closure is constructed only once per render.

Comment on lines +17 to +18
const filteredChildren = navList.children?.filter((child) => !child.hide)
const hasChildren = filteredChildren?.length && filteredChildren.length > 0
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Duplicate filter — filteredChildren is computed but unused in the render loop.

filteredChildren is calculated on Line 17 but Lines 41-42 re-filter navList.children from scratch. Use the already-computed filteredChildren in the render to avoid duplicate logic and keep filtering in one place.

Suggested fix
          <ListRoot
            open={open}
            sx={{ paddingX: (theme) => theme.spacing(2) }}
            {...slotProps?.ListRoot}
          >
-            {navList.children
-              ?.filter((child) => !child.hide)
-              .map((child) => (
+            {filteredChildren?.map((child) => (
                <ListItem.Root key={child.title} {...child} {...slotProps?.ListItem}>
                  <ListItem.Icon Icon={child.icon} />
                  <ListItem.Title title={child.title} caption={child.caption} />
                </ListItem.Root>
              ))}
          </ListRoot>

Also applies to: 41-42

🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/__shared__/SidebarNavigation/SidebarMenu/SidebarMenuContent/NavList/index.tsx`
around lines 17 - 18, Replace the duplicate filtering of navList.children in the
render with the precomputed filteredChildren: use filteredChildren (and
hasChildren) instead of calling navList.children?.filter(...) again within the
render loop in SidebarMenuContent/NavList/index.tsx — update any places that
currently re-filter to reference filteredChildren and ensure null/undefined
checks (e.g., guarded map/rendering only when hasChildren is truthy) so
filtering logic is centralized and not duplicated.

Comment on lines +9 to +46
const Root: FC<RootProps> = ({
children,
componentType = 'internalLink',
path,
hide = false,
deep = false,
...props
}) => {
const active = useActiveLink(path, deep)
const component = componentType === 'button' || !path ? 'button' : Link
const target = componentType === 'externalLink' ? '_blank' : undefined
const rel = componentType === 'externalLink' ? 'noopener' : undefined

if (hide) return null

return (
<ListItemButton
component={component}
href={path}
target={target}
rel={rel}
disableGutters
sx={{
minHeight: '44px',
padding: '0px 8px 0px 16px',
width: '100%',
flex: 1,
...(active && {
backgroundColor: (theme) => alpha(theme.palette.primary.main, 0.08),
svg: {
color: (theme) => theme.palette.primary.main,
},
'.label': {
color: (theme) => theme.palette.primary.main,
},
}),
}}
{...props}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

{...props} after sx overwrites active-state styles when consumer passes sx.

Same pattern issue as in the Header component: sx is not destructured out of props, so {...props} on Line 46 will clobber the explicit sx (Lines 31-45) whenever a consumer provides their own sx prop. All active-state and default styles are lost.

🐛 Proposed fix — destructure `sx` from props
 const Root: FC<RootProps> = ({
   children,
   componentType = 'internalLink',
   path,
   hide = false,
   deep = false,
+  sx: sxOverride,
   ...props
 }) => {
   const active = useActiveLink(path, deep)
   ...
   return (
     <ListItemButton
       component={component}
       href={path}
       target={target}
       rel={rel}
       disableGutters
       sx={{
         minHeight: '44px',
         padding: '0px 8px 0px 16px',
         width: '100%',
         flex: 1,
         ...(active && {
           backgroundColor: (theme) => alpha(theme.palette.primary.main, 0.08),
           svg: {
             color: (theme) => theme.palette.primary.main,
           },
           '.label': {
             color: (theme) => theme.palette.primary.main,
           },
         }),
+        ...sxOverride,
       }}
       {...props}
     >
       {children}
     </ListItemButton>
   )
 }
🤖 Prompt for AI Agents
In
`@packages/components/modules/navigations-v2/web/primitives/SidebarMenuNavItem/Root/index.tsx`
around lines 9 - 46, The Root component’s inline sx is being overwritten because
sx isn’t pulled out of props before spreading; destructure sx from the incoming
props in the Root signature (e.g., const Root = ({..., sx, ...props}) => { ...
}) and then merge the component’s computed sx with the consumer sx when
rendering ListItemButton (combine as an array or compose functions so the
active/default styles defined for ListItemButton are preserved and consumer sx
augments them), ensuring ListItemButton retains its active styling logic
(active, svg, .label) while allowing consumer overrides.


# Component Documentation

## Logo
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Documentation heading is inconsistent with the component name.

The heading says "## Logo" but this documentation page is for the LogoContainer component (as indicated by the Meta title). This could confuse readers.

🤖 Prompt for AI Agents
In
`@packages/design-system/components/web/logos/LogoContainer/__storybook__/LogoContainer.mdx`
at line 7, The MDX heading is incorrect—replace the "## Logo" heading with a
heading matching the component name used in the Meta (e.g., "## LogoContainer"
or "## Logo Container") so the documentation title aligns with the component;
update the heading in the LogoContainer story file (the MDX with Meta for
LogoContainer) to match the Meta title.

Comment on lines +33 to +41
```javascript
import { Logo, BaseAppLogoCondensed } from '@baseapp-frontend/design-system/web'

const MyComponent = () => {
return (
<Logo disabledLink={false}>
<BaseAppLogoCondensed />
</Logo>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the exports in the index file
rg -n 'Logo' packages/design-system/components/web/logos/index.ts -A 2 -B 2

Repository: silverlogic/baseapp-frontend

Length of output: 447


🏁 Script executed:

#!/bin/bash
# Also check what's in the LogoContainer directory
ls -la packages/design-system/components/web/logos/LogoContainer/

Repository: silverlogic/baseapp-frontend

Length of output: 357


🏁 Script executed:

#!/bin/bash
# Check the main export file to see how these are defined
cat packages/design-system/components/web/logos/index.ts

Repository: silverlogic/baseapp-frontend

Length of output: 429


Example imports and uses Logo instead of LogoContainer.

The example code imports Logo and renders <Logo disabledLink={false}>, but this is a LogoContainer documentation file. Logo and LogoContainer are separate components. The example should import and use LogoContainer instead to match what is being documented.

🤖 Prompt for AI Agents
In
`@packages/design-system/components/web/logos/LogoContainer/__storybook__/LogoContainer.mdx`
around lines 33 - 41, The example in the LogoContainer story imports and renders
the wrong component: replace the import and usage of Logo with LogoContainer so
the story demonstrates the documented component; specifically update the import
to import LogoContainer from '@baseapp-frontend/design-system/web' and render
<LogoContainer disabledLink={false}><BaseAppLogoCondensed /></LogoContainer>
(keep BaseAppLogoCondensed and the disabledLink prop as-is).

Comment on lines +9 to +12
const meta: Meta<LogoContainerProps> = {
title: '@baseapp-frontend | designSystem/Popvers/LogoContainer',
component: Logo as ComponentType<LogoContainerProps>,
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Storybook title is miscategorized — "Popvers" should likely be "Logos".

LogoContainer is a logo component, not a popover. The title Popvers/LogoContainer appears to be both a typo ("Popvers" → "Popovers") and a wrong category. This will cause the story to appear under the wrong section in Storybook's sidebar.

Suggested fix
 const meta: Meta<LogoContainerProps> = {
-  title: '@baseapp-frontend | designSystem/Popvers/LogoContainer',
+  title: '@baseapp-frontend | designSystem/Logos/LogoContainer',
   component: Logo as ComponentType<LogoContainerProps>,
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const meta: Meta<LogoContainerProps> = {
title: '@baseapp-frontend | designSystem/Popvers/LogoContainer',
component: Logo as ComponentType<LogoContainerProps>,
}
const meta: Meta<LogoContainerProps> = {
title: '@baseapp-frontend | designSystem/Logos/LogoContainer',
component: Logo as ComponentType<LogoContainerProps>,
}
🤖 Prompt for AI Agents
In
`@packages/design-system/components/web/logos/LogoContainer/__storybook__/stories.tsx`
around lines 9 - 12, The Storybook title string for the LogoContainer story is
miscategorized and misspelled; update the title property in the Meta object
(currently set where Meta<LogoContainerProps> is defined and component is
declared as Logo as ComponentType<LogoContainerProps>) to use the correct
category and spelling, e.g. replace "Popvers/LogoContainer" with
"Logos/LogoContainer" so the story appears under designSystem/Logos in
Storybook.

Comment on lines +1 to +6
import { BoxProps } from '@mui/material'

export interface LogoContainerProps extends BoxProps {
children: React.ReactNode
disabledLink?: boolean
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, check the exact content of the file in question
echo "=== Checking target file ==="
cat -n packages/design-system/components/web/logos/LogoContainer/types.ts

echo -e "\n=== Checking for global React declarations ==="
find . -name "*.d.ts" -o -name "types.d.ts" | head -20 | xargs grep -l "declare.*global.*React" 2>/dev/null || echo "No global React declarations found"

echo -e "\n=== Checking tsconfig for jsx settings ==="
find . -name "tsconfig*.json" -type f | head -5 | xargs grep -A 2 '"jsx"' 2>/dev/null || echo "No jsx config found"

echo -e "\n=== Checking how other files in design-system use React types ==="
rg "React\.(ReactNode|ComponentProps|FC)" packages/design-system/ -l | head -10

Repository: silverlogic/baseapp-frontend

Length of output: 1095


🏁 Script executed:

#!/bin/bash
# Check how Logo/types.ts imports React
echo "=== Logo/types.ts imports ==="
head -10 packages/design-system/components/web/logos/Logo/types.ts

# Check AppBar/types.ts
echo -e "\n=== AppBar/types.ts imports ==="
head -10 packages/design-system/components/native/appbars/AppBar/types.ts

# Check Scrollbar/types.ts
echo -e "\n=== Scrollbar/types.ts imports ==="
head -10 packages/design-system/components/web/scrollbars/Scrollbar/types.ts

# Find all tsconfig files
echo -e "\n=== Finding tsconfig files ==="
find . -name "tsconfig*.json" -type f | head -20

# Check root tsconfig
echo -e "\n=== Root tsconfig.json content ==="
if [ -f tsconfig.json ]; then head -50 tsconfig.json; fi

# Check if there's a tsconfig in packages/design-system
echo -e "\n=== design-system tsconfig ==="
if [ -f packages/design-system/tsconfig.json ]; then head -50 packages/design-system/tsconfig.json; fi

Repository: silverlogic/baseapp-frontend

Length of output: 2854


🏁 Script executed:

#!/bin/bash
# Find the extended tsconfig
echo "=== Finding extended tsconfig ==="
find . -path "*/tsconfig/lib.json" -o -path "*/@baseapp-frontend/tsconfig*" 2>/dev/null | head -20

# Check packages/tsconfig directory
echo -e "\n=== Checking packages/tsconfig ==="
ls -la packages/tsconfig/ 2>/dev/null || find . -type d -name "tsconfig" | grep -v node_modules | head -10

# Look for any .d.ts files that might declare React globally
echo -e "\n=== Checking for .d.ts files with React declarations ==="
find packages/design-system -name "*.d.ts" -exec cat {} \; 2>/dev/null | head -50

# Check if `@types/react` is properly listed
echo -e "\n=== Checking package.json for `@types/react` ==="
jq '.devDependencies, .dependencies' package.json 2>/dev/null | grep -i "react" | head -20

# Try to see if these files actually compile - check build output or test results
echo -e "\n=== Checking if there are any TypeScript errors reported ==="
rg "React\.ReactNode.*error" --type=ts --type=tsx 2>/dev/null || echo "No error logs found"

# Check if the files build successfully
echo -e "\n=== Checking tsconfig.build.json for design-system ==="
cat packages/design-system/tsconfig.build.json 2>/dev/null || echo "File not found"

Repository: silverlogic/baseapp-frontend

Length of output: 1141


🏁 Script executed:

#!/bin/bash
# Check the extended tsconfig
echo "=== packages/tsconfig/lib.json ==="
cat packages/tsconfig/lib.json

# Also check if there are any type declaration files in design-system root
echo -e "\n=== design-system type declaration files ==="
find packages/design-system -maxdepth 2 -name "*.d.ts" -o -name "types.ts" | grep -E "(types|index\.d)" | head -10

# Check if React is in the types array of the extended config
echo -e "\n=== Checking for React in any tsconfig types ==="
rg '"types":\s*\[' packages/tsconfig/ packages/design-system/ --type=json -A 5 || echo "No types array found"

# Verify if the project actually compiles with these files
echo -e "\n=== Checking if there's a build script or CI that would catch this ==="
grep -r "React\.ReactNode" packages/design-system/components/web/logos/ --include="*.ts" --include="*.tsx"

Repository: silverlogic/baseapp-frontend

Length of output: 1960


React is not imported — React.ReactNode will cause a TypeScript error.

Line 4 references React.ReactNode without importing React. The project's tsconfig has "strict": true and does not declare React in the global namespace, so this will fail type checking.

Proposed fix
+import React from 'react'
 import { BoxProps } from '@mui/material'

Or alternatively:

+import { ReactNode } from 'react'
 import { BoxProps } from '@mui/material'
 
 export interface LogoContainerProps extends BoxProps {
-  children: React.ReactNode
+  children: ReactNode
   disabledLink?: boolean
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { BoxProps } from '@mui/material'
export interface LogoContainerProps extends BoxProps {
children: React.ReactNode
disabledLink?: boolean
}
import React from 'react'
import { BoxProps } from '@mui/material'
export interface LogoContainerProps extends BoxProps {
children: React.ReactNode
disabledLink?: boolean
}
🤖 Prompt for AI Agents
In `@packages/design-system/components/web/logos/LogoContainer/types.ts` around
lines 1 - 6, LogoContainerProps uses React.ReactNode but React isn't imported,
causing TS errors; import the React types or use the standalone type import.
Update the file to either add an import for React (import React from 'react') or
import the type directly (import type { ReactNode } from 'react') and change
LogoContainerProps.children to use ReactNode; ensure references to
LogoContainerProps, children, and React.ReactNode are updated accordingly.

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.

2 participants