diff --git a/app/client/src/actions/propertyPaneActions.ts b/app/client/src/actions/propertyPaneActions.ts
index 25a717123bed..2488a521694d 100644
--- a/app/client/src/actions/propertyPaneActions.ts
+++ b/app/client/src/actions/propertyPaneActions.ts
@@ -1,5 +1,8 @@
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
-import type { SelectedPropertyPanel } from "reducers/uiReducers/propertyPaneReducer";
+import type {
+ SelectedPropertyPanel,
+ ShowPropertyPanePayload,
+} from "reducers/uiReducers/propertyPaneReducer";
export const updateWidgetName = (widgetId: string, newName: string) => {
return {
@@ -115,12 +118,6 @@ export const createNewQueryFromActionCreator = (
};
};
-export interface ShowPropertyPanePayload {
- widgetId?: string;
- callForDragOrResize?: boolean;
- force: boolean;
-}
-
export const showPropertyPane = (payload: ShowPropertyPanePayload) => {
return {
type: ReduxActionTypes.SHOW_PROPERTY_PANE,
diff --git a/app/client/src/ce/entities/IDE/utils.ts b/app/client/src/ce/entities/IDE/utils.ts
deleted file mode 100644
index 02c6809e6015..000000000000
--- a/app/client/src/ce/entities/IDE/utils.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import type { EditorState } from "IDE/enums";
-import { IDE_TYPE, type IDEType } from "ee/IDE/Interfaces/IDETypes";
-import { IDEBasePaths } from "ee/IDE/constants/routes";
-import { matchPath } from "react-router";
-import { identifyEntityFromPath } from "navigation/FocusEntity";
-import {
- BUILDER_CUSTOM_PATH,
- BUILDER_PATH,
- BUILDER_PATH_DEPRECATED,
-} from "ee/constants/routes/appRoutes";
-import { saveActionName } from "actions/pluginActionActions";
-import { saveJSObjectName } from "actions/jsActionActions";
-import { EditorEntityTab } from "IDE/Interfaces/EditorTypes";
-import type { EntityItem } from "ee/IDE/Interfaces/EntityItem";
-import { getHasManageActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
-
-export interface SaveEntityName {
- params: {
- name: string;
- id: string;
- };
- segment: EditorEntityTab;
- entity?: EntityItem;
-}
-
-export const EDITOR_PATHS = [
- BUILDER_CUSTOM_PATH,
- BUILDER_PATH,
- BUILDER_PATH_DEPRECATED,
-];
-
-export function getCurrentAppState(currentUrl: string): EditorState {
- const entityInfo = identifyEntityFromPath(currentUrl);
-
- return entityInfo.appState;
-}
-
-export function getIDETypeByUrl(path: string): IDEType {
- for (const type in IDEBasePaths) {
- const basePaths = IDEBasePaths[type as IDEType];
-
- if (matchPath(path, { path: basePaths })) {
- return type as IDEType;
- }
- }
-
- return IDE_TYPE.None;
-}
-
-export function getBaseUrlsForIDEType(type: IDEType): string[] {
- return IDEBasePaths[type];
-}
-
-export const saveEntityName = ({ params, segment }: SaveEntityName) => {
- let saveNameAction = saveActionName(params);
-
- if (EditorEntityTab.JS === segment) {
- saveNameAction = saveJSObjectName(params);
- }
-
- return saveNameAction;
-};
-
-export interface EditableTabPermissions {
- isFeatureEnabled: boolean;
- entity?: EntityItem;
-}
-
-export const getEditableTabPermissions = ({
- entity,
- isFeatureEnabled,
-}: EditableTabPermissions) => {
- return getHasManageActionPermission(
- isFeatureEnabled,
- entity?.userPermissions || [],
- );
-};
diff --git a/app/client/src/ce/entities/IDE/utils/getBaseUrlsForIDEType.ts b/app/client/src/ce/entities/IDE/utils/getBaseUrlsForIDEType.ts
new file mode 100644
index 000000000000..47e4f44a8a57
--- /dev/null
+++ b/app/client/src/ce/entities/IDE/utils/getBaseUrlsForIDEType.ts
@@ -0,0 +1,6 @@
+import { IDEBasePaths } from "ee/IDE/constants/routes";
+import type { IDEType } from "ee/IDE/Interfaces/IDETypes";
+
+export function getBaseUrlsForIDEType(type: IDEType): string[] {
+ return IDEBasePaths[type];
+}
diff --git a/app/client/src/ce/entities/IDE/utils/getEditableTabPermissions.ts b/app/client/src/ce/entities/IDE/utils/getEditableTabPermissions.ts
new file mode 100644
index 000000000000..1103a3dca627
--- /dev/null
+++ b/app/client/src/ce/entities/IDE/utils/getEditableTabPermissions.ts
@@ -0,0 +1,29 @@
+import {
+ BUILDER_CUSTOM_PATH,
+ BUILDER_PATH,
+ BUILDER_PATH_DEPRECATED,
+} from "ee/constants/routes/appRoutes";
+
+import type { EntityItem } from "ee/IDE/Interfaces/EntityItem";
+import { getHasManageActionPermission } from "ee/utils/BusinessFeatures/permissionPageHelpers";
+
+export const EDITOR_PATHS = [
+ BUILDER_CUSTOM_PATH,
+ BUILDER_PATH,
+ BUILDER_PATH_DEPRECATED,
+];
+
+export interface EditableTabPermissions {
+ isFeatureEnabled: boolean;
+ entity?: EntityItem;
+}
+
+export const getEditableTabPermissions = ({
+ entity,
+ isFeatureEnabled,
+}: EditableTabPermissions) => {
+ return getHasManageActionPermission(
+ isFeatureEnabled,
+ entity?.userPermissions || [],
+ );
+};
diff --git a/app/client/src/ce/entities/IDE/utils/getIDETypeByUrl.ts b/app/client/src/ce/entities/IDE/utils/getIDETypeByUrl.ts
new file mode 100644
index 000000000000..e15d738a62a9
--- /dev/null
+++ b/app/client/src/ce/entities/IDE/utils/getIDETypeByUrl.ts
@@ -0,0 +1,15 @@
+import { IDEBasePaths } from "ee/IDE/constants/routes";
+import { IDE_TYPE, type IDEType } from "ee/IDE/Interfaces/IDETypes";
+import { matchPath } from "react-router-dom";
+
+export function getIDETypeByUrl(path: string): IDEType {
+ for (const type in IDEBasePaths) {
+ const basePaths = IDEBasePaths[type as IDEType];
+
+ if (matchPath(path, { path: basePaths })) {
+ return type as IDEType;
+ }
+ }
+
+ return IDE_TYPE.None;
+}
diff --git a/app/client/src/ce/entities/IDE/utils/index.ts b/app/client/src/ce/entities/IDE/utils/index.ts
new file mode 100644
index 000000000000..bd643ba0f39b
--- /dev/null
+++ b/app/client/src/ce/entities/IDE/utils/index.ts
@@ -0,0 +1,4 @@
+export { getBaseUrlsForIDEType } from "./getBaseUrlsForIDEType";
+export { getIDETypeByUrl } from "./getIDETypeByUrl";
+export { saveEntityName } from "./saveEntityName";
+export * from "./getEditableTabPermissions";
diff --git a/app/client/src/ce/entities/IDE/utils/saveEntityName.ts b/app/client/src/ce/entities/IDE/utils/saveEntityName.ts
new file mode 100644
index 000000000000..468d0b4c6213
--- /dev/null
+++ b/app/client/src/ce/entities/IDE/utils/saveEntityName.ts
@@ -0,0 +1,23 @@
+import { saveActionName } from "actions/pluginActionActions";
+import { EditorEntityTab } from "IDE/Interfaces/EditorTypes";
+import type { EntityItem } from "ee/IDE/Interfaces/EntityItem";
+import { saveJSObjectName } from "actions/jsActionActions";
+
+interface SaveEntityName {
+ params: {
+ name: string;
+ id: string;
+ };
+ segment: EditorEntityTab;
+ entity?: EntityItem;
+}
+
+export const saveEntityName = ({ params, segment }: SaveEntityName) => {
+ let saveNameAction = saveActionName(params);
+
+ if (EditorEntityTab.JS === segment) {
+ saveNameAction = saveJSObjectName(params);
+ }
+
+ return saveNameAction;
+};
diff --git a/app/client/src/ce/selectors/applicationSelectors.tsx b/app/client/src/ce/selectors/applicationSelectors.tsx
index e5ed07dfa373..8ba26824723c 100644
--- a/app/client/src/ce/selectors/applicationSelectors.tsx
+++ b/app/client/src/ce/selectors/applicationSelectors.tsx
@@ -9,12 +9,7 @@ import type { ApplicationPayload } from "entities/Application";
import Fuse from "fuse.js";
import type { GitApplicationMetadata } from "ee/api/ApplicationApi";
import { getApplicationsOfWorkspace } from "ee/selectors/selectedWorkspaceSelectors";
-import {
- NAVIGATION_SETTINGS,
- SIDEBAR_WIDTH,
- type ThemeSetting,
- defaultThemeSetting,
-} from "constants/AppConstants";
+import { type ThemeSetting, defaultThemeSetting } from "constants/AppConstants";
import { DEFAULT_EVALUATION_VERSION } from "constants/EvalConstants";
const fuzzySearchOptions = {
@@ -148,31 +143,6 @@ export const getAppSidebarPinned = (state: AppState) => {
return state.ui.applications.isAppSidebarPinned;
};
-/**
- * Return the width of the sidbar depending on the sidebar style.
- * If there isn't any sidebar or it is unpinned, return 0.
- */
-export const getSidebarWidth = (state: AppState) => {
- const navigationSetting =
- state.ui.applications.currentApplication?.applicationDetail
- ?.navigationSetting;
- const isAppSidebarPinned = state.ui.applications.isAppSidebarPinned;
-
- if (
- navigationSetting?.showNavbar !== false &&
- navigationSetting?.orientation === NAVIGATION_SETTINGS.ORIENTATION.SIDE &&
- isAppSidebarPinned
- ) {
- if (navigationSetting?.navStyle === NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL) {
- return SIDEBAR_WIDTH.MINIMAL;
- } else {
- return SIDEBAR_WIDTH.REGULAR;
- }
- }
-
- return 0;
-};
-
export const getIsUploadingNavigationLogo = (state: AppState) => {
return state.ui.applications.isUploadingNavigationLogo;
};
diff --git a/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx b/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx
index 5ad23ff2e567..cd4b0156014d 100644
--- a/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx
+++ b/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx
@@ -1,25 +1,26 @@
+// React and core libraries
import React, { useEffect, useState } from "react";
-import type { ApplicationPayload } from "entities/Application";
-import type { Page } from "entities/Page";
-import { NAVIGATION_SETTINGS, SIDEBAR_WIDTH } from "constants/AppConstants";
-import { get } from "lodash";
import { useDispatch, useSelector } from "react-redux";
import { useLocation } from "react-router";
-import { getSelectedAppTheme } from "selectors/appThemingSelectors";
-import ApplicationName from "./components/ApplicationName";
-import MenuItem from "./components/MenuItem";
-import ShareButton from "./components/ShareButton";
-import PrimaryCTA from "../PrimaryCTA";
-import { useHref } from "pages/Editor/utils";
-import { builderURL } from "ee/RouteBuilder";
-import { getCurrentBasePageId } from "selectors/editorSelectors";
-import type { User } from "constants/userConstants";
-import SidebarProfileComponent from "./components/SidebarProfileComponent";
-import CollapseButton from "./components/CollapseButton";
-import classNames from "classnames";
+
+// Third-party libraries
import { useMouse } from "@mantine/hooks";
-import { getAppSidebarPinned } from "ee/selectors/applicationSelectors";
+import { useEventCallback } from "usehooks-ts";
+import classNames from "classnames";
+import { get } from "lodash";
+
+// Application-specific imports
+import { IDE_HEADER_HEIGHT } from "@appsmith/ads";
+import { NAVIGATION_SETTINGS, SIDEBAR_WIDTH } from "constants/AppConstants";
+import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";
+import { builderURL } from "ee/RouteBuilder";
import { setIsAppSidebarPinned } from "ee/actions/applicationActions";
+import NavigationLogo from "ee/pages/AppViewer/NavigationLogo";
+import { getAppSidebarPinned } from "ee/selectors/applicationSelectors";
+import { getCurrentBasePageId } from "selectors/editorSelectors";
+import { getSelectedAppTheme } from "selectors/appThemingSelectors";
+import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
+import { selectCombinedPreviewMode } from "selectors/gitModSelectors";
import {
StyledCtaContainer,
StyledFooter,
@@ -27,13 +28,24 @@ import {
StyledMenuContainer,
StyledSidebar,
} from "./Sidebar.styled";
-import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
-import NavigationLogo from "ee/pages/AppViewer/NavigationLogo";
-import MenuItemContainer from "./components/MenuItemContainer";
+
+// Type imports
+import type { ApplicationPayload } from "entities/Application";
+import type { Page } from "entities/Page";
+import type { User } from "constants/userConstants";
+
+// Utility/Helper functions
+import { useHref } from "pages/Editor/utils";
+
+// Imports with relative paths
+import PrimaryCTA from "../PrimaryCTA";
+import ApplicationName from "./components/ApplicationName";
import BackToAppsButton from "./components/BackToAppsButton";
-import { IDE_HEADER_HEIGHT } from "@appsmith/ads";
-import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants";
-import { selectCombinedPreviewMode } from "selectors/gitModSelectors";
+import CollapseButton from "./components/CollapseButton";
+import MenuItem from "./components/MenuItem";
+import MenuItemContainer from "./components/MenuItemContainer";
+import ShareButton from "./components/ShareButton";
+import SidebarProfileComponent from "./components/SidebarProfileComponent";
interface SidebarProps {
currentApplicationDetails?: ApplicationPayload;
@@ -84,42 +96,39 @@ export function Sidebar(props: SidebarProps) {
getIsAppSettingsPaneWithNavigationTabOpen,
);
- useEffect(() => {
- setQuery(window.location.search);
- }, [location]);
+ useEffect(
+ function updateQueryFromLocationEffect() {
+ setQuery(window.location.search);
+ },
+ [location],
+ );
- // Mark default page as first page
- const appPages = pages;
+ useEffect(
+ function updateSidebarStateFromPinnedEffect() {
+ setIsOpen(isPinned);
+ },
+ [isPinned],
+ );
- if (appPages.length > 1) {
- appPages.forEach((item, i) => {
- if (item.isDefault) {
- appPages.splice(i, 1);
- appPages.unshift(item);
+ useEffect(
+ function handleSidebarVisibilityEffect() {
+ // When the sidebar is unpinned -
+ if (!isPinned) {
+ if (x <= 20) {
+ // 1. Open the sidebar when hovering on the left edge of the screen
+ setIsOpen(true);
+ } else if (x > SIDEBAR_WIDTH.REGULAR) {
+ // 2. Close the sidebar when the mouse moves out of it
+ setIsOpen(false);
+ }
}
- });
- }
-
- useEffect(() => {
- setIsOpen(isPinned);
- }, [isPinned]);
-
- useEffect(() => {
- // When the sidebar is unpinned -
- if (!isPinned) {
- if (x <= 20) {
- // 1. Open the sidebar when hovering on the left edge of the screen
- setIsOpen(true);
- } else if (x > SIDEBAR_WIDTH.REGULAR) {
- // 2. Close the sidebar when the mouse moves out of it
- setIsOpen(false);
- }
- }
- }, [x]);
+ },
+ [x, isPinned],
+ );
- const setIsPinned = (isPinned: boolean) => {
+ const setIsPinned = useEventCallback((isPinned: boolean) => {
dispatch(setIsAppSidebarPinned(isPinned));
- };
+ });
const calculateSidebarHeight = () => {
let prefix = `calc( 100vh - `;
@@ -182,30 +191,32 @@ export function Sidebar(props: SidebarProps) {
)}
-
- {appPages.map((page) => {
- return (
- -1}
- key={page.pageId}
- >
-
+ );
+ })}
+
+ )}
{props.showUserSettings && (
diff --git a/app/client/src/pages/AppViewer/Navigation/index.tsx b/app/client/src/pages/AppViewer/Navigation/index.tsx
index 6056575735be..e9458b107a66 100644
--- a/app/client/src/pages/AppViewer/Navigation/index.tsx
+++ b/app/client/src/pages/AppViewer/Navigation/index.tsx
@@ -1,108 +1,106 @@
-import React, { useEffect, useRef, useState } from "react";
+// React and core libraries
+import React, { useEffect, useMemo, useRef, useState } from "react";
import { useLocation } from "react-router-dom";
-import { ThemeProvider } from "styled-components";
-import type { ApplicationPayload } from "entities/Application";
+
+// Third-party libraries
import { useDispatch, useSelector } from "react-redux";
+import { ThemeProvider } from "styled-components";
+
+// Type imports
import type { AppState } from "ee/reducers";
+import type { ApplicationPayload } from "entities/Application";
+
+// Application-specific imports
+import { setAppViewHeaderHeight } from "actions/appViewActions";
+import { NAVIGATION_SETTINGS } from "constants/AppConstants";
+import { builderURL } from "ee/RouteBuilder";
+import { getCurrentApplication } from "ee/selectors/applicationSelectors";
+import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors";
+import AnalyticsUtil from "ee/utils/AnalyticsUtil";
+import PageMenu from "pages/AppViewer/PageMenu";
+import { useHref } from "pages/Editor/utils";
import {
getCurrentBasePageId,
getViewModePageList,
} from "selectors/editorSelectors";
-import { getCurrentWorkspaceId } from "ee/selectors/selectedWorkspaceSelectors";
-import { getCurrentUser } from "selectors/usersSelectors";
-import type { User } from "constants/userConstants";
-import type { Theme } from "constants/DefaultTheme";
import { getThemeDetails, ThemeMode } from "selectors/themeSelectors";
+import { getCurrentUser } from "selectors/usersSelectors";
+import { useIsMobileDevice } from "utils/hooks/useDeviceDetect";
+
+// Relative imports
import HtmlTitle from "../AppViewerHtmlTitle";
-import { NAVIGATION_SETTINGS } from "constants/AppConstants";
-import PageMenu from "pages/AppViewer/PageMenu";
-import { useHref } from "pages/Editor/utils";
-import { builderURL } from "ee/RouteBuilder";
-import TopHeader from "./components/TopHeader";
import Sidebar from "./Sidebar";
-import { getCurrentApplication } from "ee/selectors/applicationSelectors";
-import { useIsMobileDevice } from "utils/hooks/useDeviceDetect";
-import { setAppViewHeaderHeight } from "actions/appViewActions";
-import AnalyticsUtil from "ee/utils/AnalyticsUtil";
+import TopHeader from "./components/TopHeader";
export function Navigation() {
+ const dispatch = useDispatch();
const { search } = useLocation();
- const queryParams = new URLSearchParams(search);
- const isEmbed = queryParams.get("embed") === "true";
- const showNavBar = queryParams.get("navbar") === "true";
- const hideHeader = isEmbed && !showNavBar;
const [isMenuOpen, setMenuOpen] = useState(false);
const headerRef = useRef(null);
+ const isMobile = useIsMobileDevice();
const basePageId = useSelector(getCurrentBasePageId);
const editorURL = useHref(builderURL, { basePageId });
- const currentWorkspaceId: string = useSelector(getCurrentWorkspaceId);
- const currentUser: User | undefined = useSelector(getCurrentUser);
- const lightTheme: Theme = useSelector((state: AppState) =>
+
+ const currentWorkspaceId = useSelector(getCurrentWorkspaceId);
+ const currentUser = useSelector(getCurrentUser);
+ const lightTheme = useSelector((state: AppState) =>
getThemeDetails(state, ThemeMode.LIGHT),
);
const currentApplicationDetails: ApplicationPayload | undefined = useSelector(
getCurrentApplication,
);
const pages = useSelector(getViewModePageList);
- const isMobile = useIsMobileDevice();
- const dispatch = useDispatch();
- useEffect(() => {
- const header = document.querySelector(".js-appviewer-header");
-
- dispatch(setAppViewHeaderHeight(header?.clientHeight || 0));
+ const queryParams = new URLSearchParams(search);
+ const isEmbed = queryParams.get("embed") === "true";
+ const forceShowNavBar = queryParams.get("navbar") === "true";
+ const hideHeader = isEmbed && !forceShowNavBar;
- return () => {
- dispatch(setAppViewHeaderHeight(0));
- };
- }, [
- currentApplicationDetails?.applicationDetail?.navigationSetting?.navStyle,
+ const navStyle =
+ currentApplicationDetails?.applicationDetail?.navigationSetting?.navStyle;
+ const orientation =
currentApplicationDetails?.applicationDetail?.navigationSetting
- ?.orientation,
- ]);
- useEffect(() => {
- if (showNavBar && currentApplicationDetails) {
- AnalyticsUtil.logEvent("APP_VIEWED_WITH_NAVBAR", {
- id: currentApplicationDetails.id,
- });
- }
- }, [showNavBar, currentApplicationDetails]);
-
- const renderNavigation = () => {
- if (
- currentApplicationDetails?.applicationDetail?.navigationSetting
- ?.orientation === NAVIGATION_SETTINGS.ORIENTATION.SIDE
- ) {
- return (
- <>
- {/*
- * We need to add top header since we want the current mobile
- * navigation experience until we create the new sidebar for mobile.
- */}
- {isMobile ? (
-
- ) : (
-
- )}
- >
- );
- }
-
- return (
+ ?.orientation;
+ const applicationId = currentApplicationDetails?.id;
+
+ const showNavbar =
+ currentApplicationDetails?.applicationDetail?.navigationSetting?.showNavbar;
+
+ // TODO: refactor this to not directly reference a DOM element by class defined elsewhere
+ useEffect(
+ function adjustHeaderHeightEffect() {
+ const header = document.querySelector(".js-appviewer-header");
+
+ dispatch(setAppViewHeaderHeight(header?.clientHeight || 0));
+
+ return () => {
+ dispatch(setAppViewHeaderHeight(0));
+ };
+ },
+ [navStyle, orientation, dispatch],
+ );
+
+ useEffect(
+ function trackNavbarAnalyticsEffect() {
+ if (forceShowNavBar && applicationId) {
+ AnalyticsUtil.logEvent("APP_VIEWED_WITH_NAVBAR", {
+ id: applicationId,
+ });
+ }
+ },
+ [forceShowNavBar, applicationId],
+ );
+
+ const navigation = useMemo(() => {
+ return orientation === NAVIGATION_SETTINGS.ORIENTATION.SIDE && !isMobile ? (
+
+ ) : (
);
- };
+ }, [
+ currentApplicationDetails,
+ currentUser,
+ currentWorkspaceId,
+ isEmbed,
+ isMenuOpen,
+ isMobile,
+ orientation,
+ pages,
+ ]);
if (hideHeader) return ;
@@ -124,8 +131,7 @@ export function Navigation() {
and we are creating the default values only when any nav settings via the
settings pane has changed, we need to hide the navbar ONLY when the showNavbar
setting is explicitly set to false by the user via the settings pane. */}
- {currentApplicationDetails?.applicationDetail?.navigationSetting
- ?.showNavbar !== false && renderNavigation()}
+ {showNavbar && navigation}
{/* Mobile Sidebar */}
{
const currentApplicationDetails = useSelector(getCurrentApplication);
const isAppSidebarPinned = useSelector(getAppSidebarPinned);
const isMobile = useIsMobileDevice();
- const _sidebarWidth = useSelector(getSidebarWidth);
+ const _sidebarWidth = useSidebarWidth();
const { search } = useLocation();
const queryParams = new URLSearchParams(search);
diff --git a/app/client/src/utils/hooks/useSidebarWidth.ts b/app/client/src/utils/hooks/useSidebarWidth.ts
new file mode 100644
index 000000000000..216520b67262
--- /dev/null
+++ b/app/client/src/utils/hooks/useSidebarWidth.ts
@@ -0,0 +1,31 @@
+// React and core libraries
+import { useSelector } from "react-redux";
+
+// Application-specific imports
+import { getApplicationsState } from "ee/selectors/applicationSelectors";
+import { NAVIGATION_SETTINGS, SIDEBAR_WIDTH } from "constants/AppConstants";
+
+/**
+ * Return the width of the sidebar depending on the sidebar style.
+ * If there isn't any sidebar or it is unpinned, return 0.
+ */
+export const useSidebarWidth = () => {
+ const applications = useSelector(getApplicationsState);
+ const navigationSetting =
+ applications.currentApplication?.applicationDetail?.navigationSetting;
+ const isAppSidebarPinned = applications.isAppSidebarPinned;
+
+ if (
+ navigationSetting?.showNavbar !== false &&
+ navigationSetting?.orientation === NAVIGATION_SETTINGS.ORIENTATION.SIDE &&
+ isAppSidebarPinned
+ ) {
+ if (navigationSetting?.navStyle === NAVIGATION_SETTINGS.NAV_STYLE.MINIMAL) {
+ return SIDEBAR_WIDTH.MINIMAL;
+ } else {
+ return SIDEBAR_WIDTH.REGULAR;
+ }
+ }
+
+ return 0;
+};