mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Navigation: Expand active page hierarchy and scroll into center if not visible (#76949)
* expand page hierarchy and scroll into center if not visible * remove unnecessary id
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { css, cx } from '@emotion/css';
|
import { css, cx } from '@emotion/css';
|
||||||
import React from 'react';
|
import React, { useEffect, useRef } from 'react';
|
||||||
import { useLocalStorage } from 'react-use';
|
import { useLocalStorage } from 'react-use';
|
||||||
|
|
||||||
import { GrafanaTheme2, NavModelItem, toIconName } from '@grafana/data';
|
import { GrafanaTheme2, NavModelItem, toIconName } from '@grafana/data';
|
||||||
@@ -24,18 +24,37 @@ export function MegaMenuItem({ link, activeItem, level = 0, onClick }: Props) {
|
|||||||
const FeatureHighlightWrapper = link.highlightText ? FeatureHighlight : React.Fragment;
|
const FeatureHighlightWrapper = link.highlightText ? FeatureHighlight : React.Fragment;
|
||||||
const hasActiveChild = hasChildMatch(link, activeItem);
|
const hasActiveChild = hasChildMatch(link, activeItem);
|
||||||
const isActive = link === activeItem || (level === MAX_DEPTH && hasActiveChild);
|
const isActive = link === activeItem || (level === MAX_DEPTH && hasActiveChild);
|
||||||
const [sectionExpanded, setSectionExpanded] =
|
const [sectionExpanded, setSectionExpanded] = useLocalStorage(
|
||||||
useLocalStorage(`grafana.navigation.expanded[${link.text}]`, false) ?? Boolean(hasActiveChild);
|
`grafana.navigation.expanded[${link.text}]`,
|
||||||
|
Boolean(hasActiveChild)
|
||||||
|
);
|
||||||
const showExpandButton = level < MAX_DEPTH && Boolean(linkHasChildren(link) || link.emptyMessage);
|
const showExpandButton = level < MAX_DEPTH && Boolean(linkHasChildren(link) || link.emptyMessage);
|
||||||
|
const item = useRef<HTMLLIElement>(null);
|
||||||
|
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
|
// expand parent sections if child is active
|
||||||
|
useEffect(() => {
|
||||||
|
if (hasActiveChild) {
|
||||||
|
setSectionExpanded(true);
|
||||||
|
}
|
||||||
|
}, [hasActiveChild, setSectionExpanded]);
|
||||||
|
|
||||||
|
// scroll active element into center if it's offscreen
|
||||||
|
useEffect(() => {
|
||||||
|
if (isActive && item.current && isElementOffscreen(item.current)) {
|
||||||
|
item.current.scrollIntoView({
|
||||||
|
block: 'center',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [isActive]);
|
||||||
|
|
||||||
if (!link.url) {
|
if (!link.url) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className={styles.listItem}>
|
<li ref={item} className={styles.listItem}>
|
||||||
<div
|
<div
|
||||||
className={cx(styles.menuItem, {
|
className={cx(styles.menuItem, {
|
||||||
[styles.hasIcon]: Boolean(level === 0 && link.icon),
|
[styles.hasIcon]: Boolean(level === 0 && link.icon),
|
||||||
@@ -175,3 +194,8 @@ const getStyles = (theme: GrafanaTheme2) => ({
|
|||||||
function linkHasChildren(link: NavModelItem): link is NavModelItem & { children: NavModelItem[] } {
|
function linkHasChildren(link: NavModelItem): link is NavModelItem & { children: NavModelItem[] } {
|
||||||
return Boolean(link.children && link.children.length > 0);
|
return Boolean(link.children && link.children.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isElementOffscreen(element: HTMLElement) {
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
return rect.bottom < 0 || rect.top >= window.innerHeight;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user