Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
839 changes: 633 additions & 206 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"@gravity-ui/i18n": "^1.7.0",
"@gravity-ui/icons": "^2.17.0",
"@gravity-ui/illustrations": "^2.1.0",
"@gravity-ui/navigation": "^3.11.0",
"@gravity-ui/navigation": "^4.0.18",
"@gravity-ui/paranoid": "^3.0.0",
"@gravity-ui/react-data-table": "^2.2.1",
"@gravity-ui/react-unipika": "^0.5.2",
Expand Down
40 changes: 38 additions & 2 deletions src/components/Drawer/Drawer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,38 @@
--gn-drawer-item-position: absolute;
position: relative;

display: flex;
overflow: hidden;
flex: 1 1 0;
flex-direction: column;

width: 100%;
min-width: 0;
height: 100%;
min-height: 0;
max-height: 100%;
}

&__drawer-container > :not(&__item-container) {
flex: 1 1 auto;

min-width: 0;
min-height: 0;
}

&__container {
position: absolute !important;
z-index: var(--ydb-drawer-veil-z-index);
inset-block: 0 !important;
inset-inline: 0 auto !important;

overflow: hidden;

width: 100%;
}

&__container[data-floating-ui-status='initial'] {
pointer-events: none;
}

&__item {
Expand All @@ -15,6 +43,16 @@
height: 100%;
}

&__item-container {
position: absolute;
inset-block: 0;
inset-inline-start: 0;

width: 100%;

pointer-events: none;
}
Comment thread
astandrik marked this conversation as resolved.

&__controls {
margin-left: auto;
}
Expand All @@ -36,8 +74,6 @@
flex-direction: column;

height: 100%;
//split-pane resizer size
margin-left: var(--g-spacing-2);
}
&__click-handler {
display: contents;
Expand Down
112 changes: 66 additions & 46 deletions src/components/Drawer/Drawer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React from 'react';

import {Xmark} from '@gravity-ui/icons';
import {DrawerItem, Drawer as GravityDrawer} from '@gravity-ui/navigation';
import {ActionTooltip, Button, Flex, Icon, Text} from '@gravity-ui/uikit';
import {ActionTooltip, Button, Flex, Drawer as GravityDrawer, Icon, Text} from '@gravity-ui/uikit';
import {debounce} from 'lodash';

import {cn} from '../../utils/cn';
import {useSetting} from '../../utils/hooks/useSetting';
import {CopyLinkButton} from '../CopyLinkButton/CopyLinkButton';
import {Portal} from '../Portal/Portal';

import {useDrawerContext} from './DrawerContext';
import {
Expand Down Expand Up @@ -73,6 +71,7 @@ const DrawerPaneContentWrapper = ({
}, [containerWidth, defaultWidth, isPercentageWidth, savedWidthString]);

const drawerWidth = userDrawerWidth ?? derivedDrawerWidth;

// Calculate drawer width based on container width percentage if specified
const calculatedWidth = React.useMemo(() => {
if (isPercentageWidth && containerWidth > 0) {
Expand All @@ -83,27 +82,32 @@ const DrawerPaneContentWrapper = ({
return drawerWidth || DEFAULT_DRAWER_WIDTH;
}, [containerWidth, isPercentageWidth, drawerWidth]);

const drawerOverlayStyle = React.useMemo<React.CSSProperties | undefined>(() => {
return containerWidth > 0 ? {width: containerWidth} : undefined;
}, [containerWidth]);

React.useEffect(() => {
if (!detectClickOutside) {
if (!detectClickOutside || !isVisible) {
return undefined;
}

const handleClickOutside = (event: DrawerEvent) => {
//skip if event is captured inside drawer or not triggered by user
if (event._capturedInsideDrawer || !event.isTrusted) {
return;
}
if (
isVisible &&
drawerRef.current &&
!drawerRef.current.contains(event.target as Node)
) {

if (drawerRef.current && !drawerRef.current.contains(event.target as Node)) {
onClose();
}
};

document.addEventListener('click', handleClickOutside);
// Attach after the opening click finishes so the same trusted event cannot close the drawer.
const listenerTimeoutId = window.setTimeout(() => {
document.addEventListener('click', handleClickOutside);
});

return () => {
window.clearTimeout(listenerTimeoutId);
document.removeEventListener('click', handleClickOutside);
};
}, [isVisible, onClose, detectClickOutside]);
Expand All @@ -118,16 +122,28 @@ const DrawerPaneContentWrapper = ({
};
}, [saveWidthDebounced]);

const handleResizeDrawer = (width: number) => {
const normalized = normalizeDrawerWidthFromResize({
resizedWidthPx: width,
isPercentageWidth,
containerWidth,
});
const handleResizeDrawer = React.useCallback(
(width: number) => {
const normalized = normalizeDrawerWidthFromResize({
resizedWidthPx: width,
isPercentageWidth,
containerWidth,
});

setUserDrawerWidth(normalized.drawerWidth);
saveWidthDebounced(normalized.savedWidthString);
};
setUserDrawerWidth(normalized.drawerWidth);
saveWidthDebounced(normalized.savedWidthString);
},
[containerWidth, isPercentageWidth, saveWidthDebounced],
);

const handleOpenChange = React.useCallback(
(open: boolean) => {
if (!open) {
onClose();
}
},
[onClose],
);

const handleClickInsideDrawer = (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
const nativeEvent = event.nativeEvent as DrawerEvent;
Expand All @@ -140,30 +156,28 @@ const DrawerPaneContentWrapper = ({
}

return (
<Portal container={itemContainer}>
<GravityDrawer
onEscape={onClose}
onVeilClick={onClose}
hideVeil={hideVeil}
className={b('container', className)}
>
<DrawerItem
id={drawerId}
visible={isVisible}
resizable
maxResizeWidth={containerWidth}
width={calculatedWidth}
onResize={handleResizeDrawer}
direction={direction}
className={b('item')}
ref={detectClickOutside ? drawerRef : undefined}
>
<div className={b('click-handler')} onClickCapture={handleClickInsideDrawer}>
{children}
</div>
</DrawerItem>
</GravityDrawer>
</Portal>
<GravityDrawer
qa={drawerId}
open={isVisible}
onOpenChange={handleOpenChange}
placement={direction}
hideVeil={hideVeil}
className={b('container', className)}
contentClassName={b('item')}
style={drawerOverlayStyle}
container={itemContainer}
resizable
maxSize={containerWidth || undefined}
size={calculatedWidth}
onResizeEnd={handleResizeDrawer}
disableBodyScrollLock
disableOutsideClick={detectClickOutside}
floatingRef={detectClickOutside ? drawerRef : undefined}
>
<div className={b('click-handler')} onClickCapture={handleClickInsideDrawer}>
{children}
</div>
</GravityDrawer>
);
};

Expand Down Expand Up @@ -207,11 +221,17 @@ export const DrawerWrapper = ({
headerClassName,
hideVeil,
}: DrawerPaneProps) => {
const onCloseDrawerRef = React.useRef(onCloseDrawer);

React.useEffect(() => {
onCloseDrawerRef.current = onCloseDrawer;
}, [onCloseDrawer]);

React.useEffect(() => {
return () => {
onCloseDrawer();
onCloseDrawerRef.current();
};
}, [onCloseDrawer]);
}, []);

const renderDrawerHeader = () => {
const controls = [];
Expand Down
11 changes: 7 additions & 4 deletions src/components/Drawer/DrawerContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,12 @@ export const DrawerContextProvider = ({children, className}: DrawerContextProvid

const updateWidth = () => {
if (containerRef.current) {
setContainerWidth(containerRef.current.clientWidth);
const containerRect = containerRef.current.getBoundingClientRect();
const visibleLeft = Math.max(containerRect.left, 0);
const visibleRight = Math.min(containerRect.right, window.innerWidth);
const visibleWidth = Math.max(0, visibleRight - visibleLeft);

setContainerWidth(visibleWidth || containerRef.current.clientWidth);
}
};

Expand All @@ -47,9 +52,7 @@ export const DrawerContextProvider = ({children, className}: DrawerContextProvid
resizeObserver.observe(containerRef.current);

return () => {
if (containerRef.current) {
resizeObserver.disconnect();
}
resizeObserver.disconnect();
};
}, []);

Expand Down
14 changes: 0 additions & 14 deletions src/containers/App/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -104,20 +104,6 @@ body,
color: var(--g-color-text-secondary);
}

.gn-aside-header__pane-container {
height: 100%;
}

.gn-aside-header__content {
position: relative;

display: flex;
overflow: auto;
flex-direction: column;

height: 100%;
}

.loader {
@include mixins.loader();
}
Expand Down
10 changes: 10 additions & 0 deletions src/containers/AsideNavigation/AsideNavigation.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
.kv-navigation {
&__content {
position: relative;

display: flex;
overflow: auto;
flex-direction: column;

height: 100%;
}

&__internal-user {
display: flex;
justify-content: space-between;
Expand Down
Loading
Loading