fix: nav item popup overflow

This commit is contained in:
ascarbek 2023-03-09 22:22:55 +06:00
parent 91e5219627
commit 593446bffe
9 changed files with 52 additions and 26 deletions

View File

@ -12,11 +12,13 @@ export const Popup = ({
className = '',
onOutsideClick,
columns = 1,
style,
}: {
items: IPopupItem[];
className: string;
onOutsideClick?: () => void;
columns?: 1 | 2 | 3;
style?: any;
}) => {
const ref = useRef<HTMLDivElement>(null);
useOutsideClick(ref, () => onOutsideClick && onOutsideClick());
@ -27,7 +29,7 @@ export const Popup = ({
};
return (
<div ref={ref} className={`${className} rounded-lg bg-white px-2 py-2 shadow-md`}>
<div ref={ref} className={`${className} rounded-lg bg-white px-2 py-2 shadow-md`} style={style}>
<div
className={`grid ${columns === 1 && 'grid-cols-1'} ${columns === 2 && 'grid-cols-2'} ${
columns === 3 && 'grid-cols-3'

View File

@ -14,6 +14,7 @@ import { INITIAL_FOLDER_HEIGHT, PAGE_ITEM_HEIGHT } from '../../_shared/constants
export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
const appDispatch = useAppDispatch();
const workspace = useAppSelector((state) => state.workspace);
const foldersStore = useAppSelector((state) => state.folders);
const navigate = useNavigate();
@ -64,6 +65,7 @@ export const useFolderEvents = (folder: IFolder, pages: IPage[]) => {
}, [pages]);
const onFolderNameClick = () => {
appDispatch(foldersActions.toggleShowPages({ id: folder.id }));
if (showPages) {
setFolderHeight(`${INITIAL_FOLDER_HEIGHT}px`);
} else {

View File

@ -12,8 +12,6 @@ import { useEffect, useRef, useState } from 'react';
import { DropDownShowSvg } from '../../_shared/svg/DropDownShowSvg';
import { ANIMATION_DURATION } from '../../_shared/constants';
let timeoutHandle: any;
export const FolderItem = ({
folder,
pages,
@ -47,18 +45,7 @@ export const FolderItem = ({
setOffsetTop,
} = useFolderEvents(folder, pages);
const [hideOverflow, setHideOverflow] = useState(!showPages);
useEffect(() => {
clearTimeout(timeoutHandle);
if (showPages) {
timeoutHandle = setTimeout(() => {
setHideOverflow(!showPages);
}, ANIMATION_DURATION);
} else {
setHideOverflow(!showPages);
}
}, [showPages]);
const [popupY, setPopupY] = useState(0);
const el = useRef<HTMLDivElement>(null);
@ -66,10 +53,17 @@ export const FolderItem = ({
setOffsetTop(el.current?.offsetTop || 0);
}, [el, showPages]);
useEffect(() => {
if (el.current) {
const { top } = el.current.getBoundingClientRect();
setPopupY(top);
}
}, [showFolderOptions, showNewPageOptions, showRenamePopup]);
return (
<div className={'relative'} ref={el}>
<div ref={el}>
<div
className={`relative my-2 ${hideOverflow ? 'overflow-hidden' : ''} transition-all `}
className={`my-2 overflow-hidden transition-all`}
style={{ height: folderHeight, transitionDuration: `${ANIMATION_DURATION}ms` }}
>
<div
@ -84,7 +78,7 @@ export const FolderItem = ({
{folder.title}
</span>
</button>
<div className={'relative flex items-center'}>
<div className={'flex items-center'}>
<Button size={'box-small-transparent'} onClick={() => onFolderOptionsClick()}>
<Details2Svg></Details2Svg>
</Button>
@ -104,6 +98,7 @@ export const FolderItem = ({
onDeleteClick={() => deleteFolder()}
onDuplicateClick={() => duplicateFolder()}
onClose={() => closePopup()}
top={popupY - 124 + 40}
></NavItemOptionsPopup>
)}
{showNewPageOptions && (
@ -112,6 +107,7 @@ export const FolderItem = ({
onBoardClick={() => onAddNewBoardPage()}
onGridClick={() => onAddNewGridPage()}
onClose={() => closePopup()}
top={popupY - 124 + 40}
></NewPagePopup>
)}
{showRenamePopup && (
@ -119,6 +115,7 @@ export const FolderItem = ({
value={folder.title}
onChange={(newTitle) => changeFolderTitle(newTitle)}
onClose={closeRenamePopup}
top={popupY - 124 + 40}
></RenamePopup>
)}
</div>

View File

@ -8,11 +8,13 @@ export const NavItemOptionsPopup = ({
onDeleteClick,
onDuplicateClick,
onClose,
top,
}: {
onRenameClick: () => void;
onDeleteClick: () => void;
onDuplicateClick: () => void;
onClose?: () => void;
top: number;
}) => {
const items: IPopupItem[] = [
{
@ -48,7 +50,8 @@ export const NavItemOptionsPopup = ({
<Popup
onOutsideClick={() => onClose && onClose()}
items={items}
className={'absolute right-0 top-[40px] z-10'}
className={`absolute right-0`}
style={{ top: `${top}px` }}
></Popup>
);
};

View File

@ -7,7 +7,7 @@ import { NavigationResizer } from './NavigationResizer';
import { IFolder } from '../../../stores/reducers/folders/slice';
import { IPage } from '../../../stores/reducers/pages/slice';
import { useNavigate } from 'react-router-dom';
import React, { useEffect, useRef } from 'react';
import React, { useRef } from 'react';
import { useDispatch } from 'react-redux';
import { useAppSelector } from '../../../stores/store';
import { ANIMATION_DURATION, NAV_PANEL_MINIMUM_WIDTH } from '../../_shared/constants';
@ -46,8 +46,10 @@ export const NavigationPanel = ({
<div className={'flex flex-col'}>
<AppLogo iconToShow={'hide'} onHideMenuClick={onHideMenuClick}></AppLogo>
<WorkspaceUser></WorkspaceUser>
<div className={'flex flex-col overflow-auto px-2'} style={{ height: 'calc(100vh - 300px)' }} ref={el}>
<WorkspaceApps folders={folders} pages={pages} onPageClick={onPageClick} />
<div className={'relative flex flex-col'} style={{ height: 'calc(100vh - 300px)' }} ref={el}>
<div className={'flex flex-col overflow-auto px-2'}>
<WorkspaceApps folders={folders} pages={pages} onPageClick={onPageClick} />
</div>
</div>
</div>

View File

@ -8,11 +8,13 @@ export const NewPagePopup = ({
onGridClick,
onBoardClick,
onClose,
top,
}: {
onDocumentClick: () => void;
onGridClick: () => void;
onBoardClick: () => void;
onClose?: () => void;
top: number;
}) => {
const items: IPopupItem[] = [
{
@ -48,7 +50,8 @@ export const NewPagePopup = ({
<Popup
onOutsideClick={() => onClose && onClose()}
items={items}
className={'absolute right-0 top-[40px] z-10'}
className={'absolute right-0'}
style={{ top: `${top}px` }}
></Popup>
);
};

View File

@ -8,7 +8,7 @@ import { Button } from '../../_shared/Button';
import { usePageEvents } from './PageItem.hooks';
import { RenamePopup } from './RenamePopup';
import { ViewLayoutTypePB } from '../../../../services/backend';
import { useEffect, useRef } from 'react';
import { useEffect, useRef, useState } from 'react';
import { PAGE_ITEM_HEIGHT } from '../../_shared/constants';
export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () => void }) => {
@ -32,8 +32,17 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () =
setOffsetTop(el.current?.offsetTop || 0);
}, [el.current]);
const [popupY, setPopupY] = useState(0);
useEffect(() => {
if (showPageOptions && el.current) {
const { top } = el.current.getBoundingClientRect();
setPopupY(top);
}
}, [showPageOptions]);
return (
<div className={'relative'} ref={el}>
<div ref={el}>
<div
onClick={() => onPageClick()}
className={`flex cursor-pointer items-center justify-between rounded-lg pl-8 pr-4 hover:bg-surface-2 ${
@ -51,7 +60,7 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () =
{page.title}
</span>
</button>
<div className={'relative flex items-center'}>
<div className={'flex items-center'}>
<Button size={'box-small-transparent'} onClick={() => onPageOptionsClick()}>
<Details2Svg></Details2Svg>
</Button>
@ -63,6 +72,7 @@ export const PageItem = ({ page, onPageClick }: { page: IPage; onPageClick: () =
onDeleteClick={() => deletePage()}
onDuplicateClick={() => duplicatePage()}
onClose={() => closePopup()}
top={popupY - 124 + 40}
></NavItemOptionsPopup>
)}
{showRenamePopup && (

View File

@ -6,11 +6,13 @@ export const RenamePopup = ({
onChange,
onClose,
className = '',
top,
}: {
value: string;
onChange: (newTitle: string) => void;
onClose: () => void;
className?: string;
top?: number;
}) => {
const ref = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
@ -32,6 +34,7 @@ export const RenamePopup = ({
className={
'absolute left-[50px] top-[40px] z-10 flex w-[300px] rounded bg-white py-1 px-1.5 shadow-md ' + className
}
style={{ top: `${top}px` }}
>
<input
ref={inputRef}

View File

@ -4,6 +4,7 @@ export interface IFolder {
id: string;
title: string;
offsetTop?: number;
showPages?: boolean;
}
const initialState: IFolder[] = [];
@ -27,6 +28,9 @@ export const foldersSlice = createSlice({
setOffsetTop(state, action: PayloadAction<{ id: string; offset: number }>) {
return state.map((f) => (f.id === action.payload.id ? { ...f, offsetTop: action.payload.offset } : f));
},
toggleShowPages(state, action: PayloadAction<{ id: string }>) {
return state.map((f) => (f.id === action.payload.id ? { ...f, showPages: !f.showPages } : f));
},
},
});