Vize

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.