Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DOCS]fix: sidemenu opening smoother #1021

Merged
merged 13 commits into from
Oct 11, 2023
2 changes: 2 additions & 0 deletions .changeset/hip-crews-ring.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
28 changes: 13 additions & 15 deletions packages/apps/docs/src/components/Layout/Landing/Landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,19 @@ export const Landing: FC<IBasePageProps> = ({
const gridClassNames = classnames(globalClass, baseGridClass, pageGridClass);

return (
<div className={gridClassNames}>
<Template menuItems={leftMenuTree} layout="landing">
<TitleHeader
title={frontmatter.title}
subTitle={frontmatter.subTitle}
/>

<div
id="maincontent"
className={classnames(contentClass, contentClassVariants.code)}
>
<article className={articleClass}>{children}</article>
</div>
</Template>
</div>
<>
<TitleHeader title={frontmatter.title} subTitle={frontmatter.subTitle} />
<div className={gridClassNames}>
<Template menuItems={leftMenuTree} layout="landing">
<div
id="maincontent"
className={classnames(contentClass, contentClassVariants.code)}
>
<article className={articleClass}>{children}</article>
</div>
</Template>
</div>
</>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { darkThemeClass, sprinkles, vars } from '@kadena/react-ui/theme';

import { $$navMenu, $$pageWidth } from '../../global.css';
import { $$footerMenu, $$pageWidth } from '../../global.css';

import { style } from '@vanilla-extract/css';

Expand All @@ -11,7 +11,7 @@ export const footerWrapperClass = style([
marginTop: '$20',
}),
{
zIndex: $$navMenu,
zIndex: $$footerMenu,
gridArea: 'footer',
selectors: {
[`${darkThemeClass} &`]: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const menuClass = style([
overflow: 'hidden',
top: '$17',
bottom: 0,
paddingBottom: '$4',
}),
{
height: `calc(100vh - ${vars.sizes.$13})`,
Expand Down Expand Up @@ -63,7 +64,10 @@ export const menuInLayoutVariants = styleVariants({
});

export const menuLayoutVariants = styleVariants({
landing: responsiveStyle({ md: { paddingTop: '290px' } }),
landing: {
...responsiveStyle({ md: {} }),
},

normal: {},
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ interface IProps {
}

export const SideMenu: FC<IProps> = ({ closeMenu, menuItems }) => {
const { active, clickMenu, clickSubMenu, setActive } = useSideMenu(
const { active, clickMenu, clickSubMenu, setActive, treeRef } = useSideMenu(
closeMenu,
menuItems,
);
Expand Down Expand Up @@ -66,7 +66,6 @@ export const SideMenu: FC<IProps> = ({ closeMenu, menuItems }) => {
<Heading as="h5">{activeItem?.menu}</Heading>
</button>
)}

<ShowOnMobile>
<Box marginX="$4" marginBottom="$8" marginTop="$4">
<Input
Expand All @@ -80,7 +79,6 @@ export const SideMenu: FC<IProps> = ({ closeMenu, menuItems }) => {
/>
</Box>
</ShowOnMobile>

<MenuCard cyTestId="sidemenu-main" active={active} idx={0}>
<ul className={listClass}>
{menuItems.map((item) => (
Expand All @@ -105,7 +103,7 @@ export const SideMenu: FC<IProps> = ({ closeMenu, menuItems }) => {
idx={1}
onClick={clickSubMenu}
>
<TreeList root={true}>
<TreeList ref={treeRef} root={true}>
<MainTreeItem item={activeItem} root={true} />
</TreeList>
</MenuCard>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { sprinkles, vars } from '@kadena/react-ui/theme';
import { responsiveStyle, sprinkles, vars } from '@kadena/react-ui/theme';

import { style } from '@vanilla-extract/css';

export const sideMenuClass = style([
sprinkles({
position: 'relative',
height: '100%',
paddingBottom: '$25',
}),
{
height: `calc(100vh - ${vars.sizes.$18})`,
overflowY: 'auto',
overflowX: 'hidden',
...responsiveStyle({
md: {
height: `calc(100vh - ${vars.sizes.$48})`,
},
}),
},
]);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,80 @@
import type { IMenuItem } from '@/Layout';
import { hasSameBasePath } from '@/utils/hasSameBasePath';
import { useRouter } from 'next/router';
import type { MouseEventHandler } from 'react';
import { useEffect, useState } from 'react';
import type { MouseEventHandler, RefObject } from 'react';
import { useEffect, useRef, useState } from 'react';

interface IReturn {
clickSubMenu: MouseEventHandler<HTMLUListElement>;
clickMenu: (e: React.MouseEvent<HTMLAnchorElement>, item: IMenuItem) => void;
active: number;
setActive: React.Dispatch<React.SetStateAction<number>>;
treeRef: RefObject<HTMLUListElement>;
}

export const useSideMenu = (
closeMenu: () => void,
menuItems: IMenuItem[],
): IReturn => {
const router = useRouter();
const treeRef = useRef<HTMLUListElement>(null);
const [oldPathname, setOldPathname] = useState<string>('');
const [active, setActive] = useState<number>(1);

const [offsetScroll, setOffsetScroll] = useState<number>(0);

const findParentUlButton = (elm?: Element): HTMLElement | null => {
if (!elm) return null;

let foundElm: HTMLElement | null = elm.parentElement;

while (
foundElm?.tagName.toLowerCase() !== 'button' ||
foundElm.tagName.toLowerCase() === 'section'
) {
if (!foundElm || foundElm.tagName.toLowerCase() === 'section') {
break;
}

const foundButton: HTMLElement | null | undefined =
foundElm.querySelector(':scope > button') as HTMLElement;
if (foundButton) {
foundElm = foundButton;
break;
}
foundElm = foundElm.parentElement;
}

return foundElm;
};

useEffect(() => {
if (treeRef.current) {
const elms = treeRef.current.querySelectorAll('[data-active="true"]');
const lastElm = elms[elms.length - 1];

const elm = findParentUlButton(lastElm);
if (!elm) return;

setOffsetScroll(elm.offsetTop);
}
}, [treeRef, setOffsetScroll]);

useEffect(() => {
if (offsetScroll > 0) {
setTimeout(() => {
// scrollintoview will not work correctly in a element with overFlow:'scroll'
treeRef.current?.parentElement?.scroll({
top: offsetScroll,
left: 0,
behavior: 'smooth',
});
}, 250);

setOffsetScroll(0);
}
}, [treeRef, offsetScroll, setOffsetScroll]);

useEffect(() => {
setOldPathname(router.pathname);

Expand Down Expand Up @@ -58,6 +114,12 @@ export const useSideMenu = (

const clickSubMenu: MouseEventHandler<HTMLUListElement> = (e) => {
const clickedItem = e.target as HTMLAnchorElement;

if (clickedItem.dataset.active !== 'true') {
const elm = findParentUlButton(clickedItem);
setOffsetScroll(elm?.offsetTop ?? 0);
}

if (clickedItem.tagName.toLowerCase() !== 'a') return;

if (clickedItem.hasAttribute('href')) {
Expand All @@ -70,5 +132,6 @@ export const useSideMenu = (
clickMenu,
active,
setActive,
treeRef,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ export const Template: FC<IProps> = ({

// When we get css from computed style it comes with `px` suffix
const onlyValue = paddingTop.split('px')[0];
setInitialTopSpacing(onlyValue);

setInitialTopSpacing(`${parseInt(onlyValue, 10) + y}`);

// Reset style value when we navigate to different pages

return () => {
setStyle({});
};
Expand All @@ -55,7 +57,7 @@ export const Template: FC<IProps> = ({

useEffect(() => {
if (!mainContentRef.current || !enablePositioning) {
setStyle({});
setStyle({ paddingTop: 0 });
return;
}

Expand All @@ -72,6 +74,7 @@ export const Template: FC<IProps> = ({
return (
<>
<MenuBack isOpen={isMenuOpen} onClick={closeMenu} />

<Menu
dataCy="menu"
isOpen={isMenuOpen}
Expand All @@ -82,6 +85,7 @@ export const Template: FC<IProps> = ({
>
<SideMenu closeMenu={closeMenu} menuItems={menuItems} />
</Menu>

{children}
<Footer />
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Heading, Stack } from '@kadena/react-ui';

import { globalClass } from '../../global.css';

import {
avatarClass,
headerClass,
Expand Down Expand Up @@ -28,7 +30,9 @@ export const TitleHeader: FC<IProps> = ({ title, subTitle, avatar }) => {

useEffect(() => {
if (router.isReady) {
setLoaderHeaderClass(classNames(headerWrapperClass, headerLoadedClass));
setLoaderHeaderClass(
classNames(globalClass, headerWrapperClass, headerLoadedClass),
realdreamer marked this conversation as resolved.
Show resolved Hide resolved
);
}
}, [router.isReady]);
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ export const MainTreeItem: FC<IProps> = ({ item, root = false, level = 1 }) => {
const ref = useRef<HTMLLIElement>(null);

useEffect(() => {
if (!item.isMenuOpen) {
setMenuOpen(false);
}
setMenuOpen(item.isMenuOpen);
}, [item.isMenuOpen]);

useEffect(() => {
Expand All @@ -33,13 +31,15 @@ export const MainTreeItem: FC<IProps> = ({ item, root = false, level = 1 }) => {
const parentScrollHeight = isMounted ? parentUl?.scrollHeight ?? 0 : 0;
const scrollHeight = ul?.scrollHeight ?? 0;

console.log(222, menuOpen, item);
realdreamer marked this conversation as resolved.
Show resolved Hide resolved
if (!menuOpen) {
ul?.style.setProperty('height', '0');
parentUl?.style.setProperty(
'height',
`${parentScrollHeight - scrollHeight}px`,
);
} else {
console.log(11111);
realdreamer marked this conversation as resolved.
Show resolved Hide resolved
ul?.style.setProperty('height', `${scrollHeight}px`);
parentUl?.style.setProperty(
'height',
Expand All @@ -48,7 +48,7 @@ export const MainTreeItem: FC<IProps> = ({ item, root = false, level = 1 }) => {
}

setIsMounted(true);
}, [ref, menuOpen, setIsMounted, isMounted]);
}, [ref, menuOpen, setIsMounted, isMounted, item]);

const nextLevel = (): LevelType => {
if (root) return level;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
} from './styles.css';

import classnames from 'classnames';
import type { FC, ReactNode } from 'react';
import React from 'react';
import type { ReactNode } from 'react';
import React, { forwardRef } from 'react';

interface IProps {
children: ReactNode;
Expand All @@ -15,21 +15,20 @@ interface IProps {
root?: boolean;
}

export const TreeList: FC<IProps> = ({
children,
menuOpen = false,
root = false,
level = 'l1',
}) => {
const classes = classnames(
treeListClass,
treeListLevelVariantClass[level],
treeListRootVariantClass[root ? 'isRoot' : 'isNotRoot'],
);
export const TreeList = forwardRef<HTMLUListElement, IProps>(
({ children, menuOpen = false, root = false, level = 'l1' }, ref) => {
const classes = classnames(
treeListClass,
treeListLevelVariantClass[level],
treeListRootVariantClass[root ? 'isRoot' : 'isNotRoot'],
);

return (
<ul role="list" className={classes}>
{children}
</ul>
);
};
return (
<ul ref={ref} role="list" className={classes}>
{children}
</ul>
);
},
);

TreeList.displayName = 'TreeList';
2 changes: 2 additions & 0 deletions packages/apps/docs/src/components/Layout/global.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { darkThemeClass } from '@kadena/react-ui/theme';
import { createVar, style } from '@vanilla-extract/css';

export const $$navMenu = createVar();
export const $$footerMenu = createVar();
export const $$modalZIndex = createVar();
export const $$pageWidth = createVar();
export const $$leftSideWidth = createVar();
Expand All @@ -13,6 +14,7 @@ export const $$borderColor = createVar();
export const globalClass = style({
vars: {
[$$navMenu]: '998', //zIndex
[$$footerMenu]: '499', //zIndex
[$$modalZIndex]: '1000', //zIndex
[$$sideMenu]: '500', //zIndex
[$$pageWidth]: '1440px', //sizes
Expand Down
Loading