react-resizable
Version:
A component that is resizable with handles.
274 lines (207 loc) • 8.96 kB
Markdown
# React-Resizable
[](https://www.npmjs.com/package/react-resizable)
[](https://www.npmjs.com/package/react-resizable)
[](https://github.com/react-grid-layout/react-resizable/actions/workflows/test.yml)
[**View the Demo**](https://react-grid-layout.github.io/react-resizable/examples/)
A simple widget that can be resized via one or more handles.
You can either use the `<Resizable>` element directly, or use the much simpler `<ResizableBox>` element.
See the example and associated code in [ExampleLayout](https://github.com/react-grid-layout/react-resizable/blob/master/examples/ExampleLayout.js) and
[ResizableBox](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.tsx) for more details.
## Table of Contents
- [Installation](#installation)
- [TypeScript](#typescript)
- [Compatibility](#compatibility)
- [Usage](#usage)
- [Resizable](#resizable)
- [ResizableBox](#resizablebox)
- [Props](#props)
- [Extracting Styles](#extracting-styles)
- [Custom Resize Handles](#resize-handle)
## Installation
```bash
$ npm install --save react-resizable
```
## Extracting Styles
You **must** include the associated styles in your application, otherwise the resize handles will not be visible and will not work properly.
```js
// In your JS/TS entry point:
import 'react-resizable/css/styles.css';
```
Or import it in your CSS:
```css
@import 'react-resizable/css/styles.css';
```
If you're using a bundler that doesn't support CSS imports, you can find the styles at `node_modules/react-resizable/css/styles.css` and include them manually.
## TypeScript
As of `4.0.0`, the library is authored in TypeScript and ships bundled type
declarations in `build/*.d.ts`. You **do not** need to install
`@types/react-resizable`; if you previously installed it, remove it so the
bundled types take precedence:
```bash
npm uninstall @types/react-resizable
# or
yarn remove @types/react-resizable
```
Public types are re-exported from the package root:
```ts
import {
Resizable,
ResizableBox,
// types
type ResizeCallbackData,
type ResizeHandleAxis,
type Axis,
type Props as ResizableProps,
} from 'react-resizable';
```
### Flow
Flow is no longer supported as of `4.0.0`. Earlier versions shipped
`*.js.flow` sidecar files generated from the Flow-annotated source; those
have been removed.
If you still need Flow types, you can vendor the last Flow-annotated source
locally from the [`3.2.0` tag](https://github.com/react-grid-layout/react-resizable/tree/db2e37eda85fb21b1864e36b01c4922452f28418/lib).
They will not be updated to reflect changes landing after `4.0.0`. The
official recommendation is to migrate to TypeScript.
## Compatibility
| Version | React Version | Types |
|---------|---------------|----------------|
| [4.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#400-may-12-2026) | `>= 16.3` | TypeScript (bundled) |
| [3.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#300-may-10-2021) | `>= 16.3` | Flow (`*.js.flow`) |
| 2.x | Skipped | — |
| [1.x](https://github.com/react-grid-layout/react-resizable/blob/master/CHANGELOG.md#1111-mar-5-2021) | `14 - 17` | Flow |
## Usage
This package has two major exports:
* [`<Resizable>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/Resizable.tsx): A raw component that does not have state. Use as a building block for larger components, by listening to its callbacks and setting its props.
* [`<ResizableBox>`](https://github.com/react-grid-layout/react-resizable/blob/master/lib/ResizableBox.tsx): A simple `<div {...props} />` element that manages basic state. Convenient for simple use-cases.
### `<Resizable>`
```js
import { Resizable } from 'react-resizable';
import 'react-resizable/css/styles.css';
class Example extends React.Component {
state = {
width: 200,
height: 200,
};
onResize = (event, {node, size, handle}) => {
this.setState({width: size.width, height: size.height});
};
render() {
return (
<Resizable
height={this.state.height}
width={this.state.width}
onResize={this.onResize}
>
<div
className="box"
style={{width: this.state.width + 'px', height: this.state.height + 'px'}}
>
<span>Contents</span>
</div>
</Resizable>
);
}
}
```
### `<ResizableBox>`
```js
import { ResizableBox } from 'react-resizable';
import 'react-resizable/css/styles.css';
class Example extends React.Component {
render() {
return (
<ResizableBox
width={200}
height={200}
draggableOpts={{grid: [25, 25]}}
minConstraints={[100, 100]}
maxConstraints={[300, 300]}
>
<span>Contents</span>
</ResizableBox>
);
}
}
```
## Props
These props apply to both `<Resizable>` and `<ResizableBox>`. Unknown props that are not in the list below will be passed to the child component.
```ts
type ResizeCallbackData = {
node: HTMLElement;
size: {width: number; height: number};
handle: ResizeHandleAxis;
};
type ResizeHandleAxis = 's' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne';
type ResizableProps = {
children: React.ReactElement<any>;
width: number;
height: number;
// Either a ReactElement to be used as handle, or a function
// returning an element that is fed the handle's location as its first argument.
handle?:
| React.ReactElement<any>
| ((resizeHandle: ResizeHandleAxis, ref: React.RefObject<HTMLElement>) => React.ReactElement<any>);
// If you change this, be sure to update your css. Default: [20, 20].
handleSize?: [number, number];
lockAspectRatio?: boolean; // default: false
axis?: 'both' | 'x' | 'y' | 'none'; // default: 'both'
minConstraints?: [number, number]; // default: [20, 20]
maxConstraints?: [number, number]; // default: [Infinity, Infinity]
onResizeStop?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
onResizeStart?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
onResize?: (e: React.SyntheticEvent, data: ResizeCallbackData) => any;
// Forwarded to react-draggable's <DraggableCore>.
draggableOpts?: Partial<React.ComponentProps<typeof import('react-draggable').DraggableCore>>;
resizeHandles?: ResizeHandleAxis[]; // default: ['se']
// If `transform: scale(n)` is set on the parent, this should be set to `n`.
transformScale?: number; // default: 1
};
```
The following props can also be used on `<ResizableBox>`:
```ts
{
style?: React.CSSProperties; // styles the returned <div />
}
```
If a `width` or `height` is passed to `<ResizableBox>`'s `style` prop, it will be ignored as it is required for internal function.
You can pass options directly to the underlying `DraggableCore` instance by using the prop `draggableOpts`. See the [demo](https://react-grid-layout.github.io/react-resizable/examples/) for more on this.
## Resize Handle
If you override the resize handle, we expect that any `ref` passed to your new handle will represent the underlying DOM element.
This is required, as `react-resizable` must be able to access the underlying DOM node to attach handlers and measure position deltas.
There are a few ways to do this:
### Native DOM Element
This requires no special treatment.
```js
<Resizable handle={<div className="foo" />} />
```
### Custom React Component
You must [forward the ref](https://reactjs.org/docs/forwarding-refs.html) and props to the underlying DOM element.
#### Class Components
```js
class MyHandleComponent extends React.Component {
render() {
const {handleAxis, innerRef, ...props} = this.props;
return <div ref={innerRef} className={`foo handle-${handleAxis}`} {...props} />
}
}
const MyHandle = React.forwardRef((props, ref) => <MyHandleComponent innerRef={ref} {...props} />);
<Resizable handle={<MyHandle />} />
```
#### Functional Components
```js
const MyHandle = React.forwardRef((props, ref) => {
const {handleAxis, ...restProps} = props;
return <div ref={ref} className={`foo handle-${handleAxis}`} {...restProps} />;
});
<Resizable handle={<MyHandle />} />
```
### Custom Function
You can define a function as a handle, which will simply receive an axis (see above `ResizeHandleAxis` type) and ref. This may be more clear to read, depending on your coding style.
```js
const MyHandle = (props) => {
return <div ref={props.innerRef} className="foo" {...props} />;
};
<Resizable handle={(handleAxis, ref) => <MyHandle innerRef={ref} className={`foo handle-${handleAxis}`} />} />
```
## License
MIT