diff --git a/frontend/src/container/AppLayout/AppLayout.styles.scss b/frontend/src/container/AppLayout/AppLayout.styles.scss index 220268d010..a34929618b 100644 --- a/frontend/src/container/AppLayout/AppLayout.styles.scss +++ b/frontend/src/container/AppLayout/AppLayout.styles.scss @@ -48,7 +48,7 @@ } .app-content { - width: calc(100% - 54px); // width of the sidebar + width: calc(100% - 64px); // width of the sidebar z-index: 0; margin: 0 auto; diff --git a/frontend/src/container/InfraMonitoringK8s/EntityDetailsUtils/EntityEvents/entityEvents.styles.scss b/frontend/src/container/InfraMonitoringK8s/EntityDetailsUtils/EntityEvents/entityEvents.styles.scss index 60fe9c3efa..0feef33b0f 100644 --- a/frontend/src/container/InfraMonitoringK8s/EntityDetailsUtils/EntityEvents/entityEvents.styles.scss +++ b/frontend/src/container/InfraMonitoringK8s/EntityDetailsUtils/EntityEvents/entityEvents.styles.scss @@ -168,7 +168,7 @@ .ant-pagination { position: fixed; bottom: 0; - width: calc(100% - 54px); + width: calc(100% - 64px); background: rgb(18, 19, 23); padding: 16px; margin: 0; diff --git a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss index 4cd55323d5..4587023d9e 100644 --- a/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss +++ b/frontend/src/container/InfraMonitoringK8s/InfraMonitoringK8s.styles.scss @@ -442,7 +442,7 @@ .ant-pagination { position: fixed; bottom: 0; - width: calc(100% - 54px); + width: calc(100% - 64px); background: var(--bg-ink-500); padding: 16px; margin: 0; diff --git a/frontend/src/container/ListOfDashboard/DashboardTemplates/DashboardTemplatesModal.styles.scss b/frontend/src/container/ListOfDashboard/DashboardTemplates/DashboardTemplatesModal.styles.scss index 4907374684..51fb567364 100644 --- a/frontend/src/container/ListOfDashboard/DashboardTemplates/DashboardTemplatesModal.styles.scss +++ b/frontend/src/container/ListOfDashboard/DashboardTemplates/DashboardTemplatesModal.styles.scss @@ -58,7 +58,7 @@ overflow-y: auto; box-sizing: border-box; - height: calc(100% - 54px); + height: calc(100% - 64px); &::-webkit-scrollbar { height: 1rem; diff --git a/frontend/src/container/MetricsExplorer/Summary/Summary.styles.scss b/frontend/src/container/MetricsExplorer/Summary/Summary.styles.scss index ffefe5bf20..f135ebf3e1 100644 --- a/frontend/src/container/MetricsExplorer/Summary/Summary.styles.scss +++ b/frontend/src/container/MetricsExplorer/Summary/Summary.styles.scss @@ -194,7 +194,7 @@ .ant-pagination { position: fixed; bottom: 0; - width: calc(100% - 54px); + width: calc(100% - 64px); background: var(--bg-ink-500); padding: 16px; margin: 0; diff --git a/frontend/src/container/SideNav/NavItem/NavItem.styles.scss b/frontend/src/container/SideNav/NavItem/NavItem.styles.scss index e7db8770c5..7f49a28acb 100644 --- a/frontend/src/container/SideNav/NavItem/NavItem.styles.scss +++ b/frontend/src/container/SideNav/NavItem/NavItem.styles.scss @@ -13,12 +13,6 @@ .nav-item-active-marker { background: #4e74f8; } - - .nav-item-data { - .nav-item-label { - color: var(--bg-vanilla-100, #fff); - } - } } &.disabled { @@ -33,14 +27,14 @@ .nav-item-data { color: white; - background: var(--bg-slate-500, #161922); + background: var(--Slate-500, #161922); } } &.active { .nav-item-data { color: white; - background: var(--bg-slate-500, #161922); + background: var(--Slate-500, #161922); // color: #3f5ecc; } } @@ -56,9 +50,9 @@ .nav-item-data { flex-grow: 1; - max-width: calc(100% - 20px); + max-width: calc(100% - 24px); display: flex; - margin: 0px 0px 0px 6px; + margin: 0px 8px; padding: 2px 8px; flex-direction: row; align-items: center; @@ -74,7 +68,7 @@ background: transparent; - transition: 0.08s all ease; + transition: 0.2s all linear; border-radius: 3px; @@ -106,7 +100,7 @@ &:hover { .nav-item-label { - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); } .nav-item-pin-icon { @@ -126,12 +120,6 @@ .nav-item-active-marker { background: #4e74f8; } - - .nav-item-data { - .nav-item-label { - color: var(--bg-slate-500); - } - } } &:hover { diff --git a/frontend/src/container/SideNav/NavItem/NavItem.tsx b/frontend/src/container/SideNav/NavItem/NavItem.tsx index e63ac7413e..a928b71a8d 100644 --- a/frontend/src/container/SideNav/NavItem/NavItem.tsx +++ b/frontend/src/container/SideNav/NavItem/NavItem.tsx @@ -2,7 +2,7 @@ /* eslint-disable jsx-a11y/click-events-have-key-events */ import './NavItem.styles.scss'; -import { Tag, Tooltip } from 'antd'; +import { Tag } from 'antd'; import cx from 'classnames'; import { Pin, PinOff } from 'lucide-react'; @@ -74,25 +74,21 @@ export default function NavItem({ )} {onTogglePin && !isPinned && ( - - - + )} {onTogglePin && isPinned && ( - - - + )} diff --git a/frontend/src/container/SideNav/SideNav.styles.scss b/frontend/src/container/SideNav/SideNav.styles.scss index 1b443e287b..fdbe6193c1 100644 --- a/frontend/src/container/SideNav/SideNav.styles.scss +++ b/frontend/src/container/SideNav/SideNav.styles.scss @@ -1,5 +1,5 @@ .sidenav-container { - width: 54px; + width: 64px; height: 100%; position: relative; z-index: 1; @@ -10,60 +10,47 @@ } .sideNav { - flex: 0 0 54px; + flex: 0 0 64px; height: 100%; - max-width: 54px; - min-width: 54px; - width: 54px; - border-right: 1px solid var(--bg-slate-500, #161922); - background: var(--bg-ink-500, #0b0c0e); + max-width: 64px; + min-width: 64px; + width: 64px; + border-right: 1px solid var(--Slate-500, #161922); + background: var(--Ink-500, #0b0c0e); padding-bottom: 48px; - transition: all 0.08s ease, background 0s, border 0s; + transition: all 0.2s, background 0s, border 0s; .brand-container { - padding: 8px 15px; + padding: 8px 18px; max-width: 100%; - background: transparent; } .brand-company-meta { display: flex; - align-items: center; - gap: 6px; - flex-shrink: 0; - width: 100%; - justify-content: center; + gap: 8px; } .brand { display: flex; align-items: center; - justify-content: center; max-width: 100%; overflow: hidden; gap: 32px; height: 32px; - width: 100%; .brand-logo { display: flex; align-items: center; - justify-content: center; + justify-content: space-between; gap: 8px; - flex-shrink: 0; - width: 20px; - height: 16px; - position: relative; cursor: pointer; img { height: 16px; - width: auto; - display: block; } .brand-logo-name { @@ -79,10 +66,6 @@ .brand-title-section { display: none; - flex-shrink: 0; - align-items: center; - gap: 0; - position: relative; .license-type { display: flex; @@ -93,7 +76,7 @@ color: var(--bg-vanilla-100); border-radius: 4px 0px 0px 4px; - background: var(--bg-slate-400, #1d212d); + background: var(--Slate-400, #1d212d); text-align: center; font-family: Inter; @@ -115,11 +98,11 @@ gap: 6px; border-radius: 0px 4px 4px 0px; - background: var(--bg-slate-300, #242834); + background: var(--Slate-300, #242834); } .version { - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); text-align: center; font-variant-numeric: lining-nums tabular-nums slashed-zero; font-feature-settings: 'salt' on; @@ -173,48 +156,24 @@ .get-started-nav-items { display: flex; - margin: 4px 10px 12px 8px; + margin: 4px 13px 12px 10px; .get-started-btn { display: flex; align-items: center; justify-content: center; padding: 8px; + margin-left: 2px; gap: 8px; width: 100%; height: 32px; border-radius: 3px; - border: 1px solid var(--bg-slate-400, #1d212d); - background: var(--bg-slate-500, #161922); + border: 1px solid var(--Slate-400, #1d212d); + background: var(--Slate-500, #161922); box-shadow: none !important; - - color: var(--bg-vanilla-400, #c0c1c3); - - svg { - color: var(--bg-vanilla-400, #c0c1c3); - } - - .nav-item-label { - color: var(--bg-vanilla-400, #c0c1c3); - } - - &:hover:not(:disabled) { - background: var(--bg-slate-400, #1d212d); - border-color: var(--bg-slate-400, #1d212d); - - color: var(--bg-vanilla-100, #fff); - - svg { - color: var(--bg-vanilla-100, #fff); - } - - .nav-item-label { - color: var(--bg-vanilla-100, #fff); - } - } } } @@ -233,10 +192,6 @@ width: 100%; } - .nav-item { - margin-bottom: 6px; - } - .nav-top-section { display: flex; flex-direction: column; @@ -272,7 +227,7 @@ } .nav-section-title { - color: var(--bg-slate-50, #62687c); + color: var(--Slate-50, #62687c); font-family: Inter; font-size: 11px; font-style: normal; @@ -286,7 +241,7 @@ align-items: center; gap: 8px; - padding: 0 17px; + padding: 0 20px; .nav-section-title-text { display: none; @@ -295,17 +250,11 @@ .nav-section-title-icon { display: flex; align-items: center; - transition: opacity 0.08s ease, transform 0.08s ease; &.reorder { display: none; cursor: pointer; margin-left: auto; - transition: color 0.2s; - - &:hover { - color: var(--bg-vanilla-100, #fff); - } } } @@ -319,7 +268,7 @@ } .nav-section-subtitle { - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); font-family: Inter; font-size: 11px; font-style: normal; @@ -327,20 +276,20 @@ line-height: 14px; /* 150% */ letter-spacing: 0.4px; - padding: 6px 20px; + padding: 0 20px; opacity: 0.6; display: none; - transition: all 0.08s ease, background 0s, border 0s; - transition-delay: 0.03s; + transition: all 0.3s, background 0s, border 0s; + transition-delay: 0.1s; } .nav-items-section { margin-top: 8px; display: flex; flex-direction: column; - transition: all 0.08s ease; + gap: 4px; } } @@ -353,7 +302,7 @@ .nav-items-section { opacity: 0; transform: translateY(-10px); - transition: all 0.1s ease; + transition: all 0.4s ease; overflow: hidden; height: 0; } @@ -363,34 +312,11 @@ .nav-items-section { opacity: 1; transform: translateY(0); - transition: all 0.1s ease; + transition: all 0.4s ease; overflow: hidden; height: auto; } } - - &.sidebar-collapsed { - .nav-title-section { - display: none; - } - - .nav-items-section { - margin-top: 0; - opacity: 1; - transform: translateY(0); - transition: all 0.08s ease; - height: auto; - overflow: visible; - } - } - } - - .shortcut-nav-items { - &.sidebar-collapsed { - .nav-items-section { - margin-top: 0; - } - } } .scroll-for-more-container { @@ -400,7 +326,7 @@ width: 100%; bottom: 12px; bottom: 8px; - margin-left: 43px; + margin-left: 50px; .scroll-for-more { display: flex; @@ -444,6 +370,8 @@ overflow-y: auto; overflow-x: hidden; + padding-top: 12px; + .secondary-nav-items { display: flex; flex-direction: column; @@ -453,10 +381,10 @@ overflow-x: hidden; padding: 8px 0; max-width: 100%; - width: 54px; + width: 64px; // width: 100%; // temp - transition: all 0.08s ease, background 0s, border 0s; + transition: all 0.2s, background 0s, border 0s; background: linear-gradient(180deg, rgba(11, 12, 14, 0) 0%, #0b0c0e 27.11%); @@ -485,7 +413,7 @@ &.scroll-available { .nav-bottom-section { - border-top: 1px solid var(--bg-slate-500, #161922); + border-top: 1px solid var(--Slate-500, #161922); } } } @@ -496,53 +424,24 @@ } &.collapsed { - flex: 0 0 54px; - max-width: 54px; - min-width: 54px; - width: 54px; + flex: 0 0 64px; + max-width: 64px; + min-width: 64px; + width: 64px; .nav-wrapper { .nav-top-section { .shortcut-nav-items { - .nav-section-title { - display: none; - } - + .nav-section-title, .nav-section-subtitle { display: none; } - - .nav-items-section { - display: flex; - margin-top: 0; - } - - .nav-title-section { - margin-top: 0; - margin-bottom: 0; - gap: 0; - } - } - - .more-nav-items { - .nav-section-title { - display: none; - } - - .nav-items-section { - display: flex; - margin-top: 0; - } - - .nav-title-section { - display: none; - } } } .nav-bottom-section { .secondary-nav-items { - width: 54px; + width: 64px; } } } @@ -567,7 +466,7 @@ border-radius: 12px; background: var(--Robin-500, #4e74f8); - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); font-variant-numeric: lining-nums tabular-nums slashed-zero; font-feature-settings: 'case' on, 'cpsp' on, 'dlig' on, 'salt' on; font-family: Inter; @@ -580,7 +479,7 @@ } .sidenav-beta-tag { - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); font-variant-numeric: lining-nums tabular-nums slashed-zero; font-feature-settings: 'case' on, 'cpsp' on, 'dlig' on, 'salt' on; font-family: Inter; @@ -595,47 +494,7 @@ background: var(--bg-slate-300); } - &:not(.pinned) { - .nav-item { - .nav-item-data { - justify-content: center; - } - } - - .shortcut-nav-items, - .more-nav-items { - .nav-section-title { - padding: 0 17px; - - .nav-section-title-icon { - display: none; - } - } - } - - &.dropdown-open { - .nav-item { - .nav-item-data { - flex-grow: 1; - justify-content: flex-start; - } - } - - .shortcut-nav-items, - .more-nav-items { - .nav-section-title { - padding: 0 17px; - - .nav-section-title-icon { - display: flex; - } - } - } - } - } - - &:not(.pinned):hover, - &.dropdown-open { + &:hover { flex: 0 0 240px; max-width: 240px; min-width: 240px; @@ -646,17 +505,8 @@ z-index: 10; background: #0b0c0e; - .brand-container { - padding: 8px 15px; - } - .brand { - justify-content: flex-start; - - .brand-company-meta { - justify-content: flex-start; - width: 100%; - } + justify-content: space-between; .brand-title-section { display: flex; @@ -683,11 +533,6 @@ .nav-section-title-icon { &.reorder { display: flex; - transition: color 0.2s; - - &:hover { - color: var(--bg-vanilla-100, #fff); - } } } } @@ -729,7 +574,7 @@ flex-direction: row; gap: 3px; border-radius: 20px; - background: var(--bg-slate-400, #1d212d); + background: var(--Slate-400, #1d212d); /* Drop Shadow */ box-shadow: 0px 103px 12px 0px rgba(0, 0, 0, 0.01), @@ -745,7 +590,7 @@ width: 140px; .scroll-for-more-label { - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); font-family: Inter; font-size: 12px; font-style: normal; @@ -786,13 +631,6 @@ align-items: flex-start; } } - - .nav-item { - .nav-item-data { - flex-grow: 1; - justify-content: flex-start; - } - } } .get-started-nav-items { @@ -826,17 +664,8 @@ z-index: 10; background: #0b0c0e; - .brand-container { - padding: 8px 15px; - } - .brand { - justify-content: flex-start; - - .brand-company-meta { - justify-content: flex-start; - width: 100%; - } + justify-content: space-between; .brand-title-section { display: flex; @@ -863,11 +692,6 @@ .nav-section-title-icon { &.reorder { display: flex; - transition: color 0.2s; - - &:hover { - color: var(--bg-vanilla-100, #fff); - } } } } @@ -909,7 +733,7 @@ flex-direction: row; gap: 3px; border-radius: 20px; - background: var(--bg-slate-400, #1d212d); + background: var(--Slate-400, #1d212d); /* Drop Shadow */ box-shadow: 0px 103px 12px 0px rgba(0, 0, 0, 0.01), @@ -927,7 +751,7 @@ .scroll-for-more-label { display: block; - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); font-family: Inter; font-size: 12px; font-style: normal; @@ -1032,7 +856,7 @@ .ant-dropdown-menu-item { .ant-dropdown-menu-title-content { - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); font-family: Inter; font-size: 12px; font-style: normal; @@ -1040,12 +864,6 @@ line-height: normal; letter-spacing: 0.14px; } - - &:hover:not(.ant-dropdown-menu-item-disabled) { - .ant-dropdown-menu-title-content { - color: var(--bg-vanilla-100, #fff); - } - } } } } @@ -1057,7 +875,7 @@ gap: 8px; .user-settings-dropdown-label-text { - color: var(--bg-slate-50, #62687c); + color: var(--Slate-50, #62687c); font-family: Inter; font-size: 10px; font-family: Inter; @@ -1069,7 +887,7 @@ } .user-settings-dropdown-label-email { - color: var(--bg-vanilla-400, #c0c1c3); + color: var(--Vanilla-400, #c0c1c3); font-family: Inter; font-size: 12px; font-style: normal; @@ -1079,16 +897,12 @@ } .ant-dropdown-menu-item-divider { - background-color: var(--bg-slate-500, #161922) !important; + background-color: var(--Slate-500, #161922) !important; } .ant-dropdown-menu-item-disabled { opacity: 0.7; } - - .ant-dropdown-menu { - width: 100% !important; - } } .settings-dropdown, @@ -1098,27 +912,6 @@ } } -.secondary-nav-items { - .nav-item { - position: relative; - - .nav-item-active-marker { - position: absolute; - left: -5px; - top: 50%; - transform: translateY(-50%); - margin: 0; - width: 8px; - height: 24px; - z-index: 1; - } - } - - .nav-item-data { - margin-left: 8px !important; - } -} - .reorder-shortcut-nav-items-modal { width: 384px !important; @@ -1235,6 +1028,7 @@ display: flex; align-items: center; border-radius: 2px; + border-radius: 2px; background: var(--Robin-500, #4e74f8) !important; color: var(--bg-vanilla-100) !important; font-family: Inter; @@ -1244,10 +1038,10 @@ line-height: 24px; &.secondary-btn { - background-color: var(--bg-slate-500, #161922) !important; + background-color: var(--Slate-500, #161922) !important; border: 1px solid var(--bg-slate-500) !important; - color: var(--bg-vanilla-400, #c0c1c3) !important; + color: var(--Vanilla-400, #c0c1c3) !important; /* button/ small */ font-family: Inter; @@ -1270,10 +1064,6 @@ } } -.help-support-dropdown li.ant-dropdown-menu-item-divider { - background-color: var(--bg-slate-500, #161922) !important; -} - .lightMode { .sideNav { background: var(--bg-vanilla-100); @@ -1305,32 +1095,8 @@ .get-started-nav-items { .get-started-btn { border: 1px solid var(--bg-vanilla-300); - background: var(--bg-vanilla-200); - color: var(--bg-slate-50, #62687c); - - svg { - color: var(--bg-slate-50, #62687c); - } - - .nav-item-label { - color: var(--bg-ink-400, #62687c); - } - - // Hover state (light mode) - &:hover:not(:disabled) { - background: var(--bg-vanilla-300); - border-color: var(--bg-vanilla-300); - - color: var(--bg-slate-500, #161922); - - svg { - color: var(--bg-slate-500, #161922); - } - - .nav-item-label { - color: var(--bg-slate-500, #161922); - } - } + background: var(--bg-vanilla-100); + color: var(--bg-ink-400); } } @@ -1342,25 +1108,7 @@ } } - .brand-container { - background: transparent; - } - .nav-wrapper { - .nav-top-section { - .shortcut-nav-items { - .nav-section-title { - .nav-section-title-icon { - &.reorder { - &:hover { - color: var(--bg-slate-400, #1d212d); - } - } - } - } - } - } - .secondary-nav-items { border-top: 1px solid var(--bg-vanilla-300); @@ -1375,43 +1123,8 @@ } } - &.pinned { - .nav-wrapper { - .nav-top-section { - .shortcut-nav-items { - .nav-section-title { - .nav-section-title-icon { - &.reorder { - &:hover { - color: var(--bg-slate-400, #1d212d); - } - } - } - } - } - } - } - } - - &:not(.pinned):hover, - &.dropdown-open { + &:hover { background: var(--bg-vanilla-100); - - .nav-wrapper { - .nav-top-section { - .shortcut-nav-items { - .nav-section-title { - .nav-section-title-icon { - &.reorder { - &:hover { - color: var(--bg-slate-400, #1d212d); - } - } - } - } - } - } - } } } @@ -1421,12 +1134,6 @@ .ant-dropdown-menu-title-content { color: var(--bg-ink-400); } - - &:hover:not(.ant-dropdown-menu-item-disabled) { - .ant-dropdown-menu-title-content { - color: var(--bg-ink-500); - } - } } } } @@ -1503,10 +1210,6 @@ color: var(--bg-ink-400); } } - - .help-support-dropdown li.ant-dropdown-menu-item-divider { - background-color: var(--bg-vanilla-300) !important; - } } .version-tooltip-overlay { @@ -1519,7 +1222,7 @@ border-radius: 2px; border: 1px solid var(--bg-slate-500); - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); font-family: Inter; font-size: 11px; font-style: normal; @@ -1534,7 +1237,7 @@ gap: 4px; .version-update-notification-tooltip-title { - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); font-family: Inter; font-size: 11px; font-style: normal; @@ -1544,7 +1247,7 @@ } .version-update-notification-tooltip-content { - color: var(--bg-vanilla-100, #fff); + color: var(--Vanilla-100, #fff); font-family: Inter; font-size: 10px; font-style: normal; diff --git a/frontend/src/container/SideNav/SideNav.tsx b/frontend/src/container/SideNav/SideNav.tsx index 99962a5fb2..f176d0b1af 100644 --- a/frontend/src/container/SideNav/SideNav.tsx +++ b/frontend/src/container/SideNav/SideNav.tsx @@ -157,27 +157,18 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { DefaultHelpSupportDropdownMenuItems, ); + const [pinnedMenuItems, setPinnedMenuItems] = useState([]); + const [tempPinnedMenuItems, setTempPinnedMenuItems] = useState( [], ); + const [secondaryMenuItems, setSecondaryMenuItems] = useState( + [], + ); + const [hasScroll, setHasScroll] = useState(false); const navTopSectionRef = useRef(null); - const [isDropdownOpen, setIsDropdownOpen] = useState(false); - - const [isHovered, setIsHovered] = useState(false); - const [pinnedMenuItems, setPinnedMenuItems] = useState([]); - const [secondaryMenuItems, setSecondaryMenuItems] = useState( - [], - ); - - const handleMouseEnter = useCallback(() => { - setIsHovered(true); - }, []); - - const handleMouseLeave = useCallback(() => { - setIsHovered(false); - }, []); const checkScroll = useCallback((): void => { if (navTopSectionRef.current) { @@ -226,68 +217,63 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { const isAdmin = user.role === USER_ROLES.ADMIN; const isEditor = user.role === USER_ROLES.EDITOR; - // Compute initial pinned items and secondary menu items synchronously to avoid flash - const computedPinnedMenuItems = useMemo(() => { - const navShortcutsPreference = userPreferences?.find( + useEffect(() => { + const navShortcuts = (userPreferences?.find( (preference) => preference.name === USER_PREFERENCES.NAV_SHORTCUTS, - ); - const navShortcuts = (navShortcutsPreference?.value as unknown) as - | string[] - | undefined; + )?.value as unknown) as string[]; - // If userPreferences not loaded yet, return empty to avoid showing defaults before preferences load - if (userPreferences === null) { - return []; - } + const shouldShowIntegrations = + (isCloudUser || isEnterpriseSelfHostedUser) && (isAdmin || isEditor); - // If preference exists with non-empty array, use stored shortcuts - if (isArray(navShortcuts) && navShortcuts.length > 0) { - return navShortcuts + if (navShortcuts && isArray(navShortcuts) && navShortcuts.length > 0) { + // nav shortcuts is array of strings + const pinnedItems = navShortcuts .map((shortcut) => defaultMoreMenuItems.find((item) => item.itemKey === shortcut), ) .filter((item): item is SidebarItem => item !== undefined); + + // Set pinned items in the order they were stored + setPinnedMenuItems(pinnedItems); + + setSecondaryMenuItems( + defaultMoreMenuItems.map((item) => ({ + ...item, + isPinned: pinnedItems.some((pinned) => pinned.itemKey === item.itemKey), + isEnabled: + item.key === ROUTES.INTEGRATIONS + ? shouldShowIntegrations + : item.isEnabled, + })), + ); + } else { + // Set default pinned items + const defaultPinnedItems = defaultMoreMenuItems.filter( + (item) => item.isPinned, + ); + setPinnedMenuItems(defaultPinnedItems); + + setSecondaryMenuItems( + defaultMoreMenuItems.map((item) => ({ + ...item, + isPinned: defaultPinnedItems.some( + (pinned) => pinned.itemKey === item.itemKey, + ), + isEnabled: + item.key === ROUTES.INTEGRATIONS + ? shouldShowIntegrations + : item.isEnabled, + })), + ); } - - // No preference, or empty array → use defaults - return defaultMoreMenuItems.filter((item) => item.isPinned); - }, [userPreferences]); - - const computedSecondaryMenuItems = useMemo(() => { - const shouldShowIntegrationsValue = - (isCloudUser || isEnterpriseSelfHostedUser) && (isAdmin || isEditor); - - return defaultMoreMenuItems.map((item) => ({ - ...item, - isPinned: computedPinnedMenuItems.some( - (pinned) => pinned.itemKey === item.itemKey, - ), - isEnabled: - item.key === ROUTES.INTEGRATIONS - ? shouldShowIntegrationsValue - : item.isEnabled, - })); }, [ - computedPinnedMenuItems, + userPreferences, isCloudUser, isEnterpriseSelfHostedUser, isAdmin, isEditor, ]); - // Track if we've done the initial sync (to avoid overwriting user actions during session) - const hasInitializedRef = useRef(userPreferences !== null); - - // Sync state only on initial load when userPreferences first becomes available - useEffect(() => { - // Only sync once: when userPreferences loads for the first time - if (!hasInitializedRef.current && userPreferences !== null) { - setPinnedMenuItems(computedPinnedMenuItems); - setSecondaryMenuItems(computedSecondaryMenuItems); - hasInitializedRef.current = true; - } - }, [computedPinnedMenuItems, computedSecondaryMenuItems, userPreferences]); - const isOnboardingV3Enabled = featureFlags?.find( (flag) => flag.name === FeatureKeys.ONBOARDING_V3, )?.active; @@ -341,17 +327,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { .map((item) => item.itemKey) .filter(Boolean) as string[]; - // Update context immediately (optimistically) so computed values reflect the change - updateUserPreferenceInContext({ - name: USER_PREFERENCES.NAV_SHORTCUTS, - description: USER_PREFERENCES.NAV_SHORTCUTS, - valueType: 'array', - defaultValue: false, - allowedValues: [], - allowedScopes: ['user'], - value: navShortcuts, - }); - updateUserPreferenceMutation( { name: USER_PREFERENCES.NAV_SHORTCUTS, @@ -360,7 +335,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { { onSuccess: (response) => { if (response.data) { - // Update context again on success to ensure consistency updateUserPreferenceInContext({ name: USER_PREFERENCES.NAV_SHORTCUTS, description: USER_PREFERENCES.NAV_SHORTCUTS, @@ -394,13 +368,13 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { if (isCurrentlyPinned) { return prevItems.filter((i) => i.key !== item.key); } - return [...prevItems, item]; + return [item, ...prevItems]; }); // Get the updated pinned menu items for preference update const updatedPinnedItems = pinnedMenuItems.some((i) => i.key === item.key) ? pinnedMenuItems.filter((i) => i.key !== item.key) - : [...pinnedMenuItems, item]; + : [item, ...pinnedMenuItems]; // Update user preference with the ordered list of item keys updateNavShortcutsPreference(updatedPinnedItems); @@ -481,10 +455,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { pathname, ]); - const isSettingsPage = useMemo(() => pathname.startsWith(ROUTES.SETTINGS), [ - pathname, - ]); - const userSettingsDropdownMenuItems: MenuProps['items'] = useMemo( () => [ @@ -624,7 +594,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { }, { type: 'group', - label: "WHAT'S NEW", + label: "WHAT's NEW", }, ...dropdownItems, { @@ -780,15 +750,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { [secondaryMenuItems], ); - // Get active "More" items that should be visible in collapsed state - const activeMoreMenuItems = useMemo( - () => moreMenuItems.filter((item) => activeMenuKey === item.key), - [moreMenuItems, activeMenuKey], - ); - - // Check if sidebar is collapsed (not pinned, not hovered, and no dropdown open) - const isCollapsed = !isPinned && !isHovered && !isDropdownOpen; - const renderNavItems = ( items: SidebarItem[], allowPin?: boolean, @@ -940,15 +901,7 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { return (
-
+
@@ -1046,43 +999,35 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { {renderNavItems(primaryMenuItems)}
- {(pinnedMenuItems.length > 0 || !isCollapsed) && ( -
- {!isCollapsed && ( -
-
-
- -
+
+
+
+
+ +
-
SHORTCUTS
+
SHORTCUTS
- {pinnedMenuItems.length > 1 && ( - -
{ - logEvent('Sidebar V2: Manage shortcuts clicked', {}); - setIsReorderShortcutNavItemsModalOpen(true); - }} - > - -
-
- )} + {pinnedMenuItems.length > 1 && ( +
{ + logEvent('Sidebar V2: Manage shortcuts clicked', {}); + setIsReorderShortcutNavItemsModalOpen(true); + }} + > +
+ )} +
- {pinnedMenuItems.length === 0 && ( -
- You have not added any shortcuts yet. -
- )} + {pinnedMenuItems.length === 0 && ( +
+ You have not added any shortcuts yet.
)} - {(pinnedMenuItems.length > 0 || isCollapsed) && ( + {pinnedMenuItems.length > 0 && (
{renderNavItems( pinnedMenuItems.filter((item) => item.isEnabled), @@ -1091,60 +1036,46 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element {
)}
- )} +
{moreMenuItems.length > 0 && (
- {!isCollapsed && ( -
-
{ - // Only allow toggling when sidebar is open (pinned, hovered, or dropdown open) - if (isCollapsed) { - return; - } - const newCollapsedState = !isMoreMenuCollapsed; - logEvent('Sidebar V2: More menu clicked', { - action: isMoreMenuCollapsed ? 'expand' : 'collapse', - }); - setIsMoreMenuCollapsed(newCollapsedState); - }} - > -
- -
+
+
{ + logEvent('Sidebar V2: More menu clicked', { + action: isMoreMenuCollapsed ? 'expand' : 'collapse', + }); + setIsMoreMenuCollapsed(!isMoreMenuCollapsed); + }} + > +
+ +
-
MORE
+
MORE
-
- {isMoreMenuCollapsed ? ( - - ) : ( - - )} -
+
+ {isMoreMenuCollapsed ? ( + + ) : ( + + )}
- )} +
- {/* Show all items when expanded, only active items when collapsed */} - {isCollapsed - ? renderNavItems( - activeMoreMenuItems.filter((item) => item.isEnabled), - true, - ) - : renderNavItems( - moreMenuItems.filter((item) => item.isEnabled), - true, - )} + {renderNavItems( + moreMenuItems.filter((item) => item.isEnabled), + true, + )}
)} @@ -1171,7 +1102,6 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { placement="topLeft" overlayClassName="nav-dropdown-overlay help-support-dropdown" trigger={['click']} - onOpenChange={(open): void => setIsDropdownOpen(open)} >
@@ -1192,10 +1122,8 @@ function SideNav({ isPinned }: { isPinned: boolean }): JSX.Element { placement="topLeft" overlayClassName="nav-dropdown-overlay settings-dropdown" trigger={['click']} - onOpenChange={(open): void => setIsDropdownOpen(open)} > -
-
+
{userSettingsMenuItem.icon}
diff --git a/frontend/src/pages/Settings/Settings.styles.scss b/frontend/src/pages/Settings/Settings.styles.scss index 1f6c145017..936ff20c1c 100644 --- a/frontend/src/pages/Settings/Settings.styles.scss +++ b/frontend/src/pages/Settings/Settings.styles.scss @@ -33,19 +33,6 @@ height: calc(100vh - 48px); border-right: 1px solid var(--Slate-500, #161922); background: var(--Ink-500, #0b0c0e); - margin-top: 4px; - - .nav-item { - .nav-item-data { - margin: 0px 8px 0px 4px; - } - - &.active { - .nav-item-data .nav-item-label { - color: var(--bg-vanilla-100, #fff); - } - } - } } .settings-page-content { @@ -94,14 +81,6 @@ .settings-page-sidenav { border-right: 1px solid var(--bg-vanilla-300); background: var(--bg-vanilla-100); - - .nav-item { - &.active { - .nav-item-data .nav-item-label { - color: var(--bg-ink-500); - } - } - } } .settings-page-content { diff --git a/frontend/src/pages/Settings/Settings.tsx b/frontend/src/pages/Settings/Settings.tsx index 852ee79f74..7643b54c53 100644 --- a/frontend/src/pages/Settings/Settings.tsx +++ b/frontend/src/pages/Settings/Settings.tsx @@ -12,7 +12,7 @@ import { SidebarItem } from 'container/SideNav/sideNav.types'; import useComponentPermission from 'hooks/useComponentPermission'; import { useGetTenantLicense } from 'hooks/useGetTenantLicense'; import history from 'lib/history'; -import { Cog } from 'lucide-react'; +import { Wrench } from 'lucide-react'; import { useAppContext } from 'providers/App/App'; import { useCallback, useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -236,7 +236,7 @@ function SettingsPage(): JSX.Element { className="settings-page-header-title" data-testid="settings-page-title" > - + Settings