mirror of https://github.com/grafana/grafana.git
				
				
				
			SingleTopNav: Flip collapse arrows for better alignment (#94081)
flip megamenu arrows for better alignment
This commit is contained in:
		
							parent
							
								
									ddbbf8df4b
								
							
						
					
					
						commit
						cf61ab3da2
					
				|  | @ -23,7 +23,7 @@ export function MegaMenuHeader({ handleMegaMenu, handleDockedMenu, onClose }: Pr | |||
| 
 | ||||
|   return ( | ||||
|     <div className={styles.header}> | ||||
|       <Stack alignItems="center" minWidth={0}> | ||||
|       <Stack alignItems="center" minWidth={0} gap={0.25}> | ||||
|         <ToolbarButton narrow onClick={handleMegaMenu}> | ||||
|           <Branding.MenuLogo className={styles.img} /> | ||||
|         </ToolbarButton> | ||||
|  | @ -69,7 +69,7 @@ const getStyles = (theme: GrafanaTheme2) => ({ | |||
|     display: 'flex', | ||||
|     gap: theme.spacing(1), | ||||
|     justifyContent: 'space-between', | ||||
|     padding: theme.spacing(0, 1, 0, 0.5), | ||||
|     padding: theme.spacing(0, 1, 0, 0.75), | ||||
|     height: TOP_BAR_LEVEL_HEIGHT, | ||||
|     minHeight: TOP_BAR_LEVEL_HEIGHT, | ||||
|   }), | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import { useLocation } from 'react-router-dom-v5-compat'; | |||
| import { useLocalStorage } from 'react-use'; | ||||
| 
 | ||||
| import { GrafanaTheme2, NavModelItem, toIconName } from '@grafana/data'; | ||||
| import { config } from '@grafana/runtime'; | ||||
| import { useStyles2, Text, IconButton, Icon, Stack } from '@grafana/ui'; | ||||
| import { useGrafana } from 'app/core/context/GrafanaContext'; | ||||
| 
 | ||||
|  | @ -39,6 +40,7 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi | |||
|   ); | ||||
|   const showExpandButton = level < MAX_DEPTH && Boolean(linkHasChildren(link) || link.emptyMessage); | ||||
|   const item = useRef<HTMLLIElement>(null); | ||||
|   const isSingleTopNav = config.featureToggles.singleTopNav; | ||||
| 
 | ||||
|   const styles = useStyles2(getStyles); | ||||
| 
 | ||||
|  | @ -74,6 +76,29 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi | |||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   function getIconName(isExpanded: boolean) { | ||||
|     if (isSingleTopNav) { | ||||
|       return isExpanded ? 'angle-up' : 'angle-down'; | ||||
|     } else { | ||||
|       return isExpanded ? 'angle-down' : 'angle-right'; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   const collapseIcon = ( | ||||
|     <div className={styles.collapseButtonWrapper}> | ||||
|       {showExpandButton && ( | ||||
|         <IconButton | ||||
|           aria-label={`${sectionExpanded ? 'Collapse' : 'Expand'} section ${link.text}`} | ||||
|           className={styles.collapseButton} | ||||
|           onClick={() => setSectionExpanded(!sectionExpanded)} | ||||
|           name={getIconName(Boolean(sectionExpanded))} | ||||
|           size="md" | ||||
|           variant="secondary" | ||||
|         /> | ||||
|       )} | ||||
|     </div> | ||||
|   ); | ||||
| 
 | ||||
|   return ( | ||||
|     <li ref={item} className={styles.listItem}> | ||||
|       <div | ||||
|  | @ -83,18 +108,7 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi | |||
|       > | ||||
|         {level !== 0 && <Indent level={level === MAX_DEPTH ? level - 1 : level} spacing={3} />} | ||||
|         {level === MAX_DEPTH && <div className={styles.itemConnector} />} | ||||
|         <div className={styles.collapseButtonWrapper}> | ||||
|           {showExpandButton && ( | ||||
|             <IconButton | ||||
|               aria-label={`${sectionExpanded ? 'Collapse' : 'Expand'} section ${link.text}`} | ||||
|               className={styles.collapseButton} | ||||
|               onClick={() => setSectionExpanded(!sectionExpanded)} | ||||
|               name={sectionExpanded ? 'angle-down' : 'angle-right'} | ||||
|               size="md" | ||||
|               variant="secondary" | ||||
|             /> | ||||
|           )} | ||||
|         </div> | ||||
|         {!isSingleTopNav && collapseIcon} | ||||
|         <div className={styles.collapsibleSectionWrapper}> | ||||
|           <MegaMenuItemText | ||||
|             isActive={isActive} | ||||
|  | @ -118,6 +132,7 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick, onPin, isPi | |||
|             </div> | ||||
|           </MegaMenuItemText> | ||||
|         </div> | ||||
|         {isSingleTopNav && collapseIcon} | ||||
|       </div> | ||||
|       {showExpandButton && sectionExpanded && ( | ||||
|         <ul className={styles.children}> | ||||
|  |  | |||
|  | @ -1,8 +1,9 @@ | |||
| import { css } from '@emotion/css'; | ||||
| import { useEffect, useState } from 'react'; | ||||
| 
 | ||||
| import { SelectableValue } from '@grafana/data'; | ||||
| import { GrafanaTheme2, SelectableValue } from '@grafana/data'; | ||||
| import { config, locationService } from '@grafana/runtime'; | ||||
| import { Text, useTheme2 } from '@grafana/ui'; | ||||
| import { Text, useStyles2, useTheme2 } from '@grafana/ui'; | ||||
| import { useMediaQueryChange } from 'app/core/hooks/useMediaQueryChange'; | ||||
| import { contextSrv } from 'app/core/services/context_srv'; | ||||
| import { getUserOrganizations, setUserOrganization } from 'app/features/org/state/actions'; | ||||
|  | @ -17,6 +18,7 @@ export function OrganizationSwitcher() { | |||
|   const theme = useTheme2(); | ||||
|   const dispatch = useDispatch(); | ||||
|   const orgs = useSelector((state) => state.organization.userOrgs); | ||||
|   const styles = useStyles2(getStyles); | ||||
|   const onSelectChange = (option: SelectableValue<UserOrg>) => { | ||||
|     if (option.value) { | ||||
|       setUserOrganization(option.value.orgId); | ||||
|  | @ -46,7 +48,11 @@ export function OrganizationSwitcher() { | |||
| 
 | ||||
|   if (orgs?.length <= 1) { | ||||
|     if (config.featureToggles.singleTopNav) { | ||||
|       return <Text truncate>{Branding.AppTitle}</Text>; | ||||
|       return ( | ||||
|         <span className={styles.brandTitle}> | ||||
|           <Text truncate>{Branding.AppTitle}</Text> | ||||
|         </span> | ||||
|       ); | ||||
|     } else { | ||||
|       return null; | ||||
|     } | ||||
|  | @ -56,3 +62,9 @@ export function OrganizationSwitcher() { | |||
| 
 | ||||
|   return <Switcher orgs={orgs} onSelectChange={onSelectChange} />; | ||||
| } | ||||
| 
 | ||||
| const getStyles = (theme: GrafanaTheme2) => ({ | ||||
|   brandTitle: css({ | ||||
|     paddingLeft: theme.spacing(1), | ||||
|   }), | ||||
| }); | ||||
|  |  | |||
|  | @ -96,7 +96,7 @@ const getStyles = (theme: GrafanaTheme2, menuDockedAndOpen: boolean) => ({ | |||
|     gap: theme.spacing(1), | ||||
|     alignItems: 'center', | ||||
|     padding: theme.spacing(0, 1), | ||||
|     paddingLeft: menuDockedAndOpen ? theme.spacing(3.5) : theme.spacing(0.5), | ||||
|     paddingLeft: menuDockedAndOpen ? theme.spacing(3.5) : theme.spacing(0.75), | ||||
|     borderBottom: `1px solid ${theme.colors.border.weak}`, | ||||
|     justifyContent: 'space-between', | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue