diff --git a/ui/dashboardApp/layout/main/Sider/Banner.tsx b/ui/dashboardApp/layout/main/Sider/Banner.tsx index 25ec615a30..4c9b85ad07 100644 --- a/ui/dashboardApp/layout/main/Sider/Banner.tsx +++ b/ui/dashboardApp/layout/main/Sider/Banner.tsx @@ -1,7 +1,8 @@ import React, { useMemo } from 'react' -import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons' +import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons' import { useSize } from '@umijs/hooks' import Flexbox from '@g07cha/flexbox-react' +import { useSpring, animated } from 'react-spring' import { useClientRequest } from '@lib/utils/useClientRequest' import client, { InfoInfoResponse } from '@lib/client' @@ -45,14 +46,14 @@ export default function ToggleBanner({ onToggle, }) { const [bannerSize, bannerRef] = useSize() - const bannerStyle = { + const transBanner = useSpring({ opacity: collapsed ? 0 : 1, height: collapsed ? toggleHeight : bannerSize.height || 0, - } - const buttonStyle = { + }) + const transButton = useSpring({ left: collapsed ? 0 : fullWidth - toggleWidth, width: collapsed ? collapsedWidth : toggleWidth, - } + }) const { data, isLoading } = useClientRequest((reqConfig) => client.getInstance().infoGet(reqConfig) @@ -67,7 +68,10 @@ export default function ToggleBanner({ return (
-
+
-
-
+ + {collapsed ? ( ) : ( )} -
+
) } diff --git a/ui/dashboardApp/layout/main/Sider/index.module.less b/ui/dashboardApp/layout/main/Sider/index.module.less index 5d4843a92a..67dbe8cd8b 100644 --- a/ui/dashboardApp/layout/main/Sider/index.module.less +++ b/ui/dashboardApp/layout/main/Sider/index.module.less @@ -2,11 +2,10 @@ @sider-background: #f7f7fa; -.wrapper { - transition: width 444ms ease; -} - .sider { + position: fixed; + left: 0; + top: 0; height: 100%; z-index: 1; background: linear-gradient(@sider-background, #ebeffa); diff --git a/ui/dashboardApp/layout/main/Sider/index.tsx b/ui/dashboardApp/layout/main/Sider/index.tsx index c00ec4523f..bcd6772c8a 100644 --- a/ui/dashboardApp/layout/main/Sider/index.tsx +++ b/ui/dashboardApp/layout/main/Sider/index.tsx @@ -1,9 +1,10 @@ -import React, { useCallback, useMemo, useState } from 'react' -import { BugOutlined, ExperimentOutlined } from '@ant-design/icons' +import React, { useState, useMemo } from 'react' +import { ExperimentOutlined, BugOutlined } from '@ant-design/icons' import { Layout, Menu } from 'antd' import { Link } from 'react-router-dom' import { useEventListener } from '@umijs/hooks' import { useTranslation } from 'react-i18next' +import { useSpring, animated } from 'react-spring' import client from '@lib/client' import Banner from './Banner' @@ -17,9 +18,10 @@ function useAppMenuItem(registry, appId, title?: string) { return null } return ( - : null}> + - {title ? title : t(`${appId}.nav_title`, appId)} + {app.icon ? : null} + {title ? title : t(`${appId}.nav_title`, appId)} ) @@ -36,12 +38,6 @@ function useActiveAppId(registry) { return appId } -function triggerResizeEvent() { - const event = document.createEvent('HTMLEvents') - event.initEvent('resize', true, false) - window.dispatchEvent(event) -} - function Sider({ registry, fullWidth, @@ -65,8 +61,12 @@ function Sider({ const debugSubMenu = ( } - title={t('nav.sider.debug')} + title={ + + + {t('nav.sider.debug')} + + } > {debugSubMenuItems} @@ -79,8 +79,12 @@ function Sider({ const experimentalSubMenu = ( } - title={t('nav.sider.experimental')} + title={ + + + {t('nav.sider.experimental')} + + } > {experimentalSubMenuItems} @@ -112,9 +116,9 @@ function Sider({ useAppMenuItem(registry, 'user_profile', displayName), ] - const siderStyle = { + const transSider = useSpring({ width: collapsed ? collapsedWidth : fullWidth, - } + }) const defaultOpenKeys = useMemo(() => { if (defaultCollapsed) { @@ -124,17 +128,8 @@ function Sider({ } }, [defaultCollapsed]) - const wrapperRef = useCallback((wrapper) => { - if (wrapper !== null) { - wrapper.addEventListener('transitionend', (e) => { - if (e.target !== wrapper || e.propertyName !== 'width') return - triggerResizeEvent() - }) - } - }, []) - return ( -
+ {extraMenuItems} -
+ ) } diff --git a/ui/dashboardApp/layout/main/index.module.less b/ui/dashboardApp/layout/main/index.module.less index 05709a45e0..4c050027a6 100644 --- a/ui/dashboardApp/layout/main/index.module.less +++ b/ui/dashboardApp/layout/main/index.module.less @@ -1,28 +1,14 @@ @import '~antd/es/style/themes/default.less'; .container { - display: flex; - position: fixed; - top: 0; - bottom: 0; - right: 0; - left: 0; height: 100vh; - width: 100vw; } .content { position: relative; - - flex: 1; - z-index: 3; background: #fff; min-height: 100vh; - box-shadow: 0 0 30px rgba(#000, 0.15); - - overflow-x: hidden; - overflow-y: auto; &:before, &:after { @@ -31,3 +17,13 @@ display: table; } } + +.contentBack { + position: fixed; + z-index: 2; + background: #fff; + top: 0; + height: 100%; + right: 0; + box-shadow: 0 0 30px rgba(#000, 0.15); +} diff --git a/ui/dashboardApp/layout/main/index.tsx b/ui/dashboardApp/layout/main/index.tsx index 594a8702da..5a23210942 100644 --- a/ui/dashboardApp/layout/main/index.tsx +++ b/ui/dashboardApp/layout/main/index.tsx @@ -1,14 +1,45 @@ -import React, { useCallback, useState } from 'react' +import React, { useState, useCallback, useEffect } from 'react' import { Root } from '@lib/components' import { useLocalStorageState } from '@umijs/hooks' import { HashRouter as Router } from 'react-router-dom' -import { animated, useSpring } from 'react-spring' +import { useSpring, animated } from 'react-spring' import Sider from './Sider' import styles from './index.module.less' const siderWidth = 260 const siderCollapsedWidth = 80 +const collapsedContentOffset = siderCollapsedWidth - siderWidth +const contentOffsetTrigger = collapsedContentOffset * 0.99 + +function triggerResizeEvent() { + const event = document.createEvent('HTMLEvents') + event.initEvent('resize', true, false) + window.dispatchEvent(event) +} + +const useContentLeftOffset = (collapsed) => { + const [offset, setOffset] = useState(siderWidth) + const onAnimationStart = useCallback(() => { + if (!collapsed) { + setOffset(siderWidth) + } + }, [collapsed]) + const onAnimationFrame = useCallback( + ({ x }) => { + if (collapsed && x < contentOffsetTrigger) { + setOffset(siderCollapsedWidth) + } + }, + [collapsed] + ) + useEffect(triggerResizeEvent, [offset]) + return { + contentLeftOffset: offset, + onAnimationStart, + onAnimationFrame, + } +} export default function App({ registry }) { const [collapsed, setCollapsed] = useLocalStorageState( @@ -16,6 +47,16 @@ export default function App({ registry }) { false ) const [defaultCollapsed] = useState(collapsed) + const { + contentLeftOffset, + onAnimationStart, + onAnimationFrame, + } = useContentLeftOffset(collapsed) + const transContentBack = useSpring({ + x: collapsed ? collapsedContentOffset : 0, + onStart: onAnimationStart, + onFrame: onAnimationFrame, + }) const transContainer = useSpring({ opacity: 1, from: { opacity: 0 }, @@ -43,9 +84,27 @@ export default function App({ registry }) { collapsedWidth={siderCollapsedWidth} animationDelay={0} /> + `translate3d(${x}px, 0, 0)` + ), + }} + > )} -
+