resizable

A resizable layout component that allows users to resize panels by dragging dividers between them.

PreviousNext
One
Two
Three
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';

import { ZardResizableImports } from '@/shared/components/resizable/resizable.imports';

@Component({
  selector: 'z-demo-resizable-preview',
  imports: [...ZardResizableImports],
  template: `
    <z-resizable class="h-60 w-80 rounded-lg border sm:w-96">
      <z-resizable-panel>
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">One</span>
        </div>
      </z-resizable-panel>
      <z-resizable-handle zWithHandle />
      <z-resizable-panel>
        <z-resizable zLayout="vertical">
          <z-resizable-panel zDefaultSize="25">
            <div class="flex h-full items-center justify-center p-6">
              <span class="font-semibold">Two</span>
            </div>
          </z-resizable-panel>
          <z-resizable-handle zWithHandle />
          <z-resizable-panel zDefaultSize="75">
            <div class="flex h-full items-center justify-center p-6">
              <span class="font-semibold">Three</span>
            </div>
          </z-resizable-panel>
        </z-resizable>
      </z-resizable-panel>
    </z-resizable>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
})
export class ZardDemoResizablePreviewComponent {}

Installation

Copy
npx zard-cli@latest add resizable

Usage

import { ZardResizableImports } from '@/shared/components/resizable/resizable.imports';
Copy
<z-resizable>
  <z-resizable-panel>Panel One</z-resizable-panel>
  <z-resizable-handle />
  <z-resizable-panel>Panel Two</z-resizable-panel>
</z-resizable>
Copy

Examples

vertical

Use zLayout="vertical" for vertical resizing.
Header
Content
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardResizableImports } from '@/shared/components/resizable/resizable.imports';

@Component({
  selector: 'z-demo-resizable-vertical',
  imports: [...ZardResizableImports],
  template: `
    <z-resizable zLayout="vertical" class="h-60 w-80 rounded-lg border sm:w-96">
      <z-resizable-panel [zDefaultSize]="30">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Header</span>
        </div>
      </z-resizable-panel>
      <z-resizable-handle />
      <z-resizable-panel [zDefaultSize]="70">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">Content</span>
        </div>
      </z-resizable-panel>
    </z-resizable>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoResizableVerticalComponent {}

handle

Use the zWithHandle input on z-resizable-handle to show a visible handle.
Sidebar
Content
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardResizableImports } from '@/shared/components/resizable/resizable.imports';

@Component({
  selector: 'z-demo-resizable-handle',
  imports: [...ZardResizableImports],
  template: `
    <div class="space-y-4">
      <z-resizable class="h-60 w-80 rounded-lg border sm:w-96">
        <z-resizable-panel [zDefaultSize]="25">
          <div class="flex h-full items-center justify-center p-6">
            <span class="font-semibold">Sidebar</span>
          </div>
        </z-resizable-panel>
        <z-resizable-handle zWithHandle />
        <z-resizable-panel [zDefaultSize]="75">
          <div class="flex h-full items-center justify-center p-6">
            <span class="font-semibold">Content</span>
          </div>
        </z-resizable-panel>
      </z-resizable>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoResizableHandleComponent {}

rtl

To enable RTL support in zard/ui, see the RTL configuration guide.
واحد
اثنان
ثلاثة
// You will notice this example is rendered inside a wrapper that sets the dir and data-lang attributes, and
// reads its text from a translations helper. This is because this site is not RTL by default.
// In your application you won't need either: set dir="rtl" on <html> (or use the CDK Dir directive on a subtree)
// and write the text of your own language. See the RTL guide: https://zardui.com/docs/rtl

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardResizableImports } from '@/shared/components/resizable/resizable.imports';
import { injectRtlTranslation, type ZardRtlTranslations } from '@/shared/demo-utils/rtl-translation';

const translations: ZardRtlTranslations<{ one: string; two: string; three: string }> = {
  en: { dir: 'ltr', values: { one: 'One', two: 'Two', three: 'Three' } },
  ar: { dir: 'rtl', values: { one: 'واحد', two: 'اثنان', three: 'ثلاثة' } },
  he: { dir: 'rtl', values: { one: 'אחד', two: 'שניים', three: 'שלושה' } },
};

@Component({
  selector: 'z-demo-resizable-rtl',
  imports: [...ZardResizableImports],
  template: `
    @let t = i18n.t();
    <!-- In RTL the first panel sits on the right, and ArrowLeft on the handle grows it. -->
    <z-resizable class="h-60 w-80 rounded-lg border sm:w-96">
      <z-resizable-panel [zDefaultSize]="50">
        <div class="flex h-full items-center justify-center p-6">
          <span class="font-semibold">{{ t.one }}</span>
        </div>
      </z-resizable-panel>
      <z-resizable-handle zWithHandle />
      <z-resizable-panel [zDefaultSize]="50">
        <z-resizable zLayout="vertical">
          <z-resizable-panel [zDefaultSize]="25">
            <div class="flex h-full items-center justify-center p-6">
              <span class="font-semibold">{{ t.two }}</span>
            </div>
          </z-resizable-panel>
          <z-resizable-handle zWithHandle />
          <z-resizable-panel [zDefaultSize]="75">
            <div class="flex h-full items-center justify-center p-6">
              <span class="font-semibold">{{ t.three }}</span>
            </div>
          </z-resizable-panel>
        </z-resizable>
      </z-resizable-panel>
    </z-resizable>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoResizableRtlComponent {
  protected readonly i18n = injectRtlTranslation(translations);
}

API Reference

z-resizableComponent

The panel group that lays out its `z-resizable-panel` children along `zLayout` and manages their sizes. Add `#ref="zResizable"` on the element to call its public methods. `ZardResizeEvent` is `{ sizes: number[]; layout: 'horizontal' | 'vertical' }`, where `sizes` is the current size of every panel as a percentage (0-100) of the group, in panel order.

PropertyDescriptionTypeDefault
[zLayout] Layout direction of the panels 'horizontal' | 'vertical' 'horizontal'
[zLazy] If true, panels only update after resize ends instead of on every drag/keyboard step boolean false
[class] Additional CSS classes to apply ClassValue ''
(zResizeStart) Emitted once when a drag or keyboard resize starts, with the sizes at that moment EventEmitter<ZardResizeEvent> -
(zResize) Emitted with the updated sizes on every resize step (drag move, arrow key, or collapse toggle) EventEmitter<ZardResizeEvent> -
(zResizeEnd) Emitted once when a drag or keyboard resize ends, with the final sizes EventEmitter<ZardResizeEvent> -
collapsePanel(index) Public method that toggles the panel at `index` between 0 and its `zDefaultSize` (or an even share of the group). No-ops unless that panel has `zCollapsible` set — it is what a handle's Enter/Space keydown calls internally, and what a consumer calls to drive an external "collapse sidebar" control. (index: number) => void -

z-resizable-panelComponent

A single panel inside a `z-resizable` group. Sizes are percentages of the group along its resize axis (0-100), not pixels: pass a bare number/numeric string for a percentage, an explicit `"50%"` string, or a `"300px"` string, which is converted to a percentage of the group's current container size once, at layout time. The `zDefaultSize`s of the panels in one group should add up to 100 — a panel that omits it gets an even share of the remaining space.

PropertyDescriptionTypeDefault
[zDefaultSize] Initial size of the panel (see the selector description for the unit) number | string | undefined undefined
[zMin] Minimum size the panel can be resized to, in the same unit as `zDefaultSize` number | string 0
[zMax] Maximum size the panel can be resized to, in the same unit as `zDefaultSize` number | string 100
[zCollapsible] Whether the neighboring handle may collapse this panel to 0 (Enter/Space, or `collapsePanel`) boolean false
[zResizable] Whether the handles on either side of this panel are allowed to resize it boolean true
[class] Additional CSS classes to apply ClassValue ''

z-resizable-handleComponent

The draggable divider between two `z-resizable-panel`s. Renders `role="separator"` with `aria-orientation` (perpendicular to the group's `zLayout`) and is keyboard-operable: arrow keys resize by 1% (10% with Shift) in the axis matching the layout, Home/End jump the adjacent panels to their min/max, and Enter/Space toggles collapse when either neighboring panel is `zCollapsible`. In a right-to-left layout the first panel sits on the right, so ArrowLeft grows it and ArrowRight shrinks it; the direction is read from the CDK `Directionality`.

PropertyDescriptionTypeDefault
[zWithHandle] Shows a visual grip indicator inside the divider boolean false
[zDisabled] Disables dragging, keyboard resize, and collapse boolean false
[zHandleIndex] Position of the handle among its panel siblings — the handle at index `i` resizes the panel at `i` and the panel at `i + 1`. Must be set explicitly when a group has more than one handle; it is not computed automatically number 0
[class] Additional CSS classes to apply ClassValue ''
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .