Run the CLI
Use the CLI to add the component to your project.
npx @ngzard/ui add progress-barDisplays an indicator showing the completion progress of a task, typically displayed as a progress bar.
import { Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-basic',
standalone: true,
imports: [ZardProgressBarComponent],
template: ` <z-progress-bar [progress]="50"></z-progress-bar> `,
})
export class ZardDemoProgressBarBasicComponent {}
Use the CLI to add the component to your project.
npx @ngzard/ui add progress-barpnpm dlx @ngzard/ui add progress-baryarn dlx @ngzard/ui add progress-barbunx @ngzard/ui add progress-barCreate the component directory structure and add the following files to your project.
import type { ClassValue } from 'clsx';
import { ChangeDetectionStrategy, Component, computed, input, ViewEncapsulation } from '@angular/core';
import { mergeClasses } from '../../shared/utils/utils';
import { containerProgressBarVariants, progressBarVariants, type ZardContainerProgressBarVariants, type ZardProgressBarVariants } from './progress-bar.variants';
@Component({
selector: 'z-progress-bar',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
styles: `
@keyframes indeterminate {
0% {
left: -0%;
width: 30%;
}
50% {
left: 50%;
width: 30%;
}
100% {
left: 100%;
width: 0;
}
}
`,
template: `
@if (zIndeterminate()) {
<div [class]="classes()">
<div [class]="barClasses()"></div>
</div>
} @else {
<div [class]="classes()">
<div [style.width.%]="correctedProgress()" [class]="barClasses()" id="bar"></div>
</div>
}
`,
host: {
class: 'w-full',
},
})
export class ZardProgressBarComponent {
readonly zType = input<ZardProgressBarVariants['zType']>('default');
readonly zSize = input<ZardContainerProgressBarVariants['zSize']>('default');
readonly zShape = input<ZardProgressBarVariants['zShape']>('default');
readonly zIndeterminate = input<ZardProgressBarVariants['zIndeterminate']>(undefined);
readonly class = input<ClassValue>('');
readonly barClass = input<ClassValue>('');
readonly progress = input(0);
readonly correctedProgress = computed(() => {
if (this.progress() > 100) return 100;
if (this.progress() < 0) return 0;
return this.progress();
});
protected readonly classes = computed(() =>
mergeClasses(containerProgressBarVariants({ zIndeterminate: this.zIndeterminate(), zType: this.zType(), zSize: this.zSize(), zShape: this.zShape() }), this.class()),
);
protected readonly barClasses = computed(() =>
mergeClasses(progressBarVariants({ zIndeterminate: this.zIndeterminate(), zType: this.zType(), zShape: this.zShape() }), this.barClass()),
);
}
import { cva, type VariantProps } from 'class-variance-authority';
export const containerProgressBarVariants = cva('w-full transition-all', {
variants: {
zType: {
default: 'bg-primary-foreground hover:bg-primary/10',
destructive: 'bg-primary-foreground dark:text-secondary-foreground hover:bg-destructive/10',
accent: 'bg-primary-foreground hover:bg-primary/10',
},
zSize: {
default: 'h-2',
sm: 'h-3',
lg: 'h-5',
},
zShape: {
default: 'rounded-sm',
circle: 'rounded-full',
square: 'rounded-none',
},
zIndeterminate: {
true: 'relative',
},
},
defaultVariants: {
zType: 'default',
zSize: 'default',
zShape: 'default',
},
});
export type ZardContainerProgressBarVariants = VariantProps<typeof containerProgressBarVariants>;
export const progressBarVariants = cva('h-full transition-all', {
variants: {
zType: {
default: 'bg-primary',
destructive: 'bg-destructive',
accent: 'bg-chart-1',
},
zShape: {
default: 'rounded-sm',
circle: 'rounded-full ',
square: 'rounded-none',
},
zIndeterminate: {
true: 'absolute animate-[indeterminate_1.5s_infinite_ease-out]',
},
},
defaultVariants: {
zType: 'default',
zShape: 'default',
},
});
export type ZardProgressBarVariants = VariantProps<typeof progressBarVariants>;
import { Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-basic',
standalone: true,
imports: [ZardProgressBarComponent],
template: ` <z-progress-bar [progress]="50"></z-progress-bar> `,
})
export class ZardDemoProgressBarBasicComponent {}
import { Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-indeterminate',
standalone: true,
imports: [ZardProgressBarComponent],
template: ` <z-progress-bar [progress]="50" [zShape]="'square'" [zIndeterminate]="true"></z-progress-bar> `,
})
export class ZardDemoProgressBarIndeterminateComponent {}
import { Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-shape',
standalone: true,
imports: [ZardProgressBarComponent],
template: `
<z-progress-bar [progress]="50" [zShape]="'default'"></z-progress-bar>
<z-progress-bar [progress]="50" [zShape]="'circle'"></z-progress-bar>
<z-progress-bar [progress]="50" [zShape]="'square'"></z-progress-bar>
`,
styles: [
`
:host {
display: flex;
flex-direction: column;
gap: 24px;
}
`,
],
})
export class ZardDemoProgressBarShapeComponent {}
import { Component } from '@angular/core';
import { ZardProgressBarComponent } from '../progress-bar.component';
@Component({
selector: 'z-demo-progress-bar-size',
standalone: true,
imports: [ZardProgressBarComponent],
template: `
<z-progress-bar [progress]="50" [zSize]="'default'"></z-progress-bar>
<z-progress-bar [progress]="50" [zSize]="'sm'"></z-progress-bar>
<z-progress-bar [progress]="50" [zSize]="'lg'"></z-progress-bar>
`,
styles: [
`
:host {
display: flex;
flex-direction: column;
gap: 24px;
}
`,
],
})
export class ZardDemoProgressBarSizeComponent {}