import { Component } from '@angular/core';
import { WrResizable } from 'ngwr/resizable';
@Component({ imports: [WrResizable] })
export class MyComponent {}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.
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;
}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>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>Keyboard
The handle is a focusable separator that announces the size and its limits in pixels.
| Key | Does |
|---|---|
| Arrows | Move the edge by step (10px), the way the arrow points. |
| Shift + arrows | Ten steps. |
| Home / End | The smallest and the largest size. |
| Enter | Back 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
| Name | Description | Type | Default |
|---|---|---|---|
edge | The edge that drags. start and end resize the width and mirror under RTL; top and bottom resize the height. | WrResizableEdge | 'end' |
size | The 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 | null | null |
minSize | Smallest size: pixels, or a percentage of the parent's matching dimension ('20%'). null for none. | WrResizableLimit | null | 0 |
maxSize | Largest size: pixels, or a percentage of the parent's matching dimension. null for none. | WrResizableLimit | null | '100%' |
defaultSize | The 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 | null | null |
step | Pixels an arrow key moves the edge. Shift moves it ten times as far. | number | 10 |
persistKey | Saves the size under this key through WrStorage (which adds the app's prefix) when a resize ends, and restores it on creation. | string | null | null |
collapsed | Shrinks the element to zero and hides the handle. size is left alone, so the element is back at its size when this turns off. | boolean | false |
disabled | Keeps the size and stops the handle. | boolean | false |
resizeLabel | Accessible name of the handle. A focusable role="separator" is an interactive widget, so it needs one. Falls back to resizable.handle. | string | null | null |
(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.
| Variable | Default | Declared on |
|---|---|---|
--wr-resizable-grip-active-color | var(--wr-color-primary) | .wr-resizable |
--wr-resizable-grip-color | var(--wr-border-base) | .wr-resizable |
--wr-resizable-grip-length | 2rem | .wr-resizable |
--wr-resizable-grip-radius | var(--wr-border-radius-pill) | .wr-resizable |
--wr-resizable-grip-thickness | var(--wr-space-xs) | .wr-resizable |
--wr-resizable-handle-hover-bg | var(--wr-color-primary-soft) | .wr-resizable |
--wr-resizable-handle-size | var(--wr-space-sm) | .wr-resizable |
--wr-resizable-line-active-color | var(--wr-color-primary) | .wr-resizable |
--wr-resizable-line-color | var(--wr-border-subtle) | .wr-resizable |
--wr-resizable-line-size | 1px | .wr-resizable |
Dependencies
| Built on | WrStorage |
|---|
See also
Component SplitterTwo panes with a divider the user drags or moves with the arrow keys.Component DrawerA side panel that slides in from any edge of the screen.Component LayoutAn app shell: header, sider, content and footer.Service WrStorageTyped key-value storage over localStorage or any engine, read as a signal or written through one, safe under SSR.