From 0f9e6dda2d130691968dc704814a99d6444d69dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Mon, 17 Oct 2022 14:19:29 +0200 Subject: [PATCH] Page: Refactor out section nav state logic and move it to SectionNav component (#57036) --- public/app/core/components/PageNew/Page.tsx | 49 +------------ .../core/components/PageNew/SectionNav.tsx | 72 +++++++++++++++---- 2 files changed, 60 insertions(+), 61 deletions(-) diff --git a/public/app/core/components/PageNew/Page.tsx b/public/app/core/components/PageNew/Page.tsx index 3e534aba243..00316949a82 100644 --- a/public/app/core/components/PageNew/Page.tsx +++ b/public/app/core/components/PageNew/Page.tsx @@ -1,10 +1,9 @@ // Libraries import { css, cx } from '@emotion/css'; -import React, { useEffect, useState } from 'react'; -import { useLocalStorage } from 'react-use'; +import React, { useEffect } from 'react'; import { GrafanaTheme2, PageLayoutType } from '@grafana/data'; -import { CustomScrollbar, useStyles2, useTheme2 } from '@grafana/ui'; +import { CustomScrollbar, useStyles2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { Footer } from '../Footer/Footer'; @@ -16,7 +15,6 @@ import { PageContents } from './PageContents'; import { PageHeader } from './PageHeader'; import { PageTabs } from './PageTabs'; import { SectionNav } from './SectionNav'; -import { SectionNavToggle } from './SectionNavToggle'; export const Page: PageType = ({ navId, @@ -31,29 +29,14 @@ export const Page: PageType = ({ scrollRef, ...otherProps }) => { - const theme = useTheme2(); const styles = useStyles2(getStyles); const navModel = usePageNav(navId, oldNavProp); const { chrome } = useGrafana(); - const isSmallScreen = window.matchMedia(`(max-width: ${theme.breakpoints.values.lg}px)`).matches; - const [navExpandedPreference, setNavExpandedPreference] = useLocalStorage( - 'grafana.sectionNav.expanded', - !isSmallScreen - ); - const [isNavExpanded, setNavExpanded] = useState(!isSmallScreen && navExpandedPreference); - usePageTitle(navModel, pageNav); const pageHeaderNav = pageNav ?? navModel?.node; - useEffect(() => { - const mediaQuery = window.matchMedia(`(max-width: ${theme.breakpoints.values.lg}px)`); - const onMediaQueryChange = (e: MediaQueryListEvent) => setNavExpanded(e.matches ? false : navExpandedPreference); - mediaQuery.addEventListener('change', onMediaQueryChange); - return () => mediaQuery.removeEventListener('change', onMediaQueryChange); - }, [navExpandedPreference, theme.breakpoints.values.lg]); - useEffect(() => { if (navModel) { chrome.update({ @@ -63,25 +46,11 @@ export const Page: PageType = ({ } }, [navModel, pageNav, chrome]); - const onToggleSectionNav = () => { - setNavExpandedPreference(!isNavExpanded); - setNavExpanded(!isNavExpanded); - }; - return (
{layout === PageLayoutType.Standard && (
- {navModel && ( - <> - - - - )} + {navModel && }
@@ -125,18 +94,6 @@ const getStyles = (theme: GrafanaTheme2) => { : '0 0.6px 1.5px -1px rgb(0 0 0 / 8%),0 2px 4px rgb(0 0 0 / 6%),0 5px 10px -1px rgb(0 0 0 / 5%)'; return { - collapseIcon: css({ - border: `1px solid ${theme.colors.border.weak}`, - transform: 'translateX(50%)', - top: theme.spacing(8), - right: theme.spacing(-1), - - [theme.breakpoints.down('md')]: { - left: '50%', - transform: 'translate(-50%, 50%) rotate(90deg)', - top: theme.spacing(2), - }, - }), wrapper: css({ label: 'page-wrapper', height: '100%', diff --git a/public/app/core/components/PageNew/SectionNav.tsx b/public/app/core/components/PageNew/SectionNav.tsx index b5ca7b6e502..6ff158cd411 100644 --- a/public/app/core/components/PageNew/SectionNav.tsx +++ b/public/app/core/components/PageNew/SectionNav.tsx @@ -1,38 +1,68 @@ import { css, cx } from '@emotion/css'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; +import { useLocalStorage } from 'react-use'; import { NavModel, GrafanaTheme2 } from '@grafana/data'; -import { useStyles2, CustomScrollbar } from '@grafana/ui'; +import { useStyles2, CustomScrollbar, useTheme2 } from '@grafana/ui'; import { SectionNavItem } from './SectionNavItem'; +import { SectionNavToggle } from './SectionNavToggle'; export interface Props { model: NavModel; - isExpanded: boolean; } -export function SectionNav({ model, isExpanded }: Props) { +export function SectionNav({ model }: Props) { const styles = useStyles2(getStyles); + const { isExpanded, onToggleSectionNav } = useSectionNavState(); if (!Boolean(model.main?.children?.length)) { return null; } return ( - + <> + + + ); } +function useSectionNavState() { + const theme = useTheme2(); + + const isSmallScreen = window.matchMedia(`(max-width: ${theme.breakpoints.values.lg}px)`).matches; + const [navExpandedPreference, setNavExpandedPreference] = useLocalStorage( + 'grafana.sectionNav.expanded', + !isSmallScreen + ); + const [isExpanded, setIsExpanded] = useState(!isSmallScreen && navExpandedPreference); + + useEffect(() => { + const mediaQuery = window.matchMedia(`(max-width: ${theme.breakpoints.values.lg}px)`); + const onMediaQueryChange = (e: MediaQueryListEvent) => setIsExpanded(e.matches ? false : navExpandedPreference); + mediaQuery.addEventListener('change', onMediaQueryChange); + return () => mediaQuery.removeEventListener('change', onMediaQueryChange); + }, [navExpandedPreference, theme.breakpoints.values.lg]); + + const onToggleSectionNav = () => { + setNavExpandedPreference(!isExpanded); + setIsExpanded(!isExpanded); + }; + + return { isExpanded, onToggleSectionNav }; +} + const getStyles = (theme: GrafanaTheme2) => { return { nav: css({ @@ -62,5 +92,17 @@ const getStyles = (theme: GrafanaTheme2) => { padding: theme.spacing(4.5, 1, 2, 2), minWidth: '250px', }), + collapseIcon: css({ + border: `1px solid ${theme.colors.border.weak}`, + transform: 'translateX(50%)', + top: theme.spacing(8), + right: theme.spacing(-1), + + [theme.breakpoints.down('md')]: { + left: '50%', + transform: 'translate(-50%, 50%) rotate(90deg)', + top: theme.spacing(2), + }, + }), }; };