ComponentAdded in v16.1

Resizable

Lets one element be resized by dragging one of its edges.

Installation

Import the class, and @use the entry point in your global styles. Nothing warns you when the @use is missing.

import { Component } from '@angular/core';
import { WrResizable } from 'ngwr/resizable';

@Component({ imports: [WrResizable] })
export class MyComponent {}

Basic

Put wrResizable on the element. It writes the element's own width in pixels and nothing else, so a panel lying over other content stays over it. [(size)] changes when the drag is released; (resizing) fires on every move.

<div class="map">
  <aside wrResizable [(size)]="width" (resizing)="live.set($event)">Layers</aside>
</div>
.map {
  position: relative;
}

aside {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: 16rem;
}

size: not set, resizing: not yet

Limits

minSize and maxSize take pixels or a percentage of the parent's matching dimension. The default range is 0 to 100%; null removes a limit.

<aside wrResizable [minSize]="160" maxSize="60%">Layers</aside>

Edges

edge is end by default. start and end resize the width and swap sides under RTL; top and bottom resize the height.

<footer wrResizable edge="top" [minSize]="48" maxSize="80%">Timeline</footer>
Timeline

Saved size

persistKey saves the size through WrStorage when a resize ends and restores it on the next visit. Enter or a double click on the handle goes back to defaultSize, or to the size the element started with.

<aside wrResizable persistKey="layers-panel" [defaultSize]="256">Layers</aside>

Collapsed and disabled

collapsed shrinks the element to zero, hides the handle and keeps size, so the element comes back as it was. disabled keeps the size and stops the handle. Keep padding and borders on an inner element: the host's own would stay visible at zero.

<aside wrResizable [collapsed]="!open()">
  <div class="body">Layers</div>
</aside>

Collapse

Keyboard

The handle is a focusable separator that announces the size and its limits in pixels.

KeyDoes
ArrowsMove the edge by step (10px), the way the arrow points.
Shift + arrowsTen steps.
Home / EndThe smallest and the largest size.
EnterBack to defaultSize.

Handle

The directive adds the handle inside the host, over the edge. It needs a positioning context: a host whose computed position is static gets position: relative. Scroll an inner element, not the host, or the handle scrolls away with the content. Name the handle with resizeLabel, or translate resizable.handle.

<aside wrResizable resizeLabel="Resize the layers panel">Layers</aside>
provideWrI18nStaticLoader({
  en: { resizable: { handle: 'Resize' } },
});

API

NameDescriptionTypeDefault
edgeThe edge that drags. start and end resize the width and mirror under RTL; top and bottom resize the height.WrResizableEdge'end'
sizeThe size in pixels. Two-way bindable. null means not set yet: the element keeps the size its CSS gives it until the first resize. sizeChange fires when a drag is released, on each key and on a reset, never during a drag: bind resizing for that.number | nullnull
minSizeSmallest size: pixels, or a percentage of the parent's matching dimension ('20%'). null for none.WrResizableLimit | null0
maxSizeLargest size: pixels, or a percentage of the parent's matching dimension. null for none.WrResizableLimit | null'100%'
defaultSizeThe size Enter and a double click on the handle go back to. null goes back to what the element started with: the size bound at creation, or its CSS size when there was none.number | nullnull
stepPixels an arrow key moves the edge. Shift moves it ten times as far.number10
persistKeySaves the size under this key through WrStorage (which adds the app's prefix) when a resize ends, and restores it on creation.string | nullnull
collapsedShrinks the element to zero and hides the handle. size is left alone, so the element is back at its size when this turns off.booleanfalse
disabledKeeps the size and stops the handle.booleanfalse
resizeLabelAccessible name of the handle. A focusable role="separator" is an interactive widget, so it needs one. Falls back to resizable.handle.string | nullnull
(resizing)The size in pixels on every move of a drag, before sizeChange settles it on release.number—

CSS variables

Set these on the element itself, with a rule more specific than its Declared on selector. In a global stylesheet, put a class of yours on an ancestor it really has: <body> for an overlay panel, which renders outside your markup. In a component stylesheet the selector alone works, but only for an element in that component's own template. A value on a wrapper or :root is shadowed, because ngwr/resizable declares each default on its own element.

VariableDefaultDeclared on
--wr-resizable-grip-active-colorvar(--wr-color-primary).wr-resizable
--wr-resizable-grip-colorvar(--wr-border-base).wr-resizable
--wr-resizable-grip-length2rem.wr-resizable
--wr-resizable-grip-radiusvar(--wr-border-radius-pill).wr-resizable
--wr-resizable-grip-thicknessvar(--wr-space-xs).wr-resizable
--wr-resizable-handle-hover-bgvar(--wr-color-primary-soft).wr-resizable
--wr-resizable-handle-sizevar(--wr-space-sm).wr-resizable
--wr-resizable-line-active-colorvar(--wr-color-primary).wr-resizable
--wr-resizable-line-colorvar(--wr-border-subtle).wr-resizable
--wr-resizable-line-size1px.wr-resizable

Dependencies

Built onWrStorage

See also