grafana/public/app/core/components/SplitPaneWrapper/SplitView.tsx
Kristina c3e4f1f876
Explore: Add resize to split view, with Min/Max button (#54420)
* Add split resize to Explore without keeping width in state

* debug commit

* ugly hack around split lib only supporting one child

* Use SplitView to accomodate one or two elements, remove debug code, fix test

* More cleanup, fix state action

* Fix even split from manual size scenario

* cleanup

* Add new state elements to test

* Handle scrollable on internal element for virtualized lists

* Left align overflow button for explore

* Change min/max buttons

* Apply suggestions from code review

Co-authored-by: Giordano Ricci <me@giordanoricci.com>

* Add more suggestions from the code review

* Fix problems tests found

* commit broken test with debug info

* Add test, remove debug code

* Remove second get of panes

* Remove second get of panes

Co-authored-by: Elfo404 <me@giordanoricci.com>
2022-09-23 08:20:33 -05:00

94 lines
2.5 KiB
TypeScript

import { css } from '@emotion/css';
import { useViewportSize } from '@react-aria/utils';
import React, { ReactNode } from 'react';
import SplitPane from 'react-split-pane';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles2 } from '@grafana/ui';
interface Props {
children: [ReactNode, ReactNode];
uiState: { rightPaneSize: number };
minSize?: number;
onResize?: (size: number) => void;
}
const onDragFinished = (size: number, onResize?: (size: number) => void) => {
document.body.style.cursor = 'auto';
onResize?.(size);
};
const onDragStarted = () => {
document.body.style.cursor = 'row-resize';
};
const getResizerStyles = (hasSplit: boolean) => (theme: GrafanaTheme2) =>
css`
position: relative;
display: ${hasSplit ? 'block' : 'none'};
&::before {
content: '';
position: absolute;
transition: 0.2s border-color ease-in-out;
border-right: 1px solid ${theme.colors.border.weak};
height: 100%;
left: 50%;
transform: translateX(-50%);
}
&::after {
background: ${theme.colors.border.weak};
content: '';
position: absolute;
left: 50%;
top: 50%;
transition: 0.2s background ease-in-out;
transform: translate(-50%, -50%);
border-radius: 4px;
height: 200px;
width: 4px;
}
&:hover {
&::before {
border-color: ${theme.colors.primary.main};
}
&::after {
background: ${theme.colors.primary.main};
}
}
cursor: col-resize;
width: ${theme.spacing(2)};
`;
export const SplitView = ({ uiState: { rightPaneSize }, children, minSize = 200, onResize }: Props) => {
const { width } = useViewportSize();
// create two elements for library, even if only one exists (one will be hidden)
const hasSplit = children.filter(Boolean).length === 2;
const existingChildren = [
<React.Fragment key="leftPane">{children[0]}</React.Fragment>,
<React.Fragment key="rightPane">{hasSplit && children[1]}</React.Fragment>,
];
return (
<SplitPane
split="vertical"
size={rightPaneSize}
primary="second"
minSize={minSize}
maxSize={width - minSize}
resizerClassName={useStyles2(getResizerStyles(hasSplit))}
paneStyle={{ overflow: 'auto', display: 'flex', flexDirection: 'column', overflowY: 'scroll' }}
onDragStarted={onDragStarted}
onDragFinished={(size: number) => onDragFinished(size, onResize)}
>
{existingChildren}
</SplitPane>
);
};