Resizable
Accessible, unstyled single-element resize wrapper with edge and corner handles.
|
|
| Package |
@vizejs/ui/resizable |
| Maturity |
stable |
| Own the source |
vize lib pull resizable |
| Requires |
context, controllable-state, id, move |
| Aliases |
resizable, resize handle, resizable box, element resizer |
| Covers |
WAI-ARIA window splitter (separator) pattern, CSS resize property, re-resizable |
Usage
import { Resizable, ResizableRoot, ResizableHandle } from "@vizejs/ui/resizable";
Or copy the source into your project with vize lib pull resizable (see Source Distribution).
API
Resizable
Source: src/families/layout/resizable/resizable-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned root id. null and undefined select a deterministic fallback. |
size |
ResizableSize |
undefined |
Controlled size in CSS pixels. undefined selects uncontrolled behavior. |
defaultSize |
ResizableSize |
{ width: 320, height: 240 } |
Initial size for uncontrolled use. |
minWidth |
number |
0 |
Minimum width in CSS pixels. |
maxWidth |
number |
Infinity |
Maximum width in CSS pixels. |
minHeight |
number |
0 |
Minimum height in CSS pixels. |
maxHeight |
number |
Infinity |
Maximum height in CSS pixels. |
lockAspectRatio |
boolean | number |
false |
Preserve the aspect ratio: true keeps the ratio from the start of each interaction, a number fixes width / height. |
step |
number |
10 |
Arrow-key step in CSS pixels. |
largeStep |
number |
50 |
Shift+Arrow step in CSS pixels. |
disabled |
boolean |
false |
Ignore pointer and keyboard resizing. |
dir |
ResizableDirection |
undefined |
Reading direction used to resolve start and end handles. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
Events
| Event |
Payload |
Description |
update:size |
[value: ResizableSize] |
Fired when the size requests a controlled value. |
resize-start |
[event: ResizableResizeEvent] |
Fired when a pointer or keyboard resize begins. |
resize |
[event: ResizableResizeEvent] |
Fired for every distinct size produced by an interaction. |
resize-end |
[event: ResizableResizeEvent] |
Fired when a pointer or keyboard resize ends. |
Slots
| Slot |
Slot props |
Description |
default |
ResizableSlotState |
Resizable contents and ResizableHandle parts. Receives the current size. |
Exposed
| Member |
Type |
Description |
disabled |
— |
|
element |
Readonly<ShallowRef<HTMLElement | null>> |
Template ref to the rendered root element. |
setSize |
— |
|
size |
— |
|
state |
— |
|
ResizableRoot
Source: src/families/layout/resizable/resizable-root.vue
Props
| Prop |
Type |
Default |
Description |
id |
string | null |
undefined |
Consumer-owned root id. null and undefined select a deterministic fallback. |
size |
ResizableSize |
undefined |
Controlled size in CSS pixels. undefined selects uncontrolled behavior. |
defaultSize |
ResizableSize |
{ width: 320, height: 240 } |
Initial size for uncontrolled use. |
minWidth |
number |
0 |
Minimum width in CSS pixels. |
maxWidth |
number |
Infinity |
Maximum width in CSS pixels. |
minHeight |
number |
0 |
Minimum height in CSS pixels. |
maxHeight |
number |
Infinity |
Maximum height in CSS pixels. |
lockAspectRatio |
boolean | number |
false |
Preserve the aspect ratio: true keeps the ratio from the start of each interaction, a number fixes width / height. |
step |
number |
10 |
Arrow-key step in CSS pixels. |
largeStep |
number |
50 |
Shift+Arrow step in CSS pixels. |
disabled |
boolean |
false |
Ignore pointer and keyboard resizing. |
dir |
ResizableDirection |
undefined |
Reading direction used to resolve start and end handles. undefined inherits DirectionProvider/LocaleProvider, then "ltr". |
Events
| Event |
Payload |
Description |
update:size |
[value: ResizableSize] |
Fired when the size requests a controlled value. |
resize-start |
[event: ResizableResizeEvent] |
Fired when a pointer or keyboard resize begins. |
resize |
[event: ResizableResizeEvent] |
Fired for every distinct size produced by an interaction. |
resize-end |
[event: ResizableResizeEvent] |
Fired when a pointer or keyboard resize ends. |
Slots
| Slot |
Slot props |
Description |
default |
ResizableSlotState |
Resizable contents and ResizableHandle parts. Receives the current size. |
Exposed
| Member |
Type |
Description |
size |
ResizableSize |
Current size. |
state |
ResizableState |
Interaction state. |
disabled |
boolean |
Whether resizing is disabled. |
element |
HTMLDivElement | null |
Rendered root element. |
setSize |
(size: ResizableSize) => boolean |
Request a size (clamped to the constraints) and report whether it changed. |
ResizableHandle
Source: src/families/layout/resizable/resizable-handle.vue
Props
| Prop |
Type |
Default |
Description |
edge |
ResizableEdge |
"se" |
Edge or corner this handle resizes from. start/end follow the root dir. |
ariaLabel |
string |
undefined |
Accessible name. undefined describes the resolved edge, e.g. "Resize from right edge". |
Slots
| Slot |
Slot props |
Description |
default |
ResizableSlotState |
Optional grip contents. Receives the current Resizable state. |
Exposed
| Member |
Type |
Description |
element |
HTMLDivElement | null |
Rendered separator element. |
physicalEdge |
ResizablePhysicalEdge |
Physical edge resolved from edge and the root dir. |
focus |
(options?: FocusOptions) => void |
Move focus to the handle. |
Behavior
Normative behavior for the @vizejs/ui/resizable single-element resize wrapper. It sizes
one element from edge and corner handles; use @vizejs/ui/splitter to divide space between
sibling panels. Every row is proven by the named mounted-DOM, SSR, or compile-time test.
| State x input |
Observable outcome |
Proven by |
| any render |
Root applies width/height and --vize-resizable-width/-height; handles are focusable role="separator" with aria-controls, per-axis orientation, aria-valuenow/min/max (infinite maxima omitted), and corner handles add aria-valuetext for both dimensions. |
renders a sized root and focusable separator handles with value semantics |
| Arrow keys on a handle |
The outward arrow grows and the inward arrow shrinks by step, Shift uses largeStep, off-axis arrows are not consumed, Home/End jump to the minimum/maximum; each key emits resize-start, resize, resize-end with source: "keyboard" and update:size. |
arrow keys resize by step, Shift by the large step, and Home/End jump to limits |
| pointer drag on a handle |
The handle captures the pointer, the size follows the accumulated movement from the pressed edge or corner, clamps to min/max, and data-state is resizing until release. |
pointer drag resizes from the pressed edge with capture and clamps to constraints |
lockAspectRatio |
true keeps the ratio from the start of the interaction; a number fixes width / height and ratio-derived dimensions still respect limits. |
aspect-ratio lock keeps width and height proportional |
start/end edges with dir |
Logical edges resolve to physical data-edge values through the root dir (end is the left edge in RTL). |
logical start and end handles follow the reading direction |
disabled |
Handles leave the tab order, report aria-disabled, and ignore keyboard and pointer input without events. |
disabled roots ignore keyboard and pointer resizing |
controlled size |
Requests emit update:size while the rendered size follows the prop. |
controlled size emits requests and follows the parent |
| root expose |
size, state, disabled, element, and a clamped setSize are available. |
root exposes size, state, and a clamped setSize |
| geometry helpers |
resolveResizableEdge, resizeByDelta, and constrainResizableSize are pure and ratio-aware. |
geometry helpers resolve edges, deltas, and ratio-aware clamping |
| handle outside a root |
Mounting throws VIZE_UI_CONTEXT_MISSING. |
handles require a Resizable root |
| SSR |
Isolated requests render byte-identical sized markup with separator values. |
renders byte-identical sized markup across isolated SSR requests |
| hydration |
Hydration reuses server handles with zero warnings and keyboard resizing works afterwards. |
hydrates handles without mismatches |
| public types |
Edges, sizes, sources, and lockAspectRatio are closed, typed contracts. |
src/families/layout/resizable/resizable.types.test-d.ts |
| DOM/SSR/Vapor |
Root and handle compile in each renderer lane. |
scripts/check-renderers.ts |
Components
| Component |
Contract |
resizable-root.vue |
Owns the controlled/uncontrolled size, constraints, aspect-ratio lock, and resize lifecycle. |
resizable-handle.vue |
Separator for one edge or corner; pointer drag through move and keyboard resizing. |
Resizable ships no stylesheet. Consumers position handles with data-edge and style
data-state.