Components/ResizeBox

ResizeBox

Transitions a container between explicit width and height targets with lifecycle events and optional overflow clipping.

VerifiedSince 1.0.0

ResizeBox

TxResizeBox does not measure slot content and does not use ResizeObserver. Use TxAutoSizer when content changes should be measured automatically.

Basic Usage

Explicit Size Targets

Switch between compact and expanded targets, observe resize-start / resize-end, disable motion to snap immediately, and toggle overflow clipping.

Loading demo...

API

Props

PropTypeDefaultDescription
asstringdivElement tag rendered as the root container.
widthnumber | stringundefinedExplicit width target. Finite numbers become px; trimmed non-empty strings are forwarded as CSS sizes. An unset value leaves the axis intrinsically sized.
heightnumber | stringundefinedExplicit height target. Finite numbers become px; trimmed non-empty strings are forwarded as CSS sizes. An unset value leaves the axis intrinsically sized.
durationnumber300Width and height transition duration in milliseconds.
easingstringcubic-bezier(0.22, 1, 0.36, 1)CSS timing function used by both size transitions.
disabledbooleanfalseRemoves transitions so new size targets apply immediately. Disabling during a resize settles the active lifecycle.
clipbooleantrueApplies overflow: hidden to the root while enabled.

Slots

SlotPropsDescription
default-Content rendered directly inside the resizable root element. The component does not wrap or measure it.

Events

EventPayloadDescription
resize-start()Emitted when a changed explicit width or height begins an enabled resize lifecycle. Rapid target changes while already animating remain in the same lifecycle.
resize-end()Emitted after the last root width/height transition settles, the safety timer settles it, or an active resize is disabled.

Expose

NameTypeDescription
rootElHTMLElement | nullCurrent root element. Vue unwraps the exposed internal ref on the public component instance.
animatingbooleanWhether an enabled explicit-size transition lifecycle is active. Vue unwraps the exposed internal ref on the public component instance.

Interaction Contract

  • The root is rendered through <component :is="as">; forwarded attrs are applied to that root, while caller class and style are merged with component classes and size styles.
  • Finite numeric targets are converted to px. Trimmed non-empty strings are preserved, so %, rem, calc(), and min() targets can be used directly.
  • undefined, runtime null, non-finite numbers, and empty or whitespace-only strings resolve to no inline size for that axis. TypeScript callers use undefined; the null behavior is a runtime safeguard.
  • The component does not validate CSS length grammar. Negative numbers and invalid non-empty strings are forwarded, so the browser may reject the declaration; if no transition runs, the duration-based safety timer still settles any lifecycle started by the resolved-value change.
  • Changing either resolved size while enabled starts one lifecycle and sets animating=true. The lifecycle ends only after all running root width / height transitions settle or the duration-based safety timer fires.
  • Transition events from child elements and transitions for properties other than width or height are ignored.
  • disabled=true adds transition: none; target changes snap without a new resize-start or resize-end. Disabling an active resize emits its final resize-end.
  • clip=true applies overflow: hidden. With clip=false, overflow follows normal CSS behavior.
  • The reduced-motion media query shortens the CSS transition duration to 0.01ms while retaining lifecycle settlement.
  • Slot-content changes alone do not start a resize. There is no automatic content measurement, ResizeObserver, or v-model contract.

Best Practices

  • Use TxResizeBox when compact and expanded width/height targets are already known by the parent.
  • Use TxAutoSizer when images, async rendering, text wrapping, or other content-driven changes must be measured automatically.
  • Set only the axis you own; leaving width or height unset preserves intrinsic sizing for that axis.
  • Prefer non-negative finite numbers or valid CSS length strings. Do not rely on the browser rejecting an invalid target as application validation.
  • Keep clip=true for panels whose inner content is larger than the compact target. Disable clipping only when overflow is intentional and the surrounding layout can contain it.
  • Treat resize-start and resize-end as lifecycle notifications, not as a source of size values; the props remain the source of truth.
  • Use CSS length strings for responsive targets such as min(420px, 100%) so explicit sizing does not force narrow-screen overflow.

Review Notes

  • Reviewed against packages/tuffex/packages/components/src/resize-box/src/types.ts, TxResizeBox.vue, and resize-box.test.ts.
  • The component animates explicit targets only; content observation belongs to TxAutoSizer.
  • Event payloads are empty, and no v-model or imperative resize method is exposed.

Source

  • Component source: packages/tuffex/packages/components/src/resize-box/src/TxResizeBox.vue.
  • Types: packages/tuffex/packages/components/src/resize-box/src/types.ts.
  • Verified coverage: packages/tuffex/packages/components/src/resize-box/__tests__/resize-box.test.ts verifies numeric/string sizes, intrinsic unset axes, attrs merging, clipping, lifecycle events, disabled snapping, safety settlement, and rapid target changes.
查看源码
packages/tuffex/packages/components/src/resize-box/index.ts