Skip to content

Commit

Permalink
fix: aesthetic display of buttons fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
b-zurg committed Jun 12, 2020
1 parent 6853490 commit c6e5b0c
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 97 deletions.
66 changes: 66 additions & 0 deletions src/components/Resizer/helpers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import styled, { css } from 'styled-components';
import { Fade, Grow, Zoom } from '@material-ui/core';
import { TransitionType, ResizerCollapseButtonProps } from '.';

type OrientationProps = {
isVertical: boolean;
};
export const topBottomCss = css`
top: 0;
bottom: 0;
`;
const leftRightCss = css`
right: 0;
left: 0;
`;

export const ButtonWrapper = styled.div<OrientationProps>`
cursor: pointer;
position: absolute;
`;

type ButtonContainerProps = OrientationProps & { grabberSize: string };
export const ButtonContainer = styled.div<ButtonContainerProps>`
position: absolute;
${props => (props.isVertical ? topBottomCss : leftRightCss)}
${props => (props.isVertical ? 'width: 6rem' : 'height: 6rem')};
transform: ${props =>
props.isVertical
? `translateX(-50%) translateX(calc(${props.grabberSize} / 2))`
: `translateY(-50%) translateY(calc(${props.grabberSize} / 2))`};
display: flex;
align-items: center;
justify-content: center;
`;

export const ResizeGrabber = styled.div<OrientationProps>`
position: absolute;
${props => (props.isVertical ? topBottomCss : leftRightCss)}
z-index: 3;
transform: ${props =>
props.isVertical ? 'translateX(-50%)' : 'translateY(-50%)'};
cursor: ${props => (props.isVertical ? 'col-resize' : 'row-resize')};
`;

export const ResizePresentation = styled.div<{ isVertical: boolean }>`
z-index: 2;
position: absolute;
${props => (props.isVertical ? topBottomCss : leftRightCss)}
`;

type TransitionComponent = typeof Fade | typeof Grow | typeof Zoom;
const transitionComponentMap: {
[key in TransitionType]: TransitionComponent;
} = {
fade: Fade,
grow: Grow,
zoom: Zoom,
};

export const getTransition = (
details: ResizerCollapseButtonProps | undefined
): TransitionComponent => transitionComponentMap[details?.transition ?? 'fade'];

export const getSizeWithUnit = (size: string | number): string =>
isNaN(size as number) ? size.toString() : `${size}px`;
127 changes: 40 additions & 87 deletions src/components/Resizer.tsx → src/components/Resizer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,69 +1,17 @@
import React, { useState, useCallback } from 'react';
import styled, { css } from 'styled-components';
import { Fade, Grow, Zoom } from '@material-ui/core';
import { ClientPosition } from 'components/hooks/useDragStateHandlers';
import React, { useState, useCallback, useMemo } from 'react';
import { Fade } from '@material-ui/core';
import { ClientPosition } from '../hooks/useDragStateHandlers';
import { getTransition, getSizeWithUnit } from '../Resizer/helpers';
import { mergeClasses } from '../SplitPane/helpers';
import {
ButtonContainer,
ButtonWrapper,
ResizeGrabber,
ResizePresentation,
} from './helpers';

export type TransitionType = 'fade' | 'grow' | 'zoom';

type OrientationProps = {
isVertical: boolean;
};

const ButtonWrapper = styled.div<OrientationProps>`
cursor: pointer;
z-index: 3;
`;

const ButtonContainer = styled.div<OrientationProps & { grabberSize: string }>`
${props =>
props.isVertical
? css`
width: 6rem;
height: 100%;
`
: css`
height: 6rem;
width: 100%;
`}
transform: ${props =>
props.isVertical
? `translateX(-50%) translateX(calc(${props.grabberSize} / 2))`
: `translateY(-50%) translateY(calc(${props.grabberSize} / 2))`};
display: flex;
align-items: center;
justify-content: center;
`;

const topBottomCss = css`
top: 0;
bottom: 0;
`;
const leftRightCss = css`
right: 0;
left: 0;
`;

const ResizeGrabber = styled.div<OrientationProps>`
position: absolute;
${props => (props.isVertical ? topBottomCss : leftRightCss)}
z-index: 3;
transform: ${props =>
props.isVertical ? 'translateX(-50%)' : 'translateY(-50%)'};
cursor: ${props => (props.isVertical ? 'col-resize' : 'row-resize')};
`;

const ResizePresentation = styled.div<{ isVertical: boolean }>`
z-index: 2;
position: absolute;
${props => (props.isVertical ? topBottomCss : leftRightCss)}
`;

type TransitionType = 'fade' | 'grow' | 'zoom';
const transitionComponentMap: {
[key in TransitionType]: typeof Fade | typeof Grow | typeof Zoom;
} = {
fade: Fade,
grow: Grow,
zoom: Zoom,
};
export interface ResizerCollapseButtonProps {
button?: React.ReactElement;
transition?: TransitionType;
Expand All @@ -79,6 +27,7 @@ export interface ResizerProps {
resizerHoverCss?: React.CSSProperties;
grabberSize?: string | number;
onDragStarted: (index: number, pos: ClientPosition) => void;
onCollapseToggle: () => void;
}

export const Resizer = React.memo(
Expand All @@ -91,11 +40,13 @@ export const Resizer = React.memo(
resizerCss = { backgroundColor: 'silver' },
resizerHoverCss = { backgroundColor: 'grey' },
collapseButtonDetails,
onCollapseToggle,
}: ResizerProps) => {
const [isHovered, setIsHovered] = useState(false);

const handleMouseDown = useCallback(
(event: React.MouseEvent) => {
event.preventDefault();

onDragStarted(index, event);
},
[index, onDragStarted]
Expand All @@ -104,38 +55,40 @@ export const Resizer = React.memo(
const handleTouchStart = useCallback(
(event: React.TouchEvent) => {
event.preventDefault();

onDragStarted(index, event.touches[0]);
},
[index, onDragStarted]
);

const handleButtonClick = useCallback((event: React.MouseEvent) => {
event.stopPropagation();
console.log('button clicked');
onCollapseToggle();
}, []);
const handleButtonMousedown = useCallback((event: React.MouseEvent) => {
event.stopPropagation();
}, []);

const classes = ['Resizer', split, className].join(' ');
const [isHovered, setIsHovered] = useState(false);
const classes = useMemo(() => mergeClasses(['Resizer', split, className]), [
split,
className,
]);

const isVertical = split === 'vertical';

const widthOrHeightSize = (size: string | number) =>
const getWidthOrHeight = (size: string | number) =>
isVertical ? { width: size } : { height: size };
const grabberSizeWithUnit = useMemo(() => getSizeWithUnit(grabberSize), [
grabberSize,
]);

const Transition = useMemo(() => getTransition(collapseButtonDetails), [
collapseButtonDetails,
]);

const Transition =
transitionComponentMap[collapseButtonDetails?.transition ?? 'fade'];
const button = collapseButtonDetails ? (
const collapseButton = collapseButtonDetails ? (
<ButtonContainer
isVertical={isVertical}
grabberSize={
isNaN(grabberSize as number)
? grabberSize.toString()
: `${grabberSize}px`
}
grabberSize={grabberSizeWithUnit}
>
<Transition in={isHovered} timeout={collapseButtonDetails.timeout}>
<ButtonWrapper
Expand All @@ -149,37 +102,37 @@ export const Resizer = React.memo(
</ButtonContainer>
) : null;

const handleMouseEnter = () => {
const handleMouseEnterGrabber = () => {
setIsHovered(true);
};
const handleMouseLeave = () => {
const handleMouseLeaveGrabber = () => {
setIsHovered(false);
};

return (
<div style={{ position: 'relative' }}>
<ResizeGrabber
isVertical={isVertical}
style={widthOrHeightSize(grabberSize)}
style={getWidthOrHeight(grabberSize)}
role="presentation"
className={classes}
onMouseDown={handleMouseDown}
onTouchStart={handleTouchStart}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
onMouseEnter={handleMouseEnterGrabber}
onMouseLeave={handleMouseLeaveGrabber}
>
{button}
{collapseButton}
</ResizeGrabber>
<Fade in={isHovered === false}>
<ResizePresentation
isVertical={isVertical}
style={{ ...widthOrHeightSize(1), ...resizerCss }}
style={{ ...getWidthOrHeight(1), ...resizerCss }}
/>
</Fade>
<Fade in={isHovered}>
<ResizePresentation
isVertical={isVertical}
style={{ ...widthOrHeightSize(1), ...resizerHoverCss }}
style={{ ...getWidthOrHeight(1), ...resizerHoverCss }}
/>
</Fade>
</div>
Expand Down
22 changes: 17 additions & 5 deletions src/components/SplitPane/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react';
import React, { useMemo, useState } from 'react';

import { Pane } from '../Pane';
import { Resizer, ResizerCollapseButtonProps } from '../Resizer';
Expand Down Expand Up @@ -70,13 +70,24 @@ export const SplitPane = React.memo((props: SplitPaneProps) => {
options
);

const classes = mergeClasses(['SplitPane', split, className]);
const dragLayerClasses = mergeClasses([
'DragLayer',
const classes = useMemo(() => mergeClasses(['SplitPane', split, className]), [
split,
resizeState ? 'resizing' : '',
className,
]);
const dragLayerClasses = useMemo(
() =>
mergeClasses([
'DragLayer',
split,
resizeState ? 'resizing' : '',
className,
]),
[split, resizeState, className]
);

const onCollapse = () => {
console.log('clicked collapse!');
};

const entries: React.ReactNode[] = [];

Expand All @@ -94,6 +105,7 @@ export const SplitPane = React.memo((props: SplitPaneProps) => {
resizerHoverCss={props.resizerHoverCss}
collapseButtonDetails={props.collapseButtonDetails}
onDragStarted={handleDragStart}
onCollapseToggle={onCollapse}
/>
);
}
Expand Down
3 changes: 2 additions & 1 deletion stories/Thing.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ export const VerticalSplitWithButton = () => (
grabberSize="1rem"
>
<div>This is a div</div>
<div>This is a div</div>
<div>This is a second div</div>
<div>This is a third div</div>
</SplitPane>
);

Expand Down
8 changes: 4 additions & 4 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"baseUrl": "./",
"paths": {
"@": ["./"],
"*": ["src/*", "node_modules/*"]
},
// "paths": {
// "@": ["./"],
// "*": ["src/*", "node_modules/*"]
// },
"jsx": "react",
"esModuleInterop": true
}
Expand Down

0 comments on commit c6e5b0c

Please sign in to comment.