Sheet

Extends the Dialog component to display content that complements the main content of the screen.

PreviousNext
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Component, inject } from '@angular/core';
 
import { ZardButtonComponent } from '../../button/button.component';
import { Z_MODAL_DATA, ZardSheetService } from '../sheet.service';
import { ZardInputDirective } from '../../input/input.directive';
import { ZardSheetModule } from '../sheet.module';
 
interface iSheetData {
  name: string;
  username: string;
}
 
@Component({
  selector: 'zard-demo-sheet-basic',
  exportAs: 'zardDemoSheetBasic',
  standalone: true,
  imports: [FormsModule, ReactiveFormsModule, ZardInputDirective],
  template: `
    <form [formGroup]="form" class="grid flex-1 auto-rows-min gap-6 px-4">
      <div class="grid gap-3">
        <label
          for="name"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Name</label
        >
        <input
          z-input
          formControlName="name"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
 
      <div class="grid gap-3">
        <label
          for="username"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Username</label
        >
        <input
          z-input
          formControlName="username"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
    </form>
  `,
})
export class ZardDemoSheetBasicInputComponent {
  private zData: iSheetData = inject(Z_MODAL_DATA);
 
  public form = new FormGroup({
    name: new FormControl('Matheus Ribeiro'),
    username: new FormControl('@ribeiromatheus.dev'),
  });
 
  constructor() {
    if (this.zData) this.form.patchValue(this.zData);
  }
}
 
@Component({
  standalone: true,
  imports: [ZardButtonComponent, ZardSheetModule],
  template: ` <button z-button zType="outline" (click)="openSheet()">Edit profile</button> `,
})
export class ZardDemoSheetBasicComponent {
  private sheetService = inject(ZardSheetService);
 
  openSheet() {
    this.sheetService.create({
      zTitle: 'Edit profile',
      zDescription: `Make changes to your profile here. Click save when you're done.`,
      zContent: ZardDemoSheetBasicInputComponent,
      zData: {
        name: 'Matheus Ribeiro',
        username: '@ribeiromatheus.dev',
      } as iSheetData,
      zOkText: 'Save changes',
      zOnOk: instance => {
        console.log('Form submitted:', instance.form.value);
      },
    });
  }
}
 

Installation

1

Run the CLI

Use the CLI to add the component to your project.

Loading...
1

Add the component files

Create the component directory structure and add the following files to your project.

Loading...

Examples

basic

import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Component, inject } from '@angular/core';
 
import { ZardButtonComponent } from '../../button/button.component';
import { Z_MODAL_DATA, ZardSheetService } from '../sheet.service';
import { ZardInputDirective } from '../../input/input.directive';
import { ZardSheetModule } from '../sheet.module';
 
interface iSheetData {
  name: string;
  username: string;
}
 
@Component({
  selector: 'zard-demo-sheet-basic',
  exportAs: 'zardDemoSheetBasic',
  standalone: true,
  imports: [FormsModule, ReactiveFormsModule, ZardInputDirective],
  template: `
    <form [formGroup]="form" class="grid flex-1 auto-rows-min gap-6 px-4">
      <div class="grid gap-3">
        <label
          for="name"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Name</label
        >
        <input
          z-input
          formControlName="name"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
 
      <div class="grid gap-3">
        <label
          for="username"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Username</label
        >
        <input
          z-input
          formControlName="username"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
    </form>
  `,
})
export class ZardDemoSheetBasicInputComponent {
  private zData: iSheetData = inject(Z_MODAL_DATA);
 
  public form = new FormGroup({
    name: new FormControl('Matheus Ribeiro'),
    username: new FormControl('@ribeiromatheus.dev'),
  });
 
  constructor() {
    if (this.zData) this.form.patchValue(this.zData);
  }
}
 
@Component({
  standalone: true,
  imports: [ZardButtonComponent, ZardSheetModule],
  template: ` <button z-button zType="outline" (click)="openSheet()">Edit profile</button> `,
})
export class ZardDemoSheetBasicComponent {
  private sheetService = inject(ZardSheetService);
 
  openSheet() {
    this.sheetService.create({
      zTitle: 'Edit profile',
      zDescription: `Make changes to your profile here. Click save when you're done.`,
      zContent: ZardDemoSheetBasicInputComponent,
      zData: {
        name: 'Matheus Ribeiro',
        username: '@ribeiromatheus.dev',
      } as iSheetData,
      zOkText: 'Save changes',
      zOnOk: instance => {
        console.log('Form submitted:', instance.form.value);
      },
    });
  }
}
 

side

import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Component, inject, signal } from '@angular/core';
 
import { ZardButtonComponent } from '../../button/button.component';
import { Z_MODAL_DATA, ZardSheetService } from '../sheet.service';
import { ZardRadioComponent } from '../../radio/radio.component';
import { ZardInputDirective } from '../../input/input.directive';
import { ZardSheetModule } from '../sheet.module';
 
interface iSheetData {
  name: string;
  username: string;
}
 
@Component({
  selector: 'zard-demo-sheet-side',
  exportAs: 'zardDemoSheetSide',
  standalone: true,
  imports: [FormsModule, ReactiveFormsModule, ZardInputDirective],
  template: `
    <form [formGroup]="form" class="grid flex-1 auto-rows-min gap-6 px-4">
      <div class="grid gap-3">
        <label
          for="name"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Name</label
        >
        <input
          z-input
          formControlName="name"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
 
      <div class="grid gap-3">
        <label
          for="username"
          class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50"
          >Username</label
        >
        <input
          z-input
          formControlName="username"
          class="file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
        />
      </div>
    </form>
  `,
})
export class ZardDemoSheetSideInputComponent {
  private zData: iSheetData = inject(Z_MODAL_DATA);
 
  public form = new FormGroup({
    name: new FormControl('Matheus Ribeiro'),
    username: new FormControl('@ribeiromatheus.dev'),
  });
 
  constructor() {
    if (this.zData) this.form.patchValue(this.zData);
  }
}
 
@Component({
  standalone: true,
  imports: [ZardRadioComponent, FormsModule, ZardButtonComponent, ZardSheetModule],
  template: `
    <div class="space-y-6 flex flex-col justify-center">
      <div class="flex space-x-4">
        <span z-radio name="top" [(ngModel)]="placement" value="top">top</span>
        <span z-radio name="bottom" [(ngModel)]="placement" value="bottom">bottom</span>
        <span z-radio name="left" [(ngModel)]="placement" value="left">left</span>
        <span z-radio name="right" [(ngModel)]="placement" value="right">right</span>
      </div>
      <button z-button zType="outline" (click)="openSheet()">Edit profile</button>
    </div>
  `,
})
export class ZardDemoSheetSideComponent {
  protected placement = signal<'right' | 'left' | 'top' | 'bottom' | null | undefined>('right');
 
  private sheetService = inject(ZardSheetService);
 
  openSheet() {
    this.sheetService.create({
      zTitle: 'Edit profile',
      zDescription: `Make changes to your profile here. Click save when you're done.`,
      zContent: ZardDemoSheetSideInputComponent,
      zData: {
        name: 'Matheus Ribeiro',
        username: '@ribeiromatheus.dev',
      } as iSheetData,
      zOkText: 'Save changes',
      zOnOk: instance => {
        console.log('Form submitted:', instance.form.value);
      },
      zSide: this.placement(),
    });
  }
}
 

dimensions

import { Component, inject } from '@angular/core';
 
import { ZardButtonComponent } from '../../button/button.component';
import { ZardSheetService } from '../sheet.service';
 
@Component({
  selector: 'z-demo-sheet-dimensions',
  standalone: true,
  imports: [ZardButtonComponent],
  template: `
    <div class="flex flex-wrap gap-4">
      <button z-button zType="outline" (click)="openWideSheet()">Wide Sheet (500px)</button>
      <button z-button zType="outline" (click)="openTallSheet()">Tall Sheet (80vh)</button>
      <button z-button zType="outline" (click)="openCustomSheet()">Custom Dimensions</button>
      <button z-button zType="outline" (click)="openTopSheet()">Top Sheet</button>
    </div>
  `,
})
export class ZardDemoSheetDimensionsComponent {
  private sheetService = inject(ZardSheetService);
 
  openWideSheet() {
    this.sheetService.create({
      zTitle: 'Wide Sheet',
      zDescription: 'This sheet has a custom width of 500px',
      zContent: `
        <div class="p-4">
          <p>This is a wide sheet with custom width.</p>
          <p>Perfect for forms that need more horizontal space.</p>
        </div>
      `,
      zSide: 'right',
      zWidth: '500px',
      zOkText: 'Got it',
    });
  }
 
  openTallSheet() {
    this.sheetService.create({
      zTitle: 'Tall Sheet',
      zDescription: 'This sheet has a custom height of 80vh',
      zContent: `
        <div class="p-4 space-y-4">
          <p>This is a tall sheet with custom height (80% of viewport height).</p>
          <p>Great for content that needs vertical space.</p>
          <div class="h-96 bg-gray-100 rounded-md flex items-center justify-center">
            <p class="text-gray-500">Large content area</p>
          </div>
        </div>
      `,
      zSide: 'left',
      zHeight: '80vh',
      zOkText: 'Close',
    });
  }
 
  openCustomSheet() {
    this.sheetService.create({
      zTitle: 'Custom Dimensions',
      zDescription: 'Both width and height customized',
      zContent: `
        <div class="p-4">
          <p>Width: 400px, Height: 60vh</p>
          <p>Complete control over dimensions.</p>
        </div>
      `,
      zSide: 'right',
      zWidth: '400px',
      zHeight: '60vh',
      zOkText: 'Close',
    });
  }
 
  openTopSheet() {
    this.sheetService.create({
      zTitle: 'Top Sheet',
      zDescription: 'Custom height for top position',
      zContent: `
        <div class="p-4">
          <p>This top sheet has a custom height.</p>
          <p>Height: 50vh</p>
        </div>
      `,
      zSide: 'top',
      zHeight: '50vh',
      zOkText: 'Done',
    });
  }
}
 

Sheet API Reference

Service

ZardSheetService

Service for creating and managing sheet overlays.

Methods:

  • create(config: ZardSheetOptions): ZardSheetRef - Creates and opens a sheet

Configuration Options

ZardSheetOptions

Input Type Default Description
zTitle string | TemplateRef<T> - Sheet title text or template
zDescription string - Sheet description/body text
zContent string | TemplateRef<T> | Type<T> - Custom content component, template, or HTML
zSide 'left' | 'right' | 'top' | 'bottom' 'left' Position of the sheet on screen
zWidth string - Custom width (e.g., '400px', '50%')
zHeight string - Custom height (e.g., '80vh', '500px')
zOkText string | null 'OK' OK button text, null to hide button
zCancelText string | null 'Cancel' Cancel button text, null to hide button
zOkIcon string - OK button icon class name
zCancelIcon string - Cancel button icon class name
zOkDestructive boolean false Whether OK button should have destructive styling
zOkDisabled boolean false Whether OK button should be disabled
zHideFooter boolean false Whether to hide the footer with action buttons
zMaskClosable boolean true Whether clicking outside closes the sheet
zClosable boolean true Whether sheet can be closed
zCustomClasses string - Additional CSS classes to apply
zOnOk EventEmitter<T> | OnClickCallback<T> - OK button click handler
zOnCancel EventEmitter<T> | OnClickCallback<T> - Cancel button click handler
zData object - Data to pass to custom content components
zViewContainerRef ViewContainerRef - View container for rendering custom content

Sheet Reference

ZardSheetRef

Reference to a sheet instance, returned by ZardSheetService.create().

Properties:

  • componentInstance: T | null - Reference to the content component

Methods:

  • close(result?: R): void - Closes the sheet

Component

ZardSheetComponent

Output Type Description
okTriggered EventEmitter<void> Emitted when OK button is clicked
cancelTriggered EventEmitter<void> Emitted when Cancel button is clicked