Skip to content

Feature/fin 021 parts/sidebar#75

Merged
Qunitee merged 14 commits into
feature/fin-021-parts/cardsfrom
feature/fin-021-parts/sidebar
Apr 13, 2026
Merged

Feature/fin 021 parts/sidebar#75
Qunitee merged 14 commits into
feature/fin-021-parts/cardsfrom
feature/fin-021-parts/sidebar

Conversation

@dmytroreshetylo

@dmytroreshetylo dmytroreshetylo commented Apr 10, 2026

Copy link
Copy Markdown
Member

Title

Add sidebar

Type

  • Feature
  • Bug

Description

Added sidebar, is mobile and get active route hooks

Media

image

Check list

  • Self-reviewed
  • Added unit tests
  • The code doesn't have new warnings and errors
  • Passed ESLint / Prettier checks

Summary by CodeRabbit

  • New Features

    • Added mobile-responsive navigation with adaptive sidebar behavior
    • Introduced collapsible sidebar with icon mode for compact displays
    • Added sheet component for side panels with animated transitions
    • Implemented tooltip support across UI components
    • Added skeleton loaders for improved loading states
    • Enhanced navigation with active route tracking and nested menu items
  • Improvements

    • Made icon button size optional for greater flexibility
    • Refactored layout structure for better responsive design

@dmytroreshetylo dmytroreshetylo requested a review from Qunitee April 10, 2026 22:10
@coderabbitai

coderabbitai Bot commented Apr 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f863df93-78f0-4bef-bedf-ceef56c71247

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces a comprehensive sidebar and sheet UI component library with mobile responsiveness support, adds responsive hooks and navigation models, updates the profile layout to conditionally render based on viewport size, wraps the app with a tooltip provider, and reorganizes CSS variable declarations.

Changes

Cohort / File(s) Summary
Profile Layout & Responsive Behavior
src/app/(profile)/layout.tsx, src/app/(profile)/main/layout.tsx, src/app/(profile)/settings/layout.tsx
Removed redundant nested layout files; refactored root profile layout to use useIsMobile() hook for conditional rendering of ProfileSidebar (desktop) vs UserMobileNavigationBar (mobile), and adjusted flex layout direction based on viewport.
Sidebar UI Component System
src/client/shared/ui/ui-sidebar/ui-sidebar*.tsx, src/client/shared/ui/ui-sidebar/styles/*
Added complete sidebar system: provider with state management and keyboard shortcuts, collapsible variants (offcanvas/icon/none), header/footer/content sections, menu system with sub-items and badges, responsive rail control, and comprehensive SCSS styling for layout, positioning, and animation.
Sheet UI Component System
src/client/shared/ui/ui-sheet/ui-sheet*.tsx, src/client/shared/ui/ui-sheet/styles/*
Added sheet/dialog component system: portal, overlay, content, close, header, footer, title, description, and trigger subcomponents with Radix UI primitives, plus SCSS for animations and positioning across all sides.
Tooltip UI Component System
src/client/shared/ui/ui-tooltip/ui-tooltip*.tsx, src/client/shared/ui/ui-tooltip/styles/*
Added tooltip system: root, trigger, content, and provider components wrapping Radix UI, with SCSS styling including zoom and directional slide-fade animations.
Responsive Hooks & Models
src/client/shared/hooks/is-mobile/is-mobile.hook.ts, src/client/shared/hooks/get-active-route/get-active-route.hook.ts, src/client/shared/models/nav-item.model.ts
Added useIsMobile() hook for viewport detection (768px breakpoint), useGetActiveRoute() hook for route matching with prefix fallback, and NavItemModel/SidebarItemModel types for navigation structure.
Sidebar Content & Navigation
src/client/shared/components/sidebar-content/fin-sidebar-content.tsx, src/client/shared/components/sidebar-content/props/sidebar-content.props.ts, src/client/widgets/profile-sidebar/profile-sidebar.tsx
Added FinSidebarContent component that renders hierarchical navigation using useGetActiveRoute() and sidebar item models, plus ProfileSidebar widget demonstrating sidebar usage with collapsible icon variant.
Global App Setup & Skeleton
src/app/client-layout.tsx, src/client/shared/ui/ui-skeleton/ui-skeleton.tsx
Wrapped LoadGlobalToast and children with UiTooltipProvider in main layout; added UiSkeleton component for loading states.
UI Props & Theme
src/client/shared/ui/ui-icon-button/props/icon-button.props.ts, src/client/shared/styles/theme.scss
Made IconButtonProps.size optional; reorganized CSS radius variables from @theme inline block to separate @theme block.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • PR #67 — Modifies profile layout and conditionally renders ProfileSidebar vs UserMobileNavigationBar using useIsMobile(), directly overlapping with main PR's responsive layout logic.
  • PR #52 — Refactors UI primitives (UiIconButton, UiSvgIcon, UiButton) and their props into a shared namespace, related to type/prop changes in this PR.
  • PR #60 — Extensive changes to ui-sidebar, ui-* components, tooltip/provider, and layout composition directly overlapping with this PR's major systems.

Suggested labels

feature, ui-components, refactoring, mobile-responsive

Suggested reviewers

  • Qunitee

Poem

🐰 With sidebar pride and mobile grace,
Sheets and tooltips find their place,
Responsive hooks guide the way,
From desktop wide to mobile's bay,
A UI feast for all to see,
Built with components wild and free!

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.26% 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/fin 021 parts/sidebar' is partially related to the changeset. It references the feature branch naming convention and the sidebar feature, which is a major component added. However, it is somewhat vague and uses a branch-naming style rather than a clear, descriptive PR title that explains what was actually added. Consider using a more descriptive title like 'Add sidebar component with mobile support and routing hooks' to clearly communicate the main changes to future reviewers.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The PR description follows the provided template structure with Type, Description, Media, and Checklist sections completed. However, the Description section is minimal ('Added sidebar, is mobile and get active route hooks') and lacks detail about the components created and tasks completed.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/fin-021-parts/sidebar

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.

@dmytroreshetylo

Copy link
Copy Markdown
Member Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Apr 10, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@dmytroreshetylo

Copy link
Copy Markdown
Member Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Apr 11, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 11

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (10)
src/client/shared/ui/ui-sidebar/styles/sidebar-inset-styles.scss-16-18 (1)

16-18: ⚠️ Potential issue | 🟡 Minor

Fix collapsed-state selector; current nesting prevents the rule from matching.

On Line 16, &.peer[data-state='collapsed'] ~ & tries to match .sidebar-inset.peer[data-state='collapsed'], but the .sidebar-inset element doesn't have the peer class (only .sidebar-wrapper does). The collapsed left margin rule will never apply.

Proposed selector fix
 `@media` (min-width: 768px) {
   .peer[data-variant='inset'] ~ & {
     margin: 0.5rem;
     margin-left: 0;
     border-radius: 0.75rem;
     box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);

-    &.peer[data-state='collapsed'] ~ & {
-      margin-left: 0.5rem;
-    }
   }
+
+  .peer[data-variant='inset'][data-state='collapsed'] ~ & {
+    margin-left: 0.5rem;
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-inset-styles.scss` around
lines 16 - 18, The collapsed-state selector is nested incorrectly: replace the
failing selector "&.peer[data-state='collapsed'] ~ &" with a selector that
targets .sidebar-inset when a sibling .sidebar-wrapper has the peer collapsed
state, e.g. ".sidebar-wrapper.peer[data-state='collapsed'] ~ &"; update the rule
block containing that selector so the margin-left: 0.5rem applies when the
.sidebar-wrapper element has the peer and data-state="collapsed".
src/client/shared/ui/ui-sidebar/styles/sidebar-menu-action-styles.scss-13-13 (1)

13-13: ⚠️ Potential issue | 🟡 Minor

outline-style: hidden is not valid CSS and will be dropped by the browser.

The hidden value is not valid for the outline-style property. Per the CSS spec and MDN, valid values are: auto, none, dotted, dashed, solid, double, groove, ridge, inset, outset. Use outline: none; instead.

Suggested fix
-  outline-style: hidden;
+  outline: none;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-menu-action-styles.scss` at
line 13, Replace the invalid CSS declaration "outline-style: hidden" with a
valid rule; change it to "outline: none" (or "outline-style: none") in the same
selector where "outline-style: hidden" appears so the browser will not drop the
rule; keep any accessibility considerations in mind (consider using
:focus-visible later if you need to hide outlines only for mouse users).
src/client/shared/ui/ui-sidebar/styles/sidebar-group-action-styles.scss-13-13 (1)

13-13: ⚠️ Potential issue | 🟡 Minor

outline-style: hidden is invalid CSS and will be ignored. Use valid CSS syntax instead.

Line 13 uses an invalid value for the outline-style property ("hidden" is not a valid outline-style keyword). The declaration has no effect and will be ignored by browsers. This pattern appears in 5 sidebar component files. Replace with a valid CSS declaration to remove the outline.

Suggested fix
-  outline-style: hidden;
+  outline: none;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-group-action-styles.scss` at
line 13, Replace the invalid CSS declaration "outline-style: hidden" (found in
sidebar-group-action-styles.scss and four other sidebar component files) with a
valid rule such as "outline: none;" or "outline-style: none;" to remove the
outline; update each file where "outline-style: hidden" appears and consider
using :focus-visible to restore accessible focus styling where needed.
src/client/shared/ui/ui-sidebar/ui-sidebar-menu-action.tsx-16-25 (1)

16-25: ⚠️ Potential issue | 🟡 Minor

Add explicit type="button" to prevent accidental form submissions.

When asChild is false, the native <button> renders without an explicit type attribute, defaulting to type="submit" in form contexts per the HTML specification. This can trigger unintended form submissions.

This pattern is already established in similar components like UiButton, UiIconButton, and UiPurpleButton which all explicitly set type={!asChild ? (type ?? 'button') : undefined} for consistency and safety.

Suggested fix
 export function UiSidebarMenuAction({
   className,
   asChild = false,
   showOnHover = false,
   ...props
 }: React.ComponentProps<'button'> & {
   asChild?: boolean;
   showOnHover?: boolean;
 }) {
   const Comp = asChild ? Slot.Root : 'button';

   return (
     <Comp
       data-slot="sidebar-menu-action"
       data-sidebar="menu-action"
       data-show-on-hover={showOnHover}
+      type={!asChild ? 'button' : undefined}
       className={cn('sidebar-menu-action', className)}
       {...props}
     />
   );
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-menu-action.tsx` around lines 16 -
25, The returned element uses Comp = asChild ? Slot.Root : 'button' and can
render a native button without an explicit type (causing accidental form
submits); modify the component to accept an optional type prop and pass
type={!asChild ? (type ?? 'button') : undefined} into <Comp ... /> so when
asChild is false the native button defaults to 'button' and when asChild is true
the type is undefined (preserving Slot behavior), matching patterns used in
UiButton/UiIconButton/UiPurpleButton.
src/app/(profile)/layout.tsx-21-26 (1)

21-26: ⚠️ Potential issue | 🟡 Minor

Avoid first-paint desktop sidebar on mobile devices.

On Line 22 and Line 26, branching depends on useIsMobile(), but that hook returns false on initial render (src/client/shared/hooks/is-mobile/is-mobile.hook.ts:3-19). Mobile users can briefly see desktop sidebar, then a swap to mobile nav.

💡 Suggested fix (gate responsive rendering until mounted)
+'use client';
+
+import * as React from 'react';
 import { ChildrenComponentProps } from '@frontend/shared/models/component-with-chilren.model';
 import { useUserGuard } from '@frontend/entities/profile/auth-guard.hook';
 import { AuthorizedUserProvider } from '@frontend/shared/services/user-information/authorized-user.hook';
 import { ProfileSidebar } from '@frontend/widgets/profile-sidebar/profile-sidebar';
 import { useIsMobile } from '@frontend/shared/hooks/is-mobile/is-mobile.hook';
 import { UserMobileNavigationBar } from '@frontend/widgets/mobile-navigation/navigation-bar/navigation-bar';
 import { cn } from '@frontend/shared/utils/cn.util';

 export default function UserLayoutPage({ children }: ChildrenComponentProps) {
   const user = useUserGuard();
   const isMobile = useIsMobile();
+  const [mounted, setMounted] = React.useState(false);
+
+  React.useEffect(() => {
+    setMounted(true);
+  }, []);

   if (!user) {
     return null;
   }

   return (
     <AuthorizedUserProvider>
-      <div className={cn('size-full flex', isMobile && 'flex-col')}>
-        {!isMobile && <ProfileSidebar />}
+      <div className={cn('size-full flex', mounted && isMobile && 'flex-col')}>
+        {mounted && !isMobile && <ProfileSidebar />}
 
         <div className="flex-1">{children}</div>
 
-        {isMobile && <UserMobileNavigationBar />}
+        {mounted && isMobile && <UserMobileNavigationBar />}
       </div>
     </AuthorizedUserProvider>
   );
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/app/`(profile)/layout.tsx around lines 21 - 26, The layout renders
ProfileSidebar or UserMobileNavigationBar based directly on useIsMobile(), which
returns false on first render and causes a desktop sidebar flash on mobile; wrap
the responsive branching in a "mounted" guard so you only decide between
ProfileSidebar and UserMobileNavigationBar after the component is mounted (e.g.,
add a local hasMounted state set true in useEffect or reuse an existing
useIsMounted hook) and in layout.tsx defer rendering those two components until
hasMounted is true to prevent the initial incorrect desktop render.
src/client/shared/ui/ui-sidebar/styles/sidebar-group-label-styles.scss-13-13 (1)

13-13: ⚠️ Potential issue | 🟡 Minor

Replace invalid outline-style: hidden with valid CSS.

outline-style: hidden is not a valid CSS value and will be ignored by browsers. The hidden keyword is valid only for border-style, not outline-style.

Fix
-  outline-style: hidden;
+  outline: none;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-group-label-styles.scss` at
line 13, Replace the invalid declaration "outline-style: hidden" with a valid
outline reset such as "outline: none;" (or "outline-style: none;") in the same
rule so the browser will honor it; locate the rule containing the
"outline-style: hidden" declaration and update that line to "outline: none;" to
correctly remove the outline.
src/client/shared/ui/ui-sidebar/styles/sidebar-rail-styles.scss-35-41 (1)

35-41: ⚠️ Potential issue | 🟡 Minor

Likely selector typo prevents cursor styles from applying.

Line 35 and Line 39 use .in[...], while surrounding logic uses .group[...]. This likely breaks the intended resize cursor behavior.

💡 Proposed fix
-  .in[data-side='left'] & {
+  .group[data-side='left'] & {
     cursor: w-resize;
   }

-  .in[data-side='right'] & {
+  .group[data-side='right'] & {
     cursor: e-resize;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-rail-styles.scss` around lines
35 - 41, The selectors `.in[data-side='left'] &` and `.in[data-side='right'] &`
are likely typos and prevent the resize cursors from applying; change those
selectors to `.group[data-side='left'] &` and `.group[data-side='right'] &`
respectively so they match the surrounding logic and enable the intended
w-resize/e-resize cursor behavior (update the two selector lines referencing
`.in` to `.group`).
src/client/shared/ui/ui-sidebar/ui-sidebar.tsx-59-61 (1)

59-61: ⚠️ Potential issue | 🟡 Minor

Fix the SR-only Ukrainian copy.

Line 61 has a typo: ВідбражаєтьсяВідображається.

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

In `@src/client/shared/ui/ui-sidebar/ui-sidebar.tsx` around lines 59 - 61, The
Ukrainian SR-only copy in the UiSheetHeader is misspelled; update the
UiSheetDescription text inside the UiSheetHeader (where UiSheetHeader,
UiSheetTitle and UiSheetDescription are defined) to fix the typo by changing
"Відбражається лише на мобільних пристроях" to "Відображається лише на мобільних
пристроях".
src/client/shared/ui/ui-sidebar/ui-sidebar-menu-button.tsx-34-43 (1)

34-43: ⚠️ Potential issue | 🟡 Minor

Default the native button to type="button".

Without an explicit type, this submits the nearest form. Sidebar navigation clicks should not trigger form submission.

💡 Suggested fix
 export function UiSidebarMenuButton({
   asChild = false,
   isActive = false,
   variant = 'default',
   size = 'default',
   tooltip,
+  type,
   className,
   ...props
 }: UiSidebarMenuButtonProps) {
@@
     <Comp
       data-slot="sidebar-menu-button"
       data-sidebar="menu-button"
       data-size={size}
       data-active={isActive}
       data-variant={variant}
       className={cn('sidebar-menu-button', className)}
+      {...(!asChild ? { type: type ?? 'button' } : {})}
       {...props}
     />
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-menu-button.tsx` around lines 34 -
43, The rendered menu button (variable "button" using "Comp" in
ui-sidebar-menu-button.tsx) lacks an explicit type, so clicks inside a form can
trigger submission; ensure a native button gets type="button" by passing
type="button" to the JSX element (place type="button" before {...props}) or set
a default in the component props (e.g., default type = 'button' when
destructuring) and, if "Comp" can be other elements, only apply this default
when Comp === 'button'.
src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx-17-25 (1)

17-25: ⚠️ Potential issue | 🟡 Minor

Make the context setters real React state setters, or keep them boolean-only everywhere.

SidebarContextProps exposes setOpen/setOpenMobile as (open: boolean) => void, but the provider already uses updater functions in toggleSidebar(). setOpen is wrapped to accept both forms, and setOpenMobile is a direct React state setter that also supports updater functions. This means the public API is typed narrower than the implementation, and callers would violate the declared type contract when passing updater functions.

💡 Suggested direction
 export type SidebarContextProps = {
   state: 'expanded' | 'collapsed';
   open: boolean;
-  setOpen: (open: boolean) => void;
+  setOpen: React.Dispatch<React.SetStateAction<boolean>>;
   openMobile: boolean;
-  setOpenMobile: (open: boolean) => void;
+  setOpenMobile: React.Dispatch<React.SetStateAction<boolean>>;
   isMobile: boolean;
   toggleSidebar: () => void;
 };

If you keep updater-form support, resolve the next value from the previous state inside the setter path instead of evaluating it against the closed-over open.

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

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx` around lines 17 -
25, SidebarContextProps currently types setOpen and setOpenMobile as (open:
boolean) => void while the provider (see toggleSidebar and the provider's
internal setters) accepts React-style updater functions; update the public types
to accept React.Dispatch<React.SetStateAction<boolean>> (or a union type like
boolean | ((prev:boolean)=>boolean)) so callers can pass updater functions, and
if keeping updater support ensure any custom setter (e.g., the wrapper around
setOpen used by toggleSidebar) resolves the next value from the previous state
(invoke functional updater when a function is passed) instead of relying on
closed-over open; update the type for setOpen and setOpenMobile and adjust the
provider wrapper logic to handle functional updaters accordingly.
🧹 Nitpick comments (4)
src/app/client-layout.tsx (1)

25-28: Consolidate tooltip provider ownership to avoid nested contexts.

MainLayout now provides tooltip context globally, while UiSidebarProvider also wraps its subtree with a tooltip provider (src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx, around Line 110-Line 125). Consider keeping a single owner to avoid config drift and unnecessary nesting.

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

In `@src/app/client-layout.tsx` around lines 25 - 28, MainLayout currently wraps
children with UiTooltipProvider (UiTooltipProvider in src/app/client-layout.tsx)
while UiSidebarProvider also creates a tooltip context (ui-sidebar-provider.tsx
around the provider block), causing nested tooltip contexts; pick a single
owner—prefer the global MainLayout—and remove the UiTooltipProvider wrapper from
UiSidebarProvider (delete the <UiTooltipProvider> ... </UiTooltipProvider> block
in UiSidebarProvider and rely on the existing UiTooltipProvider in
client-layout.tsx), ensuring consumers still import/use UiTooltip
hooks/components unchanged.
src/client/shared/ui/ui-sheet/styles/ui-sheet-overlay-styles.scss (1)

7-24: Add reduced-motion fallback for overlay animations.

Current open/close animations run unconditionally; consider respecting prefers-reduced-motion for accessibility.

♿ Suggested SCSS addition
 .sheet-overlay {
   position: fixed;
   inset: 0;
   z-index: 50;
   background-color: rgba(0, 0, 0, 0.5);

   &[data-state='open'] {
     animation: fadeIn 500ms cubic-bezier(0.4, 0, 0.2, 1) both;
   }

   &[data-state='closed'] {
     animation: fadeOut 300ms cubic-bezier(0.4, 0, 0.2, 1) both;
   }
 }
+
+@media (prefers-reduced-motion: reduce) {
+  .sheet-overlay[data-state='open'],
+  .sheet-overlay[data-state='closed'] {
+    animation: none;
+  }
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sheet/styles/ui-sheet-overlay-styles.scss` around
lines 7 - 24, Respect users' prefers-reduced-motion by wrapping the open/close
animation rules for &[data-state='open'] and &[data-state='closed'] (which
currently use the fadeIn/fadeOut keyframes) in a `@media` (prefers-reduced-motion:
reduce) query and set animation: none (or a short non-animated fallback, e.g.,
animation: none !important; opacity: 1 for open, opacity: 0 for closed) so the
fadeIn/fadeOut keyframes are not played for reduced-motion users.
src/client/shared/hooks/is-mobile/is-mobile.hook.ts (1)

10-15: Use mql.matches directly to avoid duplicated breakpoint logic.

Line 11 and Line 14 can read from the media query object itself, which keeps state updates tied to the actual query condition.

Refactor suggestion
   React.useEffect(() => {
     const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
     const onChange = () => {
-      setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
+      setIsMobile(mql.matches);
     };
     mql.addEventListener('change', onChange);
-    setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
+    setIsMobile(mql.matches);
     return () => mql.removeEventListener('change', onChange);
   }, []);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/hooks/is-mobile/is-mobile.hook.ts` around lines 10 - 15,
The hook duplicates breakpoint logic by computing window.innerWidth <
MOBILE_BREAKPOINT in both the onChange handler and initial setIsMobile; instead
read the media query state directly from the MediaQueryList (mql.matches) to
keep updates consistent with the query. Update the onChange callback (onChange)
to call setIsMobile(mql.matches) and initialize state with
setIsMobile(mql.matches) instead of recalculating via MOBILE_BREAKPOINT, leaving
mql.addEventListener('change', onChange) and cleanup via
mql.removeEventListener('change', onChange) unchanged.
src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx (1)

18-22: Preserve built-in toggle behavior when custom onClick is passed.

Because {...props} is spread after onClick, a consumer-provided onClick can replace toggleSidebar.

♻️ Suggested refactor
-export function UiSidebarRail({ className, ...props }: React.ComponentProps<'button'>) {
+export function UiSidebarRail({ className, onClick, ...props }: React.ComponentProps<'button'>) {
   const { toggleSidebar } = useSidebar();

   return (
     <button
@@
-      onClick={toggleSidebar}
+      onClick={(event) => {
+        onClick?.(event);
+        if (!event.defaultPrevented) toggleSidebar();
+      }}
       title="Toggle Sidebar"
       className={cn('sidebar-rail', className)}
       {...props}
     />
   );
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx` around lines 18 - 22,
The current JSX spreads {...props} after setting onClick={toggleSidebar},
allowing a consumer onClick to override toggleSidebar; modify the component so
the final click handler composes both: call toggleSidebar and then call
props.onClick (if present) rather than letting props replace it — update the
element that currently sets onClick={toggleSidebar} to compute a combined
handler (using toggleSidebar and props.onClick) or spread props first and set
onClick last so toggleSidebar always runs; refer to toggleSidebar,
props.onClick, and the element rendering the sidebar-rail to locate where to
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/client/shared/hooks/get-active-route/get-active-route.hook.ts`:
- Around line 39-41: The current prefix check uses pathname.startsWith(path) and
then assigns currentRoute = key during iteration, which causes false positives
(e.g., "/profile" matching "/profiled") and non-deterministic overrides; update
the match to be segment-safe by requiring either pathname === path or
pathname.startsWith(path + "/") (so the path boundary is respected), and make
the selection deterministic by picking the first matching key instead of
overwriting (e.g., use Array.prototype.find on paths or break after setting
currentRoute). Apply this change where currentRoute, paths, pathname, and key
are used so the active route resolution is boundary-aware and
order-deterministic.

In `@src/client/shared/ui/ui-icon-button/props/icon-button.props.ts`:
- Line 6: IconButtonProps currently makes size optional but UiIconButton
forwards size to UiSvgIcon where size is required; fix by either (A) making size
required on IconButtonProps (update the IconButtonProps type to remove the ?
from size) so callers must supply it, or (B) enforce a default inside
UiIconButton (set a sensible default like "medium" in the UiIconButton component
before forwarding to UiSvgIcon) and ensure UiIconButton always passes a defined
size; update references to IconButtonProps, UiIconButton, and the forwarded size
prop accordingly.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-styles.scss`:
- Around line 35-46: The selectors assume two nested .group ancestors but
UiSidebar (src/client/shared/ui/ui-sidebar/ui-sidebar.tsx) sets data-variant and
data-collapsible on the same wrapper, so the current nested
`.group[data-variant='...'] .group[data-collapsible='icon'] &` never matches;
update the SCSS to combine attributes on the same .group (e.g.,
`.group[data-variant='floating'][data-collapsible='icon'] &` and a corresponding
combined selector for non-floating/non-inset) so the `.sidebar-gap` width rules
apply when both attributes exist on the same element.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-group-action.tsx`:
- Around line 15-20: The sidebar action component renders a native button when
asChild is false but doesn't set a button type, causing unintended form
submissions; update the component (the render of Comp in
ui-sidebar-group-action.tsx, and apply the same fix to UiSidebarMenuAction) to
ensure when asChild is false you pass an explicit type='button' prop (while
preserving any user-provided type in {...props}), so the default behavior is
safe.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-header-icon.tsx`:
- Around line 1-3: This file uses React hooks (useState) and the custom hook
useSidebar inside the UiSidebarHeaderIcon component, so add the Next.js client
directive by inserting 'use client' as the very first line of src code (before
any imports) to mark the module as a client component; ensure the string literal
appears exactly as 'use client' on its own line above the existing imports
(affecting UiSidebarHeaderIcon, useState, and useSidebar usage).

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-header.tsx`:
- Line 6: The component UiSidebarHeader currently destructures an unused prop
justifyBetween from React.ComponentProps<'div'> which causes a TS2339 error;
remove justifyBetween from the parameter list (i.e., stop destructuring it) so
the function signature is just ({ className, ...props }:
React.ComponentProps<'div'>) or, if justifyBetween is actually needed, add it to
a custom prop type/interface and use that type instead; ensure any call sites
that pass justifyBetween are updated or the prop is implemented where
appropriate.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx`:
- Around line 79-89: The global keydown handler in the useEffect (handleKeyDown
/ SIDEBAR_KEYBOARD_SHORTCUT / toggleSidebar) currently fires even when focus is
inside editable controls; modify handleKeyDown to early-return unless the event
target is not an editable element: check that event.target is an HTMLElement and
skip handling when tagName is INPUT, TEXTAREA, SELECT or when
element.isContentEditable is true (and optionally when event.defaultPrevented is
true); only call event.preventDefault() and toggleSidebar() when none of those
editable conditions apply.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx`:
- Line 17: The close/primary control in UI component UiSidebarRail (the element
with tabIndex={-1}) is currently removed from keyboard navigation; update the
element (in ui-sidebar-rail.tsx) to restore keyboard accessibility by removing
tabIndex or setting it to 0 (or otherwise ensuring it receives focus and handles
keyboard events), and verify the element supports Enter/Space activation and
appropriate ARIA attributes so it remains operable via keyboard.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar.tsx`:
- Around line 42-58: The mobile branch currently passes {...props} to UiSheet
(Dialog.Root) and ignores the container's className and DOM props; update the
mobile implementation so UiSheetContent (the actual mobile DOM node) also
receives the forwarded DOM props and merged className: forward relevant props
(e.g., id, data-*, aria-*, data-testid) and merge the incoming className with
the existing classes on UiSheetContent (while keeping the current inline style
and data attributes) instead of only spreading props onto UiSheet; ensure this
change touches the UiSheet / UiSheetContent usage around openMobile,
setOpenMobile, props and className so mobile gets the same attributes as
desktop.

In `@src/client/shared/ui/ui-tooltip/styles/ui-tooltip-content-styles.scss`:
- Around line 14-43: The side selectors currently override the state animations
because they also set animation-name; remove animation-name from the standalone
&[data-side='...'] rules and instead apply side-specific animation-names only
when the tooltip is opening by using combined selectors with the open states
(e.g. combine &[data-state='delayed-open'] and &[data-state='instant-open'] with
&[data-side='top'|'right'|'bottom'|'left'] to set
slideDownAndFade/slideLeftAndFade/slideUpAndFade/slideRightAndFade), while
keeping &[data-state='closed'] with animation-name: zoomOut and the existing
open state selectors that set zoomIn/zoomOut unchanged.

In `@src/client/widgets/profile-sidebar/profile-sidebar.tsx`:
- Around line 58-59: In ProfileSidebar (profile-sidebar.tsx) the Next.js Image
component is being given string dimensions ("31", "36"); change the width and
height props to numeric values (e.g., width={31} and height={36}) so they are
numbers rather than strings; search for other Image usages in this component
(and any JSX inside ProfileSidebar) and convert any quoted numeric width/height
props to numeric literals as well.

---

Minor comments:
In `@src/app/`(profile)/layout.tsx:
- Around line 21-26: The layout renders ProfileSidebar or
UserMobileNavigationBar based directly on useIsMobile(), which returns false on
first render and causes a desktop sidebar flash on mobile; wrap the responsive
branching in a "mounted" guard so you only decide between ProfileSidebar and
UserMobileNavigationBar after the component is mounted (e.g., add a local
hasMounted state set true in useEffect or reuse an existing useIsMounted hook)
and in layout.tsx defer rendering those two components until hasMounted is true
to prevent the initial incorrect desktop render.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-group-action-styles.scss`:
- Line 13: Replace the invalid CSS declaration "outline-style: hidden" (found in
sidebar-group-action-styles.scss and four other sidebar component files) with a
valid rule such as "outline: none;" or "outline-style: none;" to remove the
outline; update each file where "outline-style: hidden" appears and consider
using :focus-visible to restore accessible focus styling where needed.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-group-label-styles.scss`:
- Line 13: Replace the invalid declaration "outline-style: hidden" with a valid
outline reset such as "outline: none;" (or "outline-style: none;") in the same
rule so the browser will honor it; locate the rule containing the
"outline-style: hidden" declaration and update that line to "outline: none;" to
correctly remove the outline.

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-inset-styles.scss`:
- Around line 16-18: The collapsed-state selector is nested incorrectly: replace
the failing selector "&.peer[data-state='collapsed'] ~ &" with a selector that
targets .sidebar-inset when a sibling .sidebar-wrapper has the peer collapsed
state, e.g. ".sidebar-wrapper.peer[data-state='collapsed'] ~ &"; update the rule
block containing that selector so the margin-left: 0.5rem applies when the
.sidebar-wrapper element has the peer and data-state="collapsed".

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-menu-action-styles.scss`:
- Line 13: Replace the invalid CSS declaration "outline-style: hidden" with a
valid rule; change it to "outline: none" (or "outline-style: none") in the same
selector where "outline-style: hidden" appears so the browser will not drop the
rule; keep any accessibility considerations in mind (consider using
:focus-visible later if you need to hide outlines only for mouse users).

In `@src/client/shared/ui/ui-sidebar/styles/sidebar-rail-styles.scss`:
- Around line 35-41: The selectors `.in[data-side='left'] &` and
`.in[data-side='right'] &` are likely typos and prevent the resize cursors from
applying; change those selectors to `.group[data-side='left'] &` and
`.group[data-side='right'] &` respectively so they match the surrounding logic
and enable the intended w-resize/e-resize cursor behavior (update the two
selector lines referencing `.in` to `.group`).

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-menu-action.tsx`:
- Around line 16-25: The returned element uses Comp = asChild ? Slot.Root :
'button' and can render a native button without an explicit type (causing
accidental form submits); modify the component to accept an optional type prop
and pass type={!asChild ? (type ?? 'button') : undefined} into <Comp ... /> so
when asChild is false the native button defaults to 'button' and when asChild is
true the type is undefined (preserving Slot behavior), matching patterns used in
UiButton/UiIconButton/UiPurpleButton.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-menu-button.tsx`:
- Around line 34-43: The rendered menu button (variable "button" using "Comp" in
ui-sidebar-menu-button.tsx) lacks an explicit type, so clicks inside a form can
trigger submission; ensure a native button gets type="button" by passing
type="button" to the JSX element (place type="button" before {...props}) or set
a default in the component props (e.g., default type = 'button' when
destructuring) and, if "Comp" can be other elements, only apply this default
when Comp === 'button'.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx`:
- Around line 17-25: SidebarContextProps currently types setOpen and
setOpenMobile as (open: boolean) => void while the provider (see toggleSidebar
and the provider's internal setters) accepts React-style updater functions;
update the public types to accept React.Dispatch<React.SetStateAction<boolean>>
(or a union type like boolean | ((prev:boolean)=>boolean)) so callers can pass
updater functions, and if keeping updater support ensure any custom setter
(e.g., the wrapper around setOpen used by toggleSidebar) resolves the next value
from the previous state (invoke functional updater when a function is passed)
instead of relying on closed-over open; update the type for setOpen and
setOpenMobile and adjust the provider wrapper logic to handle functional
updaters accordingly.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar.tsx`:
- Around line 59-61: The Ukrainian SR-only copy in the UiSheetHeader is
misspelled; update the UiSheetDescription text inside the UiSheetHeader (where
UiSheetHeader, UiSheetTitle and UiSheetDescription are defined) to fix the typo
by changing "Відбражається лише на мобільних пристроях" to "Відображається лише
на мобільних пристроях".

---

Nitpick comments:
In `@src/app/client-layout.tsx`:
- Around line 25-28: MainLayout currently wraps children with UiTooltipProvider
(UiTooltipProvider in src/app/client-layout.tsx) while UiSidebarProvider also
creates a tooltip context (ui-sidebar-provider.tsx around the provider block),
causing nested tooltip contexts; pick a single owner—prefer the global
MainLayout—and remove the UiTooltipProvider wrapper from UiSidebarProvider
(delete the <UiTooltipProvider> ... </UiTooltipProvider> block in
UiSidebarProvider and rely on the existing UiTooltipProvider in
client-layout.tsx), ensuring consumers still import/use UiTooltip
hooks/components unchanged.

In `@src/client/shared/hooks/is-mobile/is-mobile.hook.ts`:
- Around line 10-15: The hook duplicates breakpoint logic by computing
window.innerWidth < MOBILE_BREAKPOINT in both the onChange handler and initial
setIsMobile; instead read the media query state directly from the MediaQueryList
(mql.matches) to keep updates consistent with the query. Update the onChange
callback (onChange) to call setIsMobile(mql.matches) and initialize state with
setIsMobile(mql.matches) instead of recalculating via MOBILE_BREAKPOINT, leaving
mql.addEventListener('change', onChange) and cleanup via
mql.removeEventListener('change', onChange) unchanged.

In `@src/client/shared/ui/ui-sheet/styles/ui-sheet-overlay-styles.scss`:
- Around line 7-24: Respect users' prefers-reduced-motion by wrapping the
open/close animation rules for &[data-state='open'] and &[data-state='closed']
(which currently use the fadeIn/fadeOut keyframes) in a `@media`
(prefers-reduced-motion: reduce) query and set animation: none (or a short
non-animated fallback, e.g., animation: none !important; opacity: 1 for open,
opacity: 0 for closed) so the fadeIn/fadeOut keyframes are not played for
reduced-motion users.

In `@src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx`:
- Around line 18-22: The current JSX spreads {...props} after setting
onClick={toggleSidebar}, allowing a consumer onClick to override toggleSidebar;
modify the component so the final click handler composes both: call
toggleSidebar and then call props.onClick (if present) rather than letting props
replace it — update the element that currently sets onClick={toggleSidebar} to
compute a combined handler (using toggleSidebar and props.onClick) or spread
props first and set onClick last so toggleSidebar always runs; refer to
toggleSidebar, props.onClick, and the element rendering the sidebar-rail to
locate where to change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 381af00f-ce95-4917-a3dc-9c32b9b09774

📥 Commits

Reviewing files that changed from the base of the PR and between 949c14a and 437cf11.

📒 Files selected for processing (79)
  • src/app/(profile)/layout.tsx
  • src/app/(profile)/main/layout.tsx
  • src/app/(profile)/profile/budget/regular-operations/page.tsx
  • src/app/(profile)/profile/settings/page.tsx
  • src/app/(profile)/settings/layout.tsx
  • src/app/client-layout.tsx
  • src/client/shared/components/sidebar-content/fin-sidebar-content.tsx
  • src/client/shared/components/sidebar-content/props/sidebar-content.props.ts
  • src/client/shared/hooks/get-active-route/get-active-route.hook.ts
  • src/client/shared/hooks/is-mobile/is-mobile.hook.ts
  • src/client/shared/models/nav-item.model.ts
  • src/client/shared/styles/theme.scss
  • src/client/shared/ui/ui-icon-button/props/icon-button.props.ts
  • src/client/shared/ui/ui-sheet/styles/ui-sheet-content-styles.scss
  • src/client/shared/ui/ui-sheet/styles/ui-sheet-overlay-styles.scss
  • src/client/shared/ui/ui-sheet/ui-sheet-close.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-content.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-description.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-footer.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-header.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-overlay.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-portal.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-title.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet-trigger.tsx
  • src/client/shared/ui/ui-sheet/ui-sheet.tsx
  • src/client/shared/ui/ui-sidebar/styles/sidebar-content-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-footer-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-group-action-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-group-content-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-group-label-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-group-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-header-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-inset-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-action-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-badge-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-button-variant-mixin.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-button-variants.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-item-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-skeleton-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-sub-button-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-sub-item-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-menu-sub-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-provider-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-rail-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-separator-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-styles.scss
  • src/client/shared/ui/ui-sidebar/styles/sidebar-trigger-styles.scss
  • src/client/shared/ui/ui-sidebar/ui-sidebar-content.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-footer.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-group-action.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-group-content.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-group-label.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-group.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-header-icon.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-header-title.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-header.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-inset.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-action.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-badge.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-button.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-item.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-skeleton.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-sub-button.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-sub-item.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu-sub.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-menu.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-separator.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar-trigger.tsx
  • src/client/shared/ui/ui-sidebar/ui-sidebar.tsx
  • src/client/shared/ui/ui-skeleton/ui-skeleton.tsx
  • src/client/shared/ui/ui-tooltip/styles/ui-tooltip-content-styles.scss
  • src/client/shared/ui/ui-tooltip/ui-tooltip-content.tsx
  • src/client/shared/ui/ui-tooltip/ui-tooltip-provider.tsx
  • src/client/shared/ui/ui-tooltip/ui-tooltip-trigger.tsx
  • src/client/shared/ui/ui-tooltip/ui-tooltip.tsx
  • src/client/widgets/profile-sidebar/profile-sidebar.tsx
💤 Files with no reviewable changes (2)
  • src/app/(profile)/main/layout.tsx
  • src/app/(profile)/settings/layout.tsx

Comment thread src/client/shared/hooks/get-active-route/get-active-route.hook.ts Outdated
Comment thread src/client/shared/ui/ui-icon-button/props/icon-button.props.ts
Comment thread src/client/shared/ui/ui-sidebar/styles/sidebar-styles.scss Outdated
Comment thread src/client/shared/ui/ui-sidebar/ui-sidebar-group-action.tsx
Comment thread src/client/shared/ui/ui-sidebar/ui-sidebar-header-icon.tsx
Comment thread src/client/shared/ui/ui-sidebar/ui-sidebar-provider.tsx
Comment thread src/client/shared/ui/ui-sidebar/ui-sidebar-rail.tsx
Comment thread src/client/shared/ui/ui-sidebar/ui-sidebar.tsx
Comment thread src/client/widgets/profile-sidebar/profile-sidebar.tsx
@Qunitee Qunitee merged commit f54c7b2 into feature/fin-021-parts/cards Apr 13, 2026
1 check passed
@dmytroreshetylo dmytroreshetylo deleted the feature/fin-021-parts/sidebar branch April 25, 2026 22:23
@coderabbitai coderabbitai Bot mentioned this pull request Jun 1, 2026
6 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Jun 14, 2026
5 tasks
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