Skip to content

Commit c872c7b

Browse files
author
Stephen Gibson
committed
Can now pass a function to be called when rendering the resize handles
1 parent 3d29f02 commit c872c7b

File tree

5 files changed

+81
-3
lines changed

5 files changed

+81
-3
lines changed

src/components/Space.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const SpaceInner: React.FC<ISpaceProps & { wrapperInstance: Space }> = (props) =
3939
onTouchMove,
4040
onTouchEnd,
4141
children,
42+
handleRender
4243
} = props;
4344

4445
const events = {
@@ -88,8 +89,8 @@ const SpaceInner: React.FC<ISpaceProps & { wrapperInstance: Space }> = (props) =
8889

8990
return (
9091
<>
91-
{resizeHandles.mouseHandles.map((r) => (
92-
<div {...r} />
92+
{resizeHandles.mouseHandles.map((handleProps) => (
93+
handleRender?.(handleProps) || <div {...handleProps} />
9394
))}
9495
{React.createElement(
9596
props.as || "div",
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { Meta, Story, Canvas } from "@storybook/addon-docs/blocks";
2+
import { withKnobs } from "@storybook/addon-knobs";
3+
import { action } from '@storybook/addon-actions';
4+
import { ViewPort, Fill } from "../../";
5+
import { description } from "../Utils";
6+
import { CommonHeader, PropsTable, StandardProps, AnchoredProps, ResizableProps } from "../Utils";
7+
8+
<CommonHeader />
9+
10+
<Meta title="React Spaces/Custom resize handles" />
11+
12+
# Custom resize handles
13+
14+
React spaces allows you to pass custom components to be used as resize handles using the `handleRender` prop.
15+
This is an alternative to overriding the default css classes and will give you more control.
16+
17+
Pass a function to the `handleRender` prop that will be called for every resize handle on that component.
18+
19+
```tsx
20+
// This example is literally what happens under the hood
21+
<BottomResizable
22+
size="50%"
23+
handleRender={(props: IResizeHandleProps) => <div {...props}></div>}>
24+
</BottomResizable>
25+
```
26+
27+
You can determine the position of the handle by accessing the `props.key` property. This will allow you to render different handles depending
28+
on where it should be positioned.
29+
30+
It's also important that you pass following props to the **top level** element for your custom component, if you don't resizing will not work on mouse drag:
31+
32+
```tsx
33+
onMouseDown: (e: React.MouseEvent<HTMLElement, MouseEvent>) => void;
34+
onTouchStart: (e: React.TouchEvent<HTMLElement>) => void;
35+
```
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Meta, Story, Canvas } from "@storybook/addon-docs/blocks";
2+
import { withKnobs } from "@storybook/addon-knobs";
3+
import { action } from '@storybook/addon-actions';
4+
import { ViewPort, Fill, BottomResizable } from "../../";
5+
import { green, description } from "../Utils";
6+
import { CommonHeader, PropsTable, StandardProps, AnchoredProps, ResizableProps } from "../Utils";
7+
8+
<CommonHeader />
9+
10+
<Meta title="Basic examples/Custom resize handles" />
11+
12+
### Custom resize handles
13+
14+
Example of a custom resize handle that renders an up arrow for bottom or top resizable
15+
16+
<Canvas>
17+
<Story name="Simple example">
18+
<ViewPort>
19+
<BottomResizable
20+
style={green}
21+
size="50%"
22+
onResizeStart={action('onResizeStart')}
23+
onResizeEnd={action('onResizeEnd')}
24+
handleRender={(props) =>
25+
["top", "bottom"].includes(props.key) && <div {...props} style={{display: "flex", justifyContent: "center"}}>
26+
<div style={{position: "absolute", transform: "translateY(-50%)"}}>
27+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-arrows-expand" viewBox="0 0 16 16">
28+
<path fill-rule="evenodd" d="M1 8a.5.5 0 0 1 .5-.5h13a.5.5 0 0 1 0 1h-13A.5.5 0 0 1 1 8zM7.646.146a.5.5 0 0 1 .708 0l2 2a.5.5 0 0 1-.708.708L8.5 1.707V5.5a.5.5 0 0 1-1 0V1.707L6.354 2.854a.5.5 0 1 1-.708-.708l2-2zM8 10a.5.5 0 0 1 .5.5v3.793l1.146-1.147a.5.5 0 0 1 .708.708l-2 2a.5.5 0 0 1-.708 0l-2-2a.5.5 0 0 1 .708-.708L7.5 14.293V10.5A.5.5 0 0 1 8 10z"/>
29+
</svg>
30+
</div>
31+
</div>
32+
}
33+
>
34+
{description("I have an additional arrow on my handle")}
35+
</BottomResizable>
36+
</ViewPort>
37+
</Story>
38+
</Canvas>

src/core-react.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export function useSpace(props: ISpaceProps) {
127127
return { space: space, resizeHandles: resizeHandles, domRect: domRect, elementRef: elementRef };
128128
}
129129

130-
interface IResizeHandleProps {
130+
export interface IResizeHandleProps {
131131
id?: string;
132132
key: string | number;
133133
className?: string;

src/core-types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import { ReactNode } from "react";
2+
import { IResizeHandleProps } from "./core-react";
3+
14
export enum Type {
25
ViewPort = "viewport",
36
Fixed = "fixed",
@@ -74,6 +77,7 @@ export interface ISpaceProps extends ICommonProps {
7477
position?: IPositionalProps | undefined;
7578
handleSize?: number | undefined;
7679
handlePlacement?: ResizeHandlePlacement;
80+
handleRender?: (handleProps: IResizeHandleProps) => ReactNode
7781
touchHandleSize?: number | undefined;
7882
minimumSize?: number | undefined;
7983
maximumSize?: number | undefined;

0 commit comments

Comments
 (0)