1- import React , { useMemo } from 'react' ;
1+ import React , { useCallback , useMemo } from 'react' ;
22import { connect } from 'react-redux' ;
33import {
44 useHoverState ,
@@ -14,6 +14,9 @@ import {
1414 PerformanceSignals ,
1515 Placeholder ,
1616 ContentWithFallback ,
17+ palette ,
18+ useDarkMode ,
19+ Tooltip ,
1720} from '@mongodb-js/compass-components' ;
1821import { usePreference , withPreferences } from 'compass-preferences-model' ;
1922import type { ItemAction } from '@mongodb-js/compass-components' ;
@@ -117,17 +120,31 @@ const navigationItemLabel = css({
117120 marginLeft : spacing [ 2 ] ,
118121} ) ;
119122
123+ const navigationItemDisabledDarkModeStyles = css ( {
124+ '--item-color' : palette . gray . dark1 ,
125+ '--item-color-active' : palette . gray . dark1 ,
126+ '--item-bg-color-hover' : 'var(--item-bg-color)' ,
127+ } ) ;
128+
129+ const navigationItemDisabledLightModeStyles = css ( {
130+ '--item-color' : palette . gray . base ,
131+ '--item-color-active' : palette . gray . base ,
132+ '--item-bg-color-hover' : 'var(--item-bg-color)' ,
133+ } ) ;
134+
120135const navigationItemActionIcons = css ( { color : 'inherit' } ) ;
121136
122137export function NavigationItem < Actions extends string > ( {
123138 isExpanded,
124139 onAction,
125- onClick,
140+ onClick : onButtonClick ,
126141 glyph,
127142 label,
128143 actions,
129144 isActive,
130145 showTooManyCollectionsInsight,
146+ disabled : isButtonDisabled = false ,
147+ disabledMessage : buttonDisabledMessage ,
131148} : {
132149 isExpanded ?: boolean ;
133150 onAction ( actionName : Actions , ...rest : any [ ] ) : void ;
@@ -137,17 +154,35 @@ export function NavigationItem<Actions extends string>({
137154 actions ?: ItemAction < Actions > [ ] ;
138155 isActive : boolean ;
139156 showTooManyCollectionsInsight ?: boolean ;
157+ disabled ?: boolean ;
158+ disabledMessage ?: string ;
140159} ) {
160+ const darkMode = useDarkMode ( ) ;
141161 const showInsights = usePreference ( 'showInsights' , React ) ;
162+ const onClick = useCallback ( ( ) => {
163+ if ( isButtonDisabled ) {
164+ return ;
165+ }
166+ onButtonClick ( ) ;
167+ } , [ isButtonDisabled , onButtonClick ] ) ;
142168 const [ hoverProps ] = useHoverState ( ) ;
143169 const focusRingProps = useFocusRing ( ) ;
144170 const defaultActionProps = useDefaultAction ( onClick ) ;
145171
146172 const navigationItemProps = mergeProps (
147173 {
148- className : cx ( navigationItem , isActive && activeNavigationItem ) ,
174+ className : cx (
175+ navigationItem ,
176+ isActive && activeNavigationItem ,
177+ isButtonDisabled &&
178+ ( darkMode
179+ ? navigationItemDisabledDarkModeStyles
180+ : navigationItemDisabledLightModeStyles )
181+ ) ,
182+ role : 'button' ,
149183 [ 'aria-label' ] : label ,
150184 [ 'aria-current' ] : isActive ,
185+ [ 'aria-disabled' ] : isButtonDisabled ,
151186 tabIndex : 0 ,
152187 } ,
153188 hoverProps ,
@@ -156,37 +191,52 @@ export function NavigationItem<Actions extends string>({
156191 ) as React . HTMLProps < HTMLDivElement > ;
157192
158193 return (
159- < div { ...navigationItemProps } >
160- < div className = { itemWrapper } >
161- < div className = { itemButtonWrapper } >
162- < Icon glyph = { glyph } size = "small" > </ Icon >
163- { isExpanded && < span className = { navigationItemLabel } > { label } </ span > }
164- </ div >
165- { showInsights && isExpanded && showTooManyCollectionsInsight && (
166- < div className = { signalContainerStyles } >
167- < SignalPopover
168- signals = { PerformanceSignals . get ( 'too-many-collections' ) }
169- > </ SignalPopover >
194+ < Tooltip
195+ align = "right"
196+ spacing = { spacing [ 3 ] }
197+ isDisabled = { ! isButtonDisabled || ! buttonDisabledMessage }
198+ trigger = { ( { children : tooltip , ...triggerProps } ) => {
199+ const props = mergeProps ( triggerProps , navigationItemProps ) ;
200+ return (
201+ < div { ...props } >
202+ < div className = { itemWrapper } >
203+ < div className = { itemButtonWrapper } >
204+ < Icon glyph = { glyph } size = "small" > </ Icon >
205+ { isExpanded && (
206+ < span className = { navigationItemLabel } > { label } </ span >
207+ ) }
208+ { tooltip }
209+ </ div >
210+ { showInsights && isExpanded && showTooManyCollectionsInsight && (
211+ < div className = { signalContainerStyles } >
212+ < SignalPopover
213+ signals = { PerformanceSignals . get ( 'too-many-collections' ) }
214+ > </ SignalPopover >
215+ </ div >
216+ ) }
217+ { ! isButtonDisabled && isExpanded && actions && (
218+ < ItemActionControls < Actions >
219+ iconSize = "small"
220+ onAction = { onAction }
221+ data-testid = "sidebar-navigation-item-actions"
222+ actions = { actions }
223+ // This is what renders the "create database" action,
224+ // the icons here should always be clearly visible,
225+ // so we let the icon to inherit the foreground color of
226+ // the text
227+ isVisible = { true }
228+ iconClassName = { navigationItemActionIcons }
229+ collapseToMenuThreshold = { 3 }
230+ > </ ItemActionControls >
231+ ) }
232+ < div className = { cx ( 'item-background' , itemBackground ) } />
233+ </ div >
170234 </ div >
171- ) }
172- { isExpanded && actions && (
173- < ItemActionControls < Actions >
174- iconSize = "small"
175- onAction = { onAction }
176- data-testid = "sidebar-navigation-item-actions"
177- actions = { actions }
178- // This is what renders the "create database" action,
179- // the icons here should always be clearly visible,
180- // so we let the icon to inherit the foreground color of
181- // the text
182- isVisible = { true }
183- iconClassName = { navigationItemActionIcons }
184- collapseToMenuThreshold = { 3 }
185- > </ ItemActionControls >
186- ) }
187- < div className = { cx ( 'item-background' , itemBackground ) } />
188- </ div >
189- </ div >
235+ ) ;
236+ } }
237+ >
238+ { buttonDisabledMessage }
239+ </ Tooltip >
190240 ) ;
191241}
192242
@@ -201,8 +251,8 @@ const PlaceholderItem = ({ forLabel }: { forLabel: string }) => {
201251export function NavigationItems ( {
202252 isReady,
203253 isExpanded,
204- showCreateDatabaseAction = false ,
205- showPerformanceItem = false ,
254+ showCreateDatabaseAction,
255+ isPerformanceTabSupported ,
206256 onFilterChange,
207257 onAction,
208258 currentLocation,
@@ -211,8 +261,8 @@ export function NavigationItems({
211261} : {
212262 isReady ?: boolean ;
213263 isExpanded ?: boolean ;
214- showCreateDatabaseAction ? : boolean ;
215- showPerformanceItem ? : boolean ;
264+ showCreateDatabaseAction : boolean ;
265+ isPerformanceTabSupported : boolean ;
216266 onFilterChange ( regex : RegExp | null ) : void ;
217267 onAction ( actionName : string , ...rest : any [ ] ) : void ;
218268 currentLocation : string | null ;
@@ -272,16 +322,16 @@ export function NavigationItems({
272322 label = "My Queries"
273323 isActive = { currentLocation === 'My Queries' }
274324 />
275- { showPerformanceItem && (
276- < NavigationItem < '' >
277- isExpanded = { isExpanded }
278- onAction = { onAction }
279- onClick = { openPerformanceWorkspace }
280- glyph = "Gauge "
281- label = " Performance"
282- isActive = { currentLocation === 'Performance' }
283- />
284- ) }
325+ < NavigationItem < '' >
326+ isExpanded = { isExpanded }
327+ onAction = { onAction }
328+ onClick = { openPerformanceWorkspace }
329+ glyph = "Gauge"
330+ label = "Performance "
331+ isActive = { currentLocation === ' Performance' }
332+ disabled = { ! isPerformanceTabSupported }
333+ disabledMessage = "Performance metrics are not available for your deployment or to your database user"
334+ />
285335 < NavigationItem < DatabasesActions >
286336 isExpanded = { isExpanded }
287337 onAction = { onAction }
@@ -321,9 +371,10 @@ const mapStateToProps = (
321371 0
322372 ) ;
323373
324- const isReady = [ 'ready' , 'refreshing' ] . includes (
325- state . instance ?. status ?? ''
326- ) ;
374+ const isReady =
375+ [ 'ready' , 'refreshing' ] . includes ( state . instance ?. status ?? '' ) &&
376+ state . isPerformanceTabSupported !== null ;
377+
327378 const isDataLake = state . instance ?. dataLake . isDataLake ?? false ;
328379 const isWritable = state . instance ?. isWritable ?? false ;
329380
@@ -332,6 +383,7 @@ const mapStateToProps = (
332383 showPerformanceItem : ! isDataLake ,
333384 showCreateDatabaseAction : ! isDataLake && isWritable && ! preferencesReadOnly ,
334385 showTooManyCollectionsInsight : totalCollectionsCount > 10_000 ,
386+ isPerformanceTabSupported : ! isDataLake && ! ! state . isPerformanceTabSupported ,
335387 } ;
336388} ;
337389
0 commit comments