I am attempting to create a Panel component that has the option to be wrapped in a PanelGroup component. The PanelGroup components main function is the query the children Panel components and determine if certain conditions so it can add a z-index prop to each of them according to the conditions.
- Is it a left, right, top or bottom positioned Panel
- Is it a nested Panel
Each condition will require a z-index that may be higher than the others and also placed in front of the highest z-index found on the page. I would like to be able to iterate though the children inside a useEffect and after logic is ran to determine the hierarchy, add the z-index to each child as a prop. I have attempted to use React.Children mapping through and using cloneElement to add the z-index, however the issue is this method must be called inside the render/return and when a second panel is opened it causes any other panel that is open to close and open again. Is there a way to update the props without using the top level React API?
PanelGroup API
<PanelGroup>
<Panel
id={'1'}
open={open1}
onClosed={handleClose1}
controller={true}
renderPortal={true}
position={PanelPosition.RIGHT}
>
<div>
<h2>Panel Slide Left</h2>
<button onClick={handleClose1}>Close</button>
</div>
</Panel>
<Panel
id={'2'}
open={open2}
onClosed={handleClose2}
controller={true}
renderPortal={true}
position={PanelPosition.LEFT}
>
<div>
<h2>Panel Slide Right</h2>
<button onClick={handleClose2}>Close</button>
</div>
</Panel>
</PanelGroup>
This is what I tried which does not work
const PanelGroup = ({
children
}: PanelGroupProp): JSX.Element => {
const [highestZIndex, setHighestZIndex] = React.useState(null);
/**
* Handles finding the highest index on the page after render. This value
* will be used as the benchmark to set the z-index of the panel
* components managed by this component.
*/
React.useEffect(() => {
const highestIndex = getHighestZIndex();
setHighestZIndex(highestIndex);
}, []);
const renderGroupPanelChildren = (children): React.ReactElement => {
let incrementor = highestZIndex + 1;
return (
<React.Fragment>
{React.Children.map(children || null, (child) => {
const newProps = {...child.props, ZIndex: incrementor };
incrementor++;
return <child.type {...newProps } key={getGuid()} />;
})}
</React.Fragment>
);
};
return (
<>
<PanelOverlay visibility={false} />
{renderGroupPanelChildren(children)}
</>
);
};
I would like to find a way to do something like:
const PanelGroupComponent = ({
children
}: PanelGroupProp): JSX.Element => {
const [highestZIndex, setHighestZIndex] = React.useState(null);
const [elements, setElements] = React.useState(null);
/**
* Handles finding the highest index on the page after render. This value
* will be used as the benchmark to set the z-index of the panel
* components managed by this component.
*/
React.useEffect(() => {
const highestIndex = getHighestZIndex();
setHighestZIndex(highestIndex);
}, []);
React.useEffect(() => {
// logic to set z-index's ....
const elements ....
setElements(elements);
}, [highestIndex]);
return (
<>
<PanelOverlay visibility={false} />
{elements}
</>
);
};