Skip to content

Commit

Permalink
fix(react-components): 3D resources Submenu disappear in FDX when hov…
Browse files Browse the repository at this point in the history
…ered (#3570)

* fixed Submenu disappear issue occuring in FDX when mouse cursor is hovered on the menu items

* removed unused state in layerscontainer

* updated appending of 3D resource components to use context of Div element Ref

---------

Co-authored-by: cognite-bulldozer[bot] <51074376+cognite-bulldozer[bot]@users.noreply.github.com>
  • Loading branch information
pramodcog and cognite-bulldozer[bot] authored Aug 14, 2023
1 parent db50158 commit 231f367
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { ModelsLoadingStateContext } from '../Reveal3DResources/ModelsLoadingCon
import { SDKProvider } from './SDKProvider';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { useRevealKeepAlive } from '../RevealKeepAlive/RevealKeepAliveContext';
import { RevealContainerElementContext } from './RevealContainerElementContext';

type RevealContainerProps = {
color?: Color;
Expand Down Expand Up @@ -67,14 +68,21 @@ export function RevealContainer({
);

function mountChildren(): ReactElement {
if (viewer === undefined || viewerDomElement.current === null) return <></>;
if (
viewer === undefined ||
viewerDomElement.current === null ||
wrapperDomElement.current === null
)
return <></>;
return (
<>
<RevealContext.Provider value={viewer}>
<ModelsLoadingProvider>
{createPortal(children, viewerDomElement.current)}
</ModelsLoadingProvider>
</RevealContext.Provider>
<RevealContainerElementContext.Provider value={wrapperDomElement.current}>
<RevealContext.Provider value={viewer}>
<ModelsLoadingProvider>
{createPortal(children, viewerDomElement.current)}
</ModelsLoadingProvider>
</RevealContext.Provider>
</RevealContainerElementContext.Provider>
</>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*!
* Copyright 2023 Cognite AS
*/

import { createContext, useContext } from 'react';

export const RevealContainerElementContext = createContext<HTMLDivElement | null>(null);

export const useRevealContainerElement = (): HTMLDivElement => {
const element = useContext(RevealContainerElementContext);
if (element === null) {
throw new Error(
'useRevealContainerElement must be used within a RevealContainerElementContextProvider'
);
}
return element;
};
13 changes: 12 additions & 1 deletion react-components/src/components/RevealToolbar/LayersButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,13 @@ import {
import { useReveal } from '../RevealContainer/RevealContext';
import { use3DModelName } from '../../hooks/use3DModelName';
import { isEqual } from 'lodash';
import { useRevealContainerElement } from '../RevealContainer/RevealContainerElementContext';

export const LayersButton = (): ReactElement => {
const viewer = useReveal();
const revealContainerElement = useRevealContainerElement();
const [layersEnabled, setLayersEnabled] = useState<boolean>(false);
const [visible, setVisible] = useState<boolean>(false);

const [cadModelIds, setCadModelIds] = useState<number[]>([]);
const [pointCloudModelIds, setPointCloudModelIds] = useState<number[]>([]);
Expand All @@ -36,6 +39,7 @@ export const LayersButton = (): ReactElement => {

const showLayers = (): void => {
setLayersEnabled(!layersEnabled);
setVisible((prevState) => !prevState);
};

useEffect(() => {
Expand Down Expand Up @@ -146,9 +150,15 @@ export const LayersButton = (): ReactElement => {
setReveal3DResourcesLayerData(updated3DResourcesLayerData);
}, [updated3DResourcesLayerData]);

useEffect(() => {
viewer.on('click', () => {
setVisible(false);
});
}, [viewer]);

return (
<Dropdown
appendTo={document.body}
appendTo={revealContainerElement ?? document.body}
content={
<LayersContainer
props={{
Expand All @@ -157,6 +167,7 @@ export const LayersButton = (): ReactElement => {
}}
/>
}
visible={visible}
placement="auto">
<Button type="ghost" icon="Layers" aria-label="3D Resource layers" onClick={showLayers} />
</Dropdown>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
* Copyright 2023 Cognite AS
*/

import { type ReactElement } from 'react';
import { useState, type ReactElement } from 'react';
import { useReveal } from '../../RevealContainer/RevealContext';
import { type CogniteCadModel } from '@cognite/reveal';
import { Checkbox, Flex, Menu } from '@cognite/cogs.js';
import { StyledChipCount, StyledLabel, StyledSubMenu } from './elements';
import { uniqueId } from 'lodash';
import { type Reveal3DResourcesLayersProps } from './types';
import { useRevealContainerElement } from '../../RevealContainer/RevealContainerElementContext';

export const CadModelLayersContainer = ({
layerProps
}: {
layerProps: Reveal3DResourcesLayersProps;
}): ReactElement => {
const viewer = useReveal();
const revealContainerElement = useRevealContainerElement();
const [visible, setVisible] = useState(false);

const { cadLayerData } = layerProps.reveal3DResourcesLayerData;

Expand Down Expand Up @@ -63,6 +66,7 @@ export const CadModelLayersContainer = ({
{cadLayerData.map((data) => (
<Menu.Item
key={uniqueId()}
hideTooltip={true}
hasCheckbox
checkboxProps={{
checked: data.isToggled,
Expand All @@ -81,14 +85,28 @@ export const CadModelLayersContainer = ({
return (
<>
{cadLayerData.length > 0 && (
<Menu.Submenu content={cadModelContent()} title="CAD models">
<Flex direction="row" justifyContent="space-between" gap={4}>
<Menu.Submenu
appendTo={revealContainerElement ?? document.body}
visible={visible}
onClickOutside={() => {
setVisible(false);
}}
content={cadModelContent()}
title="CAD models">
<Flex
direction="row"
justifyContent="space-between"
gap={4}
onClick={() => {
setVisible((prevState) => !prevState);
}}>
<Checkbox
checked={someModelVisible}
indeterminate={indeterminate}
onChange={(e) => {
e.stopPropagation();
handleAllCadModelsVisibility(e.target.checked);
setVisible(true);
}}
/>
<StyledLabel> CAD models </StyledLabel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@
* Copyright 2023 Cognite AS
*/

import { type ReactElement } from 'react';
import { useState, type ReactElement } from 'react';
import { useReveal } from '../../RevealContainer/RevealContext';
import { Checkbox, Flex, Menu } from '@cognite/cogs.js';
import { StyledChipCount, StyledLabel, StyledSubMenu } from './elements';
import { type Image360Collection } from '@cognite/reveal';
import { uniqueId } from 'lodash';
import { type Reveal3DResourcesLayersProps } from './types';
import { useRevealContainerElement } from '../../RevealContainer/RevealContainerElementContext';

export const Image360CollectionLayerContainer = ({
layerProps
}: {
layerProps: Reveal3DResourcesLayersProps;
}): ReactElement => {
const viewer = useReveal();
const revealContainerElement = useRevealContainerElement();
const [visible, setVisible] = useState(false);
const { image360LayerData } = layerProps.reveal3DResourcesLayerData;

const count = image360LayerData.length.toString();
Expand Down Expand Up @@ -79,14 +82,27 @@ export const Image360CollectionLayerContainer = ({
return (
<>
{image360LayerData.length > 0 && (
<Menu.Submenu content={image360Content()} title="360 images">
<Flex direction="row" justifyContent="space-between">
<Menu.Submenu
appendTo={revealContainerElement ?? document.body}
visible={visible}
onClickOutside={() => {
setVisible(false);
}}
content={image360Content()}
title="360 images">
<Flex
direction="row"
justifyContent="space-between"
onClick={() => {
setVisible((prevState) => !prevState);
}}>
<Checkbox
checked={someImagesVisible}
indeterminate={indeterminate}
onChange={(e) => {
e.stopPropagation();
handleAll360ImagesVisibility(e.target.checked);
setVisible(true);
}}
/>
<StyledLabel> 360 images </StyledLabel>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,24 @@
* Copyright 2023 Cognite AS
*/

import { type ReactElement } from 'react';
import { useState, type ReactElement } from 'react';

import { useReveal } from '../../RevealContainer/RevealContext';
import { Checkbox, Flex, Menu } from '@cognite/cogs.js';
import { StyledChipCount, StyledLabel, StyledSubMenu } from './elements';
import { type CognitePointCloudModel } from '@cognite/reveal';
import { uniqueId } from 'lodash';
import { type Reveal3DResourcesLayersProps } from './types';
import { useRevealContainerElement } from '../../RevealContainer/RevealContainerElementContext';

export const PointCloudLayersContainer = ({
layerProps
}: {
layerProps: Reveal3DResourcesLayersProps;
}): ReactElement => {
const viewer = useReveal();
const revealContainerElement = useRevealContainerElement();
const [visible, setVisible] = useState(false);
const { pointCloudLayerData } = layerProps.reveal3DResourcesLayerData;
const count = pointCloudLayerData.length.toString();
const someModelVisible = !pointCloudLayerData.every((data) => !data.isToggled);
Expand Down Expand Up @@ -74,14 +77,27 @@ export const PointCloudLayersContainer = ({
return (
<>
{pointCloudLayerData.length > 0 && (
<Menu.Submenu openOnHover={false} content={pointCloudModelContent()} title="Point clouds">
<Flex direction="row" justifyContent="space-between">
<Menu.Submenu
appendTo={revealContainerElement ?? document.body}
visible={visible}
onClickOutside={() => {
setVisible(false);
}}
content={pointCloudModelContent()}
title="Point clouds">
<Flex
direction="row"
justifyContent="space-between"
onClick={() => {
setVisible((prevState) => !prevState);
}}>
<Checkbox
checked={someModelVisible}
indeterminate={indeterminate}
onChange={(e) => {
e.stopPropagation();
handleAllPointCloudModelsVisibility(e.target.checked);
setVisible(true);
}}
/>
<StyledLabel> Point clouds </StyledLabel>
Expand Down

0 comments on commit 231f367

Please sign in to comment.