Skip to content

useColumnResize ​

A resizable column or row: a handle that drags the size its owner keeps. SlidingColumn is built on it, and ColumnResizeHandle is the handle.

tsx
import { clampColumnSize, useColumnResize } from '@basmilius/react-ui';
tsx
import { useRef, useState } from 'react';
import { ColumnResizeHandle, useColumnResize } from '@basmilius/react-ui';

export default function ColumnResizeHandleDemo() {
    const column = useRef<HTMLElement>(null);
    const [width, setWidth] = useState(220);
    const { startResize } = useColumnResize(column, { size: width, min: 160, max: () => 400, from: 'left', onSize: setWidth });

    return (
        <div className="flex h-56 w-full overflow-hidden rounded-lg border border-border bg-bg">
            <aside ref={column} className="relative shrink-0 border-r border-border bg-surface p-3 text-xs text-text-muted" style={{ width }}>
                Drag my right edge: {width} pixels.
                <ColumnResizeHandle from="left" onPointerDown={startResize} />
            </aside>
            <div className="grow p-3 text-xs text-text-faint">The rest of the view.</div>
        </div>
    );
}
tsx
const column = useRef<HTMLElement>(null);
const { startResize } = useColumnResize(column, {
    size: width,
    min: 160,
    max: () => window.innerWidth - 400,
    from: 'left',
    onSize: setWidth
});

from is the edge the column hangs from, and with it the axis of the drag. A column pinned to the right edge of the window grows as the pointer moves left; one that starts at its own left edge grows as it moves right. top and bottom do the same for a row.

startResize goes on the handle's onPointerDown. The handle takes the pointer capture, so the drag keeps going when the pointer leaves the few pixels it is wide. While it lasts the column carries data-resizing, so a transition on its size can turn off. Every move calls onSize with a whole number held between min and max(); max is read at drag time, so a window resize between two drags counts.

clampColumnSize ​

clampColumnSize({ min, max }, size) holds a size between the two and rounds it. Run a stored width through it before the first render, since the window may be smaller than it was when the width was saved.

Options ​

OptionType
sizenumberRequired. The size now, in whole pixels.
minnumberRequired.
fromColumnEdgeRequired. 'left' | 'right' | 'top' | 'bottom'
onSize(size: number) => voidRequired.
max() => number

ColumnResizeOptions, ColumnResize and ColumnEdge are exported types.