Run the CLI
Use the CLI to add carousel to your project.
npx @ngzard/ui@latest add carouselMajor infrastructure improvements this month! We focused on developer experience with a new provider system, CLI enhancements with our own private registry, and streamlined dark-mode setup.
New provider function for streamlined app configuration. Add event manager plugins and other Zard utilities with a single function call in your app.config.ts.
provideZard()The CLI now uses our own private registry instead of fetching from GitHub. This brings significant performance improvements, better version control, and more reliable component installations.
Adding dark-mode support to your project is now as simple as running a single CLI command. It automatically configures everything you need.
npx @ngzard/ui@latest add dark-modeMajor updates this month with new interactive components including Carousel, Button Group, Input Group, and Kbd components. Enhanced user experience with better form controls and keyboard navigation support.
Use the CLI to add carousel to your project.
npx @ngzard/ui@latest add carouselpnpm dlx @ngzard/ui@latest add carouselyarn dlx @ngzard/ui@latest add carouselbunx @ngzard/ui@latest add carouselA slideshow component for cycling through elements with support for mouse drag, touch swipe, and automatic playback.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardCardComponent } from '../../card';
import { ZardCarouselImports } from '../carousel.imports';
@Component({
imports: [ZardCarouselImports, ZardCardComponent],
template: `
<div class="mx-auto w-3/4 max-w-md">
<z-carousel>
<z-carousel-content>
@for (slide of slides; track slide) {
<z-carousel-item>
<z-card>
<div class="flex h-25 items-center justify-center text-4xl font-semibold md:h-50">
{{ slide }}
</div>
</z-card>
</z-carousel-item>
}
</z-carousel-content>
</z-carousel>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoCarouselDefaultComponent {
protected slides = ['1', '2', '3', '4', '5'];
}
Use the CLI to add kbd to your project.
npx @ngzard/ui@latest add kbdpnpm dlx @ngzard/ui@latest add kbdyarn dlx @ngzard/ui@latest add kbdbunx @ngzard/ui@latest add kbdDisplay keyboard keys and shortcuts in a visually consistent way.
import { Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardKbdComponent } from '../kbd.component';
@Component({
selector: 'z-demo-kbd-default',
imports: [ZardKbdComponent, ZardButtonComponent],
standalone: true,
template: `
<div class="flex flex-col items-center justify-center gap-4">
<div class="flex items-center gap-2">
<z-kbd>Esc</z-kbd>
<z-kbd>⌘</z-kbd>
<z-kbd>Ctrl</z-kbd>
</div>
<button type="submit" z-button zType="outline">
Submit
<z-kbd class="ml-2">Enter</z-kbd>
</button>
</div>
`,
})
export class ZardDemoKbdDefaultComponent {}
Breaking changes with icons migration from lucide-static to lucide-angular for better performance. New layout components including Sheet and Empty state component for better UX.
Use the CLI to add sheet to your project.
npx @ngzard/ui@latest add sheetpnpm dlx @ngzard/ui@latest add sheetyarn dlx @ngzard/ui@latest add sheetbunx @ngzard/ui@latest add sheetA versatile sheet component for side panels and overlays with customizable positioning and smooth transitions.
import { ChangeDetectionStrategy, Component, inject, type AfterViewInit } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ZardButtonComponent } from '@/shared/components/button';
import { ZardInputDirective } from '@/shared/components/input';
import { ZardSheetImports } from '@/shared/components/sheet/sheet.imports';
import { Z_SHEET_DATA, ZardSheetService } from '@/shared/components/sheet/sheet.service';
interface iSheetData {
name: string;
username: string;
}
@Component({
selector: 'zard-demo-sheet-basic',
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 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive 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 focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm"
/>
</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 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive 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 focus-visible:ring-[3px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm"
/>
</div>
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
exportAs: 'zardDemoSheetBasic',
})
export class ZardDemoSheetBasicInputComponent implements AfterViewInit {
private zData: iSheetData = inject(Z_SHEET_DATA);
form = new FormGroup({
name: new FormControl(''),
username: new FormControl(''),
});
ngAfterViewInit(): void {
if (this.zData) {
this.form.patchValue(this.zData);
}
}
}
@Component({
imports: [ZardButtonComponent, ZardSheetImports],
template: `
<button type="button" z-button zType="outline" (click)="openSheet()">Edit profile</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
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',
},
zOkText: 'Save changes',
zOnOk: instance => {
console.log('Form submitted:', instance.form.value);
},
});
}
}
Use the CLI to add empty to your project.
npx @ngzard/ui@latest add emptypnpm dlx @ngzard/ui@latest add emptyyarn dlx @ngzard/ui@latest add emptybunx @ngzard/ui@latest add emptyClean empty state component for "no data" scenarios with customizable messages and icons.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardEmptyComponent } from '../empty.component';
@Component({
selector: 'z-demo-empty-default',
imports: [ZardButtonComponent, ZardEmptyComponent, ZardIconComponent],
standalone: true,
template: `
<z-empty
zIcon="folder-code"
zTitle="No Projects Yet"
zDescription="You haven't created any projects yet. Get started by creating your first project."
[zActions]="[actionPrimary, actionSecondary]"
>
<ng-template #actionPrimary>
<button z-button>Create Project</button>
</ng-template>
<ng-template #actionSecondary>
<button z-button zType="outline">Import Project</button>
</ng-template>
<button z-button zType="link" zSize="sm" class="text-muted-foreground">
Learn More
<i z-icon zType="arrow-up-right"></i>
</button>
</z-empty>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoEmptyDefaultComponent {}
Focus on loading and feedback components this month. New Progress, Skeleton, and Loader components for better perceived performance and user feedback during async operations.
Use the CLI to add progress-bar to your project.
npx @ngzard/ui@latest add progress-barpnpm dlx @ngzard/ui@latest add progress-baryarn dlx @ngzard/ui@latest add progress-barbunx @ngzard/ui@latest add progress-barVisual progress indicator with customizable variants for tracking task completion and loading states.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-basic',
imports: [ZardProgressBarComponent],
template: `
<z-progress-bar [progress]="50" />
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoProgressBarBasicComponent {}
Use the CLI to add skeleton to your project.
npx @ngzard/ui@latest add skeletonpnpm dlx @ngzard/ui@latest add skeletonyarn dlx @ngzard/ui@latest add skeletonbunx @ngzard/ui@latest add skeletonLoading placeholder component for better perceived performance during content loading with pulse animation.
import { Component } from '@angular/core';
import { ZardSkeletonComponent } from '../skeleton.component';
@Component({
selector: 'z-demo-skeleton-default',
imports: [ZardSkeletonComponent],
standalone: true,
template: `
<div class="flex items-center space-x-4">
<z-skeleton class="h-12 w-12 rounded-full" />
<div class="space-y-2">
<z-skeleton class="h-4 w-[250px]" />
<z-skeleton class="h-4 w-[200px]" />
</div>
</div>
`,
})
export class ZardDemoSkeletonDefaultComponent {}
Use the CLI to add loader to your project.
npx @ngzard/ui@latest add loaderpnpm dlx @ngzard/ui@latest add loaderyarn dlx @ngzard/ui@latest add loaderbunx @ngzard/ui@latest add loaderAnimated loading spinner with multiple size variants for indicating async operations in progress.
import { Component } from '@angular/core';
import { ZardLoaderComponent } from '../loader.component';
@Component({
selector: 'z-demo-loader-default',
imports: [ZardLoaderComponent],
standalone: true,
template: `
<z-loader />
`,
})
export class ZardDemoLoaderDefaultComponent {}
Enhanced navigation and display components. New Avatar component with fallback support, Divider for content separation, and Breadcrumb for hierarchical navigation.
Use the CLI to add avatar to your project.
npx @ngzard/ui@latest add avatarpnpm dlx @ngzard/ui@latest add avataryarn dlx @ngzard/ui@latest add avatarbunx @ngzard/ui@latest add avatarUser profile image component with automatic fallback to initials and multiple size variants.



import { Component } from '@angular/core';
import { ZardAvatarGroupComponent } from '../avatar-group.component';
import { ZardAvatarComponent } from '../avatar.component';
@Component({
selector: 'z-demo-avatar-basic',
imports: [ZardAvatarComponent, ZardAvatarGroupComponent],
standalone: true,
template: `
<z-avatar zSrc="/images/avatar/imgs/avatar_image.jpg" zFallback="ZA" [zSize]="32" />
<z-avatar zSrc="error-image.png" zFallback="ZA" zSize="sm" />
<z-avatar-group>
<z-avatar zSrc="/images/avatar/imgs/avatar_image.jpg" zFallback="JD" zSize="sm" />
<z-avatar zSrc="https://github.com/srizzon.png" zFallback="SA" zSize="sm" />
<z-avatar zSrc="https://github.com/Luizgomess.png" zFallback="LU" zSize="sm" />
</z-avatar-group>
`,
})
export class ZardDemoAvatarBasicComponent {}
Use the CLI to add divider to your project.
npx @ngzard/ui@latest add dividerpnpm dlx @ngzard/ui@latest add divideryarn dlx @ngzard/ui@latest add dividerbunx @ngzard/ui@latest add dividerVisual divider component for separating content sections with horizontal and vertical orientations.
Before divider
After divider
import { Component } from '@angular/core';
import { ZardDividerComponent } from '../divider.component';
@Component({
selector: 'z-demo-divider-default',
imports: [ZardDividerComponent],
standalone: true,
template: `
<div class="flex flex-col">
<p>Before divider</p>
<z-divider />
<p>After divider</p>
</div>
`,
})
export class ZardDemoDividerDefaultComponent {}
Use the CLI to add breadcrumb to your project.
npx @ngzard/ui@latest add breadcrumbpnpm dlx @ngzard/ui@latest add breadcrumbyarn dlx @ngzard/ui@latest add breadcrumbbunx @ngzard/ui@latest add breadcrumbNavigation breadcrumb trail showing the current page location within a hierarchical structure.
import { Component } from '@angular/core';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardBreadcrumbImports } from '../breadcrumb.imports';
@Component({
selector: 'z-demo-breadcrumb-default',
imports: [ZardBreadcrumbImports, ZardIconComponent],
standalone: true,
template: `
<z-breadcrumb zWrap="wrap" zAlign="start">
<z-breadcrumb-item [routerLink]="['/']">
<z-icon zType="house" />
Home
</z-breadcrumb-item>
<z-breadcrumb-item [routerLink]="['/docs/components']">Components</z-breadcrumb-item>
<z-breadcrumb-item>Breadcrumb</z-breadcrumb-item>
</z-breadcrumb>
`,
})
export class ZardDemoBreadcrumbDefaultComponent {}
Major release of navigation and content organization components. New Tabs for multi-view interfaces, Accordion for collapsible content, and Tooltip for contextual information. Theming system improvements with new color palettes.
Use the CLI to add tabs to your project.
npx @ngzard/ui@latest add tabspnpm dlx @ngzard/ui@latest add tabsyarn dlx @ngzard/ui@latest add tabsbunx @ngzard/ui@latest add tabsTabbed interface component for organizing content into separate views with smooth transitions and keyboard navigation.
Is the default tab component
Content of the second tab
Content of the third tab
Content of the fourth tab
Content of the fifth tab
Content of the sixth tab
import { Component } from '@angular/core';
import { ZardTabComponent, ZardTabGroupComponent } from '../tabs.component';
@Component({
selector: 'z-demo-tabs-default',
imports: [ZardTabComponent, ZardTabGroupComponent],
standalone: true,
template: `
<div class="h-[300px] w-full">
<z-tab-group>
<z-tab label="First">
<p>Is the default tab component</p>
</z-tab>
<z-tab label="Second">
<p>Content of the second tab</p>
</z-tab>
<z-tab label="Third">
<p>Content of the third tab</p>
</z-tab>
<z-tab label="Fourth">
<p>Content of the fourth tab</p>
</z-tab>
<z-tab label="Fifth">
<p>Content of the fifth tab</p>
</z-tab>
<z-tab label="Sixth">
<p>Content of the sixth tab</p>
</z-tab>
</z-tab-group>
</div>
`,
})
export class ZardDemoTabsDefaultComponent {}
Use the CLI to add accordion to your project.
npx @ngzard/ui@latest add accordionpnpm dlx @ngzard/ui@latest add accordionyarn dlx @ngzard/ui@latest add accordionbunx @ngzard/ui@latest add accordionCollapsible content panels for organizing information in a compact space with expand/collapse animations.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardAccordionImports } from '@/shared/components/accordion/accordion.imports';
@Component({
selector: 'z-demo-accordion-basic',
imports: [ZardAccordionImports],
template: `
<z-accordion zDefaultValue="item-2">
<z-accordion-item zValue="item-1" zTitle="A Study in Scarlet">
The first case of Sherlock Holmes and Dr. Watson. They investigate a murder in London, which leads to a
backstory involving Mormons in the U.S. Introduces Holmes’s deductive method.
</z-accordion-item>
<z-accordion-item zValue="item-2" zTitle="The Sign of Four" zDescription="Sir Arthur Conan Doyle">
The first case of Sherlock Holmes and Dr. Watson. They investigate a murder in London, which leads to a
backstory involving Mormons in the U.S. Introduces Holmes’s deductive method.
</z-accordion-item>
<z-accordion-item zValue="item-3" zTitle="The Hound of the Baskervilles">
Holmes and Watson investigate the legend of a demonic hound haunting the Baskerville family. Set in the eerie
Dartmoor moorlands, the story involves betrayal and greed.
</z-accordion-item>
</z-accordion>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoAccordionBasicComponent {}
Use the CLI to add tooltip to your project.
npx @ngzard/ui@latest add tooltippnpm dlx @ngzard/ui@latest add tooltipyarn dlx @ngzard/ui@latest add tooltipbunx @ngzard/ui@latest add tooltipContextual information overlay displayed on hover with customizable positioning and delay settings.
import { Component } from '@angular/core';
import { ZardTooltipImports } from '@/shared/components/tooltip/tooltip.imports';
import { ZardButtonComponent } from '../../button/button.component';
@Component({
selector: 'z-demo-tooltip-hover',
imports: [ZardButtonComponent, ZardTooltipImports],
template: `
<button type="button" z-button zType="outline" zTooltip="Tooltip content">Hover</button>
`,
})
export class ZardDemoTooltipHoverComponent {}
Overlay components release! New Dialog, Popover, Alert Dialog, and Dropdown Menu components. CVA integration for type-safe styling variants across all components.
Use the CLI to add dialog to your project.
npx @ngzard/ui@latest add dialogpnpm dlx @ngzard/ui@latest add dialogyarn dlx @ngzard/ui@latest add dialogbunx @ngzard/ui@latest add dialogModal dialog component for displaying important content that requires user attention with backdrop overlay.
import { ChangeDetectionStrategy, Component, inject, type AfterViewInit } from '@angular/core';
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardInputDirective } from '../../input/input.directive';
import { ZardSelectItemComponent } from '../../select/select-item.component';
import { ZardSelectComponent } from '../../select/select.component';
import { ZardDialogModule } from '../dialog.component';
import { Z_MODAL_DATA, ZardDialogService } from '../dialog.service';
interface iDialogData {
name: string;
username: string;
}
@Component({
selector: 'zard-demo-dialog-basic',
imports: [FormsModule, ReactiveFormsModule, ZardInputDirective, ZardSelectComponent, ZardSelectItemComponent],
template: `
<form [formGroup]="form" class="grid gap-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" />
</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" />
</div>
<div class="grid gap-3">
<label
for="region"
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"
>
Region
</label>
<z-select formControlName="region">
<z-select-item zValue="africa">Africa</z-select-item>
<z-select-item zValue="america">America</z-select-item>
<z-select-item zValue="asia">Asia</z-select-item>
<z-select-item zValue="australia">Australia</z-select-item>
<z-select-item zValue="europe">Europe</z-select-item>
</z-select>
</div>
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
exportAs: 'zardDemoDialogBasic',
})
export class ZardDemoDialogBasicInputComponent implements AfterViewInit {
private zData: iDialogData = inject(Z_MODAL_DATA);
form = new FormGroup({
name: new FormControl('Pedro Duarte'),
username: new FormControl('@peduarte'),
region: new FormControl(''),
});
ngAfterViewInit(): void {
if (this.zData) {
this.form.patchValue(this.zData);
}
}
}
@Component({
imports: [ZardButtonComponent, ZardDialogModule],
template: `
<button type="button" z-button zType="outline" (click)="openDialog()">Edit profile</button>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoDialogBasicComponent {
private dialogService = inject(ZardDialogService);
openDialog() {
this.dialogService.create({
zTitle: 'Edit Profile',
zDescription: `Make changes to your profile here. Click save when you're done.`,
zContent: ZardDemoDialogBasicInputComponent,
zData: {
name: 'Samuel Rizzon',
username: '@samuelrizzondev',
region: 'america',
} as iDialogData,
zOkText: 'Save changes',
zOnOk: instance => {
console.log('Form submitted:', instance.form.value);
},
zWidth: '425px',
});
}
}
Use the CLI to add popover to your project.
npx @ngzard/ui@latest add popoverpnpm dlx @ngzard/ui@latest add popoveryarn dlx @ngzard/ui@latest add popoverbunx @ngzard/ui@latest add popoverFloating content container that appears on trigger with customizable positioning and close behavior.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardPopoverComponent, ZardPopoverDirective } from '../popover.component';
@Component({
selector: 'z-popover-default-demo',
imports: [ZardButtonComponent, ZardPopoverComponent, ZardPopoverDirective],
standalone: true,
template: `
<button type="button" z-button zPopover [zContent]="popoverContent" zType="outline">Open popover</button>
<ng-template #popoverContent>
<z-popover>
<div class="space-y-2">
<h4 class="leading-none font-medium">Dimensions</h4>
<p class="text-muted-foreground text-sm">Set the dimensions for the layer.</p>
</div>
</z-popover>
</ng-template>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoPopoverDefaultComponent {}
Use the CLI to add alert-dialog to your project.
npx @ngzard/ui@latest add alert-dialogpnpm dlx @ngzard/ui@latest add alert-dialogyarn dlx @ngzard/ui@latest add alert-dialogbunx @ngzard/ui@latest add alert-dialogConfirmation dialog for critical actions requiring explicit user confirmation with cancel and confirm options.
import { Component, inject } from '@angular/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardAlertDialogService } from '../alert-dialog.service';
@Component({
selector: 'zard-demo-alert-dialog-default',
imports: [ZardButtonComponent],
standalone: true,
template: `
<button z-button zType="outline" (click)="showDialog()">Show Dialog</button>
`,
})
export class ZardDemoAlertDialogDefaultComponent {
private alertDialogService = inject(ZardAlertDialogService);
showDialog() {
this.alertDialogService.confirm({
zTitle: 'Are you absolutely sure?',
zDescription:
'This action cannot be undone. This will permanently delete your account and remove your data from our servers.',
zOkText: 'Continue',
zCancelText: 'Cancel',
});
}
}
Use the CLI to add dropdown to your project.
npx @ngzard/ui@latest add dropdownpnpm dlx @ngzard/ui@latest add dropdownyarn dlx @ngzard/ui@latest add dropdownbunx @ngzard/ui@latest add dropdownContext menu with hierarchical actions, keyboard navigation, and support for nested submenus.
import { Component } from '@angular/core';
import { ZardButtonComponent } from '@/shared/components/button';
import { ZardDividerComponent } from '@/shared/components/divider';
import { ZardDropdownImports } from '@/shared/components/dropdown/dropdown.imports';
import { ZardMenuImports } from '@/shared/components/menu';
@Component({
selector: 'z-dropdown-demo',
imports: [ZardDropdownImports, ZardButtonComponent, ZardDividerComponent, ZardMenuImports],
template: `
<button type="button" z-button zType="outline" z-dropdown [zDropdownMenu]="menu">Open</button>
<z-dropdown-menu-content #menu="zDropdownMenuContent" class="w-56">
<z-menu-label>My Account</z-menu-label>
<z-dropdown-menu-item (click)="onProfile()">
Profile
<z-menu-shortcut>⇧⌘P</z-menu-shortcut>
</z-dropdown-menu-item>
<z-dropdown-menu-item (click)="onBilling()">
Billing
<z-menu-shortcut>⌘B</z-menu-shortcut>
</z-dropdown-menu-item>
<z-dropdown-menu-item (click)="onSettings()">
Settings
<z-menu-shortcut>⌘S</z-menu-shortcut>
</z-dropdown-menu-item>
<z-dropdown-menu-item (click)="onKeyboardShortcuts()">
Keyboard shortcuts
<z-menu-shortcut>⌘K</z-menu-shortcut>
</z-dropdown-menu-item>
<z-divider zSpacing="sm" class="-mx-1" />
<z-dropdown-menu-item (click)="onTeam()">Team</z-dropdown-menu-item>
<z-dropdown-menu-item (click)="onNewTeam()">
New Team
<z-menu-shortcut>⌘+T</z-menu-shortcut>
</z-dropdown-menu-item>
<z-divider zSpacing="sm" class="-mx-1" />
<z-dropdown-menu-item (click)="onGitHub()">GitHub</z-dropdown-menu-item>
<z-dropdown-menu-item (click)="onSupport()">Support</z-dropdown-menu-item>
<z-dropdown-menu-item disabled="true">API</z-dropdown-menu-item>
<z-divider zSpacing="sm" class="-mx-1" />
<z-dropdown-menu-item (click)="onLogout()">
Log out
<z-menu-shortcut>⇧⌘Q</z-menu-shortcut>
</z-dropdown-menu-item>
</z-dropdown-menu-content>
`,
})
export class ZardDropdownDemoComponent {
onProfile() {
console.log('Profile clicked');
}
onBilling() {
console.log('Billing clicked');
}
onSettings() {
console.log('Settings clicked');
}
onKeyboardShortcuts() {
console.log('Keyboard shortcuts clicked');
}
onTeam() {
console.log('Team clicked');
}
onNewTeam() {
console.log('New Team clicked');
}
onGitHub() {
console.log('GitHub clicked');
}
onSupport() {
console.log('Support clicked');
}
onLogout() {
console.log('Log out clicked');
}
}
Comprehensive form controls release! New Select, Checkbox, Radio, Switch, and Slider components with full Angular Reactive Forms integration and ControlValueAccessor support.
Use the CLI to add select to your project.
npx @ngzard/ui@latest add selectpnpm dlx @ngzard/ui@latest add selectyarn dlx @ngzard/ui@latest add selectbunx @ngzard/ui@latest add selectAdvanced dropdown select with search functionality, multi-select support, and custom item rendering.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardBadgeComponent } from '@/shared/components/badge';
import { ZardSelectImports } from '@/shared/components/select/select.imports';
@Component({
selector: 'z-demo-select-basic',
imports: [ZardBadgeComponent, ZardSelectImports],
template: `
<div class="flex flex-col gap-4">
<span>
Selected value:
@if (selectedValue) {
<z-badge>{{ selectedValue }}</z-badge>
}
</span>
<z-select class="w-75" zPlaceholder="Select a fruit" [(zValue)]="selectedValue">
<z-select-item zValue="apple">Apple</z-select-item>
<z-select-item zValue="banana">Banana</z-select-item>
<z-select-item zValue="blueberry">Blueberry</z-select-item>
<z-select-item zValue="grapes">Grapes</z-select-item>
<z-select-item zValue="pineapple" zDisabled>Pineapple</z-select-item>
</z-select>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSelectBasicComponent {
selectedValue = '';
}
Use the CLI to add checkbox to your project.
npx @ngzard/ui@latest add checkboxpnpm dlx @ngzard/ui@latest add checkboxyarn dlx @ngzard/ui@latest add checkboxbunx @ngzard/ui@latest add checkboxCheckbox input component with indeterminate state support and full accessibility features.
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ZardCheckboxComponent } from '../checkbox.component';
@Component({
selector: 'z-demo-checkbox-default',
imports: [ZardCheckboxComponent, FormsModule],
standalone: true,
template: `
<span z-checkbox></span>
<span z-checkbox [(ngModel)]="checked">Default Checked</span>
`,
})
export class ZardDemoCheckboxDefaultComponent {
checked = true;
}
Use the CLI to add radio to your project.
npx @ngzard/ui@latest add radiopnpm dlx @ngzard/ui@latest add radioyarn dlx @ngzard/ui@latest add radiobunx @ngzard/ui@latest add radioRadio button group for mutually exclusive options with customizable layouts and orientation.
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ZardRadioComponent } from '../radio.component';
@Component({
selector: 'z-demo-radio-default',
imports: [ZardRadioComponent, FormsModule],
standalone: true,
template: `
<div class="flex flex-col gap-3">
<span z-radio name="option" [(ngModel)]="selected" value="default">Default</span>
<span z-radio name="option" [(ngModel)]="selected" value="comfortable">Comfortable</span>
<span z-radio name="option" [(ngModel)]="selected" value="compact">Compact</span>
</div>
`,
})
export class ZardDemoRadioDefaultComponent {
selected = 'default';
}
Use the CLI to add switch to your project.
npx @ngzard/ui@latest add switchpnpm dlx @ngzard/ui@latest add switchyarn dlx @ngzard/ui@latest add switchbunx @ngzard/ui@latest add switchToggle switch component for boolean settings with smooth animation transitions.
import { Component } from '@angular/core';
import { ZardSwitchComponent } from '../switch.component';
@Component({
selector: 'zard-demo-switch',
imports: [ZardSwitchComponent],
standalone: true,
template: `
<z-switch />
`,
})
export class ZardDemoSwitchDefaultComponent {}
Use the CLI to add slider to your project.
npx @ngzard/ui@latest add sliderpnpm dlx @ngzard/ui@latest add slideryarn dlx @ngzard/ui@latest add sliderbunx @ngzard/ui@latest add sliderRange slider for numeric value selection with min/max bounds, step support, and value display.
import { Component } from '@angular/core';
import { ZardSliderComponent } from '../slider.component';
@Component({
selector: 'z-demo-slider-default',
imports: [ZardSliderComponent],
standalone: true,
template: `
<div class="preview flex min-h-[350px] w-full items-center justify-center p-10">
<z-slider class="w-[60%]" zDefault="50" />
</div>
`,
})
export class ZardDemoSliderDefaultComponent {}
Form foundations and CLI launch! New Input and Form components with validation support. Official CLI tool released for easy project initialization and component installation.
Use the CLI to add input to your project.
npx @ngzard/ui@latest add inputpnpm dlx @ngzard/ui@latest add inputyarn dlx @ngzard/ui@latest add inputbunx @ngzard/ui@latest add inputText input field component with multiple variants, sizes, and built-in validation state indicators.
import { ChangeDetectionStrategy, Component, inject, type AfterViewInit } from '@angular/core';
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
import { ZardInputDirective } from '../input.directive';
@Component({
selector: 'z-demo-input-default',
imports: [ZardInputDirective, ReactiveFormsModule],
template: `
<form [formGroup]="form" class="flex flex-col gap-3">
<input z-input placeholder="Name" formControlName="name" />
<input z-input placeholder="Disabled" formControlName="novalue" />
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoInputDefaultComponent implements AfterViewInit {
private fb = inject(FormBuilder);
readonly form = this.fb.group({
name: [''],
novalue: [''],
});
ngAfterViewInit(): void {
this.form.get('novalue')?.disable();
this.form.patchValue({ name: 'John Doe' });
}
}
Use the CLI to add form to your project.
npx @ngzard/ui@latest add formpnpm dlx @ngzard/ui@latest add formyarn dlx @ngzard/ui@latest add formbunx @ngzard/ui@latest add formComplete form component with field management, validation, error handling, and submission control.
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ZardIdDirective } from '@/shared/core';
import { ZardButtonComponent } from '../../button/button.component';
import { ZardInputDirective } from '../../input/input.directive';
import { ZardFormImports } from '../form.imports';
@Component({
selector: 'zard-demo-form-default',
imports: [FormsModule, ZardButtonComponent, ZardInputDirective, ZardFormImports, ZardIdDirective],
template: `
<form class="max-w-sm space-y-6">
<z-form-field zardId="fullName" #f="zardId">
<label z-form-label zRequired [for]="f.id()">Full Name</label>
<z-form-control>
<input
z-input
type="text"
[id]="f.id()"
placeholder="Enter your full name"
[(ngModel)]="fullName"
name="fullName"
/>
</z-form-control>
<z-form-message>This is your display name.</z-form-message>
</z-form-field>
<z-form-field zardId="email" #e="zardId">
<label z-form-label zRequired [for]="e.id()">Email</label>
<z-form-control>
<input z-input type="email" [id]="e.id()" placeholder="Enter your email" [(ngModel)]="email" name="email" />
</z-form-control>
<z-form-message>We'll never share your email with anyone else.</z-form-message>
</z-form-field>
<z-form-field zardId="bio" #b="zardId">
<label z-form-label [for]="b.id()">Bio</label>
<z-form-control>
<textarea
z-input
[id]="b.id()"
placeholder="Tell us about yourself"
rows="3"
[(ngModel)]="bio"
name="bio"
></textarea>
</z-form-control>
<z-form-message>Optional: Brief description about yourself.</z-form-message>
</z-form-field>
<button z-button zType="default" type="submit">Submit</button>
</form>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class ZardDemoFormDefaultComponent {
fullName = '';
email = '';
bio = '';
}
🎉 Initial release of ZardUI! An Angular component library built with TailwindCSS v4, featuring standalone components, signal-based reactivity, and modern Angular architecture. Core components including Button, Card, Badge, Alert, and Table.
Use the CLI to add button to your project.
npx @ngzard/ui@latest add buttonpnpm dlx @ngzard/ui@latest add buttonyarn dlx @ngzard/ui@latest add buttonbunx @ngzard/ui@latest add buttonVersatile button component with multiple variants (primary, secondary, outline, ghost), sizes, and loading states.
import { Component } from '@angular/core';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardButtonComponent } from '../button.component';
@Component({
selector: 'z-demo-button-default',
imports: [ZardButtonComponent, ZardIconComponent],
standalone: true,
template: `
<button z-button zType="outline">Button</button>
<button z-button zType="outline"><i z-icon zType="arrow-up"></i></button>
<button z-button zType="outline">
Button
<i z-icon zType="popcorn"></i>
</button>
`,
})
export class ZardDemoButtonDefaultComponent {}
Use the CLI to add card to your project.
npx @ngzard/ui@latest add cardpnpm dlx @ngzard/ui@latest add cardyarn dlx @ngzard/ui@latest add cardbunx @ngzard/ui@latest add cardContainer component for grouping related content with optional header, footer, and customizable padding.
import { Component } from '@angular/core';
import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCardComponent } from '@/shared/components/card/card.component';
import { ZardIdDirective } from '@/shared/core';
@Component({
selector: 'z-demo-card-default',
imports: [ZardCardComponent, ZardButtonComponent, ZardIdDirective],
template: `
<z-card
class="w-full md:w-94"
zTitle="Login to your account"
zDescription="Enter your email below to login to your account"
zAction="Sign Up"
(zActionClick)="onActionClick()"
>
<div class="space-y-4">
<div class="space-y-2" zardId="email" #e="zardId">
<label
[for]="e.id()"
class="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Email
</label>
<input
[id]="e.id()"
type="email"
placeholder="m@example.com"
class="border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
required
/>
</div>
<div class="space-y-2">
<div class="flex items-center" zardId="password" #p="zardId">
<label
[for]="p.id()"
class="text-sm leading-none font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Password
</label>
<a href="#" class="ml-auto text-sm underline-offset-4 hover:underline">Forgot your password?</a>
</div>
<input
[id]="p.id()"
type="password"
class="border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
required
/>
</div>
</div>
<div card-footer class="flex w-full flex-col gap-2">
<z-button zType="default">Login</z-button>
<z-button zType="outline">Login with Google</z-button>
</div>
</z-card>
`,
})
export class ZardDemoCardDefaultComponent {
protected onActionClick(): void {
alert('Redirect to Sign Up');
}
}
Use the CLI to add badge to your project.
npx @ngzard/ui@latest add badgepnpm dlx @ngzard/ui@latest add badgeyarn dlx @ngzard/ui@latest add badgebunx @ngzard/ui@latest add badgeSmall label component for displaying status, categories, counts, or tags with various color variants.
import { Component } from '@angular/core';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardBadgeComponent } from '../badge.component';
@Component({
selector: 'z-demo-badge-default',
imports: [ZardBadgeComponent, ZardIconComponent],
standalone: true,
template: `
<div class="flex flex-col items-center gap-2">
<div class="flex w-full flex-wrap gap-2">
<z-badge>Badge</z-badge>
<z-badge zType="secondary">Secondary</z-badge>
<z-badge zType="destructive">Destructive</z-badge>
<z-badge zType="outline">Outline</z-badge>
</div>
<div class="flex w-full flex-wrap gap-2">
<z-badge zType="secondary" class="bg-blue-500 text-white dark:bg-blue-600">
<z-icon zType="badge-check" />
Verified
</z-badge>
<z-badge zShape="pill" class="h-5 min-w-5 px-1 font-mono tabular-nums">8</z-badge>
<z-badge zShape="pill" zType="destructive" class="h-5 min-w-5 px-1 font-mono tabular-nums">99</z-badge>
<z-badge zShape="pill" zType="outline" class="h-5 min-w-5 px-1 font-mono tabular-nums">20+</z-badge>
</div>
</div>
`,
})
export class ZardDemoBadgeDefaultComponent {}
Use the CLI to add alert to your project.
npx @ngzard/ui@latest add alertpnpm dlx @ngzard/ui@latest add alertyarn dlx @ngzard/ui@latest add alertbunx @ngzard/ui@latest add alertNotification component for displaying important information to users with different severity levels.
Please verify your billing information and try again.
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ZardIconComponent } from '../../icon/icon.component';
import { ZardAlertComponent } from '../alert.component';
@Component({
selector: 'z-demo-alert-basic',
imports: [ZardAlertComponent, ZardIconComponent],
standalone: true,
template: `
<div class="grid w-full max-w-xl items-start gap-4">
<z-alert
zIcon="circle-check"
zTitle="Success! Your changes have been saved"
zDescription="This is an alert with icon, title and description."
/>
<z-alert [zIcon]="customIcon" zTitle="This Alert has a title and an icon. No description." />
<ng-template #customIcon>
<z-icon zType="popcorn" />
</ng-template>
<z-alert zType="destructive" zTitle="Unable to process your payment." [zDescription]="customDescription" />
<ng-template #customDescription>
<p>Please verify your billing information and try again.</p>
<ul class="list-disc pl-5">
<li>Check your card details</li>
<li>Ensure sufficient funds</li>
<li>Verify billing address</li>
</ul>
</ng-template>
</div>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoAlertBasicComponent {}
Use the CLI to add table to your project.
npx @ngzard/ui@latest add tablepnpm dlx @ngzard/ui@latest add tableyarn dlx @ngzard/ui@latest add tablebunx @ngzard/ui@latest add tableData table component with sorting, filtering, pagination, and customizable column rendering.
| Name | Age | Address |
|---|---|---|
| John Brown | 32 | New York No. 1 Lake Park |
| Jim Green | 42 | London No. 1 Lake Park |
| Joe Black | 32 | Sidney No. 1 Lake Park |
import { Component } from '@angular/core';
import { ZardTableComponent } from '../table.component';
interface Person {
key: string;
name: string;
age: number;
address: string;
}
@Component({
selector: 'z-demo-table-simple',
imports: [ZardTableComponent],
standalone: true,
template: `
<table z-table>
<caption>A list of your recent invoices.</caption>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Address</th>
</tr>
</thead>
<tbody>
@for (data of listOfData; track data.key) {
<tr>
<td class="font-medium">{{ data.name }}</td>
<td>{{ data.age }}</td>
<td>{{ data.address }}</td>
</tr>
}
</tbody>
</table>
`,
})
export class ZardDemoTableSimpleComponent {
listOfData: Person[] = [
{
key: '1',
name: 'John Brown',
age: 32,
address: 'New York No. 1 Lake Park',
},
{
key: '2',
name: 'Jim Green',
age: 42,
address: 'London No. 1 Lake Park',
},
{
key: '3',
name: 'Joe Black',
age: 32,
address: 'Sidney No. 1 Lake Park',
},
];
}