Skip to content

Commit

Permalink
feat: add title bar to drag windows, scrolling, styling
Browse files Browse the repository at this point in the history
  • Loading branch information
KatoakDR committed Oct 22, 2023
1 parent 6c04a56 commit 12e6b98
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 18 deletions.
97 changes: 92 additions & 5 deletions electron/renderer/components/grid-item/grid-item.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { EuiPanel } from '@elastic/eui';
import {
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiIcon,
EuiSplitPanel,
EuiText,
useEuiOverflowScroll,
} from '@elastic/eui';
import { css } from '@emotion/react';
import {
CSSProperties,
MouseEvent,
Expand Down Expand Up @@ -46,6 +55,40 @@ interface GridItemProps {
children?: ReactNode;
}

/**
* The grid layout pushes resizable handles as children of the grid item.
* When the scrollbar for the content is displayed then it creates a
* barrier between the right-most edge of the grid item and its content.
* Yet the resizable handles are still visible on the grid item's edge
* just not clickable in that position, it's now offset by the scrollbar.
* To mitigate this adjustment, we move the resizable handles to the the
* outside of the scrollable content.
*/
function separateResizeHandleComponents(nodes: ReactNode): {
children: Array<ReactNode>;
resizeHandles: Array<ReactNode>;
} {
const children = [];
const resizeHandles = [];

if (Array.isArray(nodes)) {
for (const child of nodes) {
if (child.key?.startsWith('resizableHandle-')) {
resizeHandles.push(child);
} else {
children.push(child);
}
}
} else {
children.push(nodes);
}

return {
resizeHandles,
children,
};
}

/**
* How to use custom components as react-grid-layout children.
* https://github.com/react-grid-layout/react-grid-layout/tree/master?tab=readme-ov-file#custom-child-components-and-draggable-handles
Expand All @@ -57,17 +100,61 @@ const GridItem: React.FC<GridItemProps> = forwardRef<
>((props, ref): JSX.Element => {
const { style, className, children, ...otherProps } = props;

const gridItemContentStyles = css`
white-space: pre-wrap;
${useEuiOverflowScroll('y', false)}
`;

const { resizeHandles, children: gridItemChildren } =
separateResizeHandleComponents(children);

return (
<EuiPanel
<EuiSplitPanel.Outer
panelRef={ref}
hasBorder={true}
grow={false}
hasBorder={true}
style={style}
className={className}
{...otherProps}
>
{children}
</EuiPanel>
<EuiSplitPanel.Inner grow={false} color="subdued" paddingSize="none">
<EuiFlexGroup
responsive={false}
alignItems="center"
justifyContent="flexStart"
gutterSize="none"
>
<EuiFlexItem grow={1} className={'grab-handle'}>
<EuiIcon type="grabOmnidirectional" />
</EuiFlexItem>
<EuiFlexItem grow={true} className={'grab-handle'}>
<EuiText size="xs">{'Room'}</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup
responsive={false}
alignItems="center"
justifyContent="flexEnd"
>
<EuiButtonIcon
aria-label="Close"
iconType="cross"
color="accent"
size="xs"
/>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiSplitPanel.Inner>
<EuiSplitPanel.Inner
grow={true}
paddingSize="none"
css={gridItemContentStyles}
>
{gridItemChildren}
</EuiSplitPanel.Inner>
{resizeHandles}
</EuiSplitPanel.Outer>
);
});

Expand Down
29 changes: 16 additions & 13 deletions electron/renderer/components/grid/grid.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EuiText, useEuiOverflowScroll, useEuiTheme } from '@elastic/eui';
import { EuiText, useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';
import Head from 'next/head';
import { useMemo, useRef, useState } from 'react';
Expand All @@ -9,21 +9,23 @@ const Grid: React.FC = (): JSX.Element => {
const { euiTheme } = useEuiTheme();

const gridLayoutStyles = css`
.react-grid-layout {
background: ${euiTheme.colors.lightestShade};
}
.react-grid-item {
padding: ${euiTheme.size.xs};
}
.react-grid-item.react-grid-placeholder {
background: ${euiTheme.colors.warning};
}
.react-grid-item .grab-handle {
cursor: grab;
}
.react-grid-item .grab-handle:active {
cursor: grabbing;
}
`;

const gridItemTextStyles = css`
font-family: ${euiTheme.font.familyCode};
white-space: pre-wrap;
${useEuiOverflowScroll('y', true)}
font-size: ${euiTheme.size.m};
line-height: 'initial';
color: ${euiTheme.colors.emptyShade};
background: ${euiTheme.colors.darkestShade};
`;

/**
Expand All @@ -49,9 +51,9 @@ const Grid: React.FC = (): JSX.Element => {
* then the grid item will rerender.
*/
const [layout, setLayout] = useState([
{ i: 'a', x: 0, y: 0, w: 3, h: 2 },
{ i: 'b', x: 3, y: 0, w: 3, h: 2 },
{ i: 'c', x: 6, y: 0, w: 3, h: 2 },
{ i: 'a', x: 0, y: 0, w: 3, h: 2, title: 'Room' },
{ i: 'b', x: 3, y: 0, w: 3, h: 2, title: 'Spells' },
{ i: 'c', x: 6, y: 0, w: 3, h: 2, title: 'Combat' },
]);

/**
Expand All @@ -64,7 +66,7 @@ const Grid: React.FC = (): JSX.Element => {
return layout.map((item) => {
return (
<GridItem key={item.i} ref={useRef(null)}>
<EuiText css={gridItemTextStyles}>{item.i}</EuiText>
<EuiText css={gridItemTextStyles}>Hello World</EuiText>
</GridItem>
);
});
Expand Down Expand Up @@ -93,6 +95,7 @@ const Grid: React.FC = (): JSX.Element => {
isDroppable={true}
isResizable={true}
resizeHandles={['se']}
draggableHandle={'.grab-handle'}
>
{children}
</ResponsiveGridLayout>
Expand Down

0 comments on commit 12e6b98

Please sign in to comment.