Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions components/progress/demo/indeterminate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 11
title:
zh-CN: 不确定进度
en-US: Indeterminate
---

## zh-CN

当无法确定任务的具体进度时,可以使用不确定状态的进度条,展示持续加载动画。

## en-US

When the exact progress of a task is unknown, use an indeterminate progress bar to show continuous loading animation.
18 changes: 18 additions & 0 deletions components/progress/demo/indeterminate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Component } from '@angular/core';

import { NzFlexModule } from 'ng-zorro-antd/flex';
import { NzProgressModule } from 'ng-zorro-antd/progress';

@Component({
selector: 'nz-demo-progress-indeterminate',
imports: [NzFlexModule, NzProgressModule],
Comment on lines +6 to +8

Copilot AI Feb 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the coding guidelines, all components should set changeDetection: ChangeDetectionStrategy.OnPush in the @Component decorator. This is missing from this demo component but is present in all other demo components in the codebase. Adding this will improve performance by reducing unnecessary change detection cycles.

Copilot generated this review using guidance from repository custom instructions.
template: `
<div nz-flex nzVertical nzGap="small">
<nz-progress [nzIndeterminate]="true"></nz-progress>
<nz-progress [nzIndeterminate]="true" nzStatus="exception"></nz-progress>
<nz-progress [nzIndeterminate]="true" nzStatus="success"></nz-progress>
<nz-progress [nzIndeterminate]="true" [nzShowInfo]="false"></nz-progress>
</div>
`
})
export class NzDemoProgressIndeterminateComponent {}
21 changes: 11 additions & 10 deletions components/progress/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ If it will take a long time to complete an operation, you can use `Progress` to

### nz-progress

| Property | Description | Type | Default | Global Config |
| -------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------- | ------------- |
| `[nzType]` | to set the type | `'line' \| 'circle' \| 'dashboard'` | `'line'` | |
| `[nzFormat]` | template function of the content | `(percent: number) => string \| TemplateRef<{ $implicit: number }>` | `percent => percent + '%'` | |
| `[nzPercent]` | to set the completion percentage | `number` | `0` | |
| `[nzShowInfo]` | whether to display the progress value and the status icon | `boolean` | `true` | ✅ |
| `[nzStatus]` | to set the status of the Progress | `'success' \| 'exception' \| 'active' \| 'normal'` | - | |
| `[nzStrokeLinecap]` | to set the style of the progress linecap | `'round' \| 'square'` | `'round'` | ✅ |
| `[nzStrokeColor]` | color of progress bar, render linear-gradient when passing an object | `string \| { from: string; to: string: direction: string; [percent: string]: string }` | - | ✅ |
| `[nzSuccessPercent]` | segmented success percent | `number` | 0 | |
| Property | Description | Type | Default | Global Config |
| -------------------- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------- | ------------- |
| `[nzType]` | to set the type | `'line' \| 'circle' \| 'dashboard'` | `'line'` | |
| `[nzFormat]` | template function of the content | `(percent: number) => string \| TemplateRef<{ $implicit: number }>` | `percent => percent + '%'` | |
| `[nzPercent]` | to set the completion percentage | `number` | `0` | |
| `[nzShowInfo]` | whether to display the progress value and the status icon | `boolean` | `true` | ✅ |
| `[nzStatus]` | to set the status of the Progress | `'success' \| 'exception' \| 'active' \| 'normal'` | - | |
| `[nzStrokeLinecap]` | to set the style of the progress linecap | `'round' \| 'square'` | `'round'` | ✅ |
| `[nzStrokeColor]` | color of progress bar, render linear-gradient when passing an object | `string \| { from: string; to: string: direction: string; [percent: string]: string }` | - | ✅ |
| `[nzSuccessPercent]` | segmented success percent | `number` | 0 | |
| `[nzIndeterminate]` | whether to show indeterminate progress with continuous animation (only available for `nzType="line"`) | `boolean` | `false` | |

### `nzType="line"`

Expand Down
21 changes: 11 additions & 10 deletions components/progress/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ description: 展示操作的当前进度。

各类型通用的属性。

| 属性 | 说明 | 类型 | 默认值 | 全局配置 |
| -------------------- | ---------------------------- | -------------------------------------------------------------------------------------- | -------------------------- | -------- |
| `[nzType]` | 类型 | `'line' \| 'circle' \| 'dashboard'` | `'line'` | |
| `[nzFormat]` | 内容的模板函数 | `(percent: number) => string \| TemplateRef<{ $implicit: number }>` | `percent => percent + '%'` |
| `[nzPercent]` | 百分比 | `number` | `0` | |
| `[nzShowInfo]` | 是否显示进度数值或状态图标 | `boolean` | `true` | ✅ |
| `[nzStatus]` | 状态 | `'success' \| 'exception' \| 'active' \| 'normal'` | - | |
| `[nzStrokeLinecap]` | 进度条端点形状 | `'round' \| 'square'` | `'round'` | ✅ |
| `[nzStrokeColor]` | 进度条颜色,传入对象时为渐变 | `string \| { from: string; to: string: direction: string; [percent: string]: string }` | - | ✅ |
| `[nzSuccessPercent]` | 已完成的分段百分比 | `number` | 0 | |
| 属性 | 说明 | 类型 | 默认值 | 全局配置 |
| -------------------- | ------------------------------------------------------------ | -------------------------------------------------------------------------------------- | -------------------------- | -------- |
| `[nzType]` | 类型 | `'line' \| 'circle' \| 'dashboard'` | `'line'` | |
| `[nzFormat]` | 内容的模板函数 | `(percent: number) => string \| TemplateRef<{ $implicit: number }>` | `percent => percent + '%'` |
| `[nzPercent]` | 百分比 | `number` | `0` | |
| `[nzShowInfo]` | 是否显示进度数值或状态图标 | `boolean` | `true` | ✅ |
| `[nzStatus]` | 状态 | `'success' \| 'exception' \| 'active' \| 'normal'` | - | |
| `[nzStrokeLinecap]` | 进度条端点形状 | `'round' \| 'square'` | `'round'` | ✅ |
| `[nzStrokeColor]` | 进度条颜色,传入对象时为渐变 | `string \| { from: string; to: string: direction: string; [percent: string]: string }` | - | ✅ |
| `[nzSuccessPercent]` | 已完成的分段百分比 | `number` | 0 | |
| `[nzIndeterminate]` | 是否显示不确定状态的持续加载动画(仅适用于 `nzType="line"`) | `boolean` | `false` | |

### `nzType="line"`

Expand Down
4 changes: 3 additions & 1 deletion components/progress/progress.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
[class.ant-progress-circle]="isCircleStyle"
[class.ant-progress-steps]="isSteps"
[class.ant-progress-rtl]="dir === 'rtl'"
[class.ant-progress-indeterminate]="nzIndeterminate && nzType === 'line'"
>
@if (nzType === 'line') {
<div>
Expand All @@ -100,7 +101,7 @@
<div class="ant-progress-inner">
<div
class="ant-progress-bg"
[style.width.%]="nzPercent"
[style.width.%]="nzIndeterminate ? 100 : nzPercent"
[style.border-radius]="nzStrokeLinecap === 'round' ? '100px' : '0'"
[style.background]="!isGradient ? nzStrokeColor : null"
[style.background-image]="isGradient ? lineGradient : null"
Expand Down Expand Up @@ -191,6 +192,7 @@
@Input() @WithConfig() nzStrokeLinecap: NzProgressStrokeLinecapType = 'round';

@Input({ transform: numberAttribute }) nzSteps: number = 0;
@Input() nzIndeterminate: boolean = false;
Comment thread
Hbib24 marked this conversation as resolved.
Outdated
Comment thread
Hbib24 marked this conversation as resolved.
Outdated

steps: NzProgressStepItem[] = [];

Expand Down Expand Up @@ -245,54 +247,54 @@
});
}

ngOnChanges(changes: SimpleChanges): void {
const {
nzSteps,
nzGapPosition,
nzStrokeLinecap,
nzStrokeColor,
nzGapDegree,
nzType,
nzStatus,
nzPercent,
nzSuccessPercent,
nzStrokeWidth
} = changes;

if (nzStatus) {
this.cachedStatus = this.nzStatus || this.cachedStatus;
}

if (nzPercent || nzSuccessPercent) {
const fillAll = parseInt(this.nzPercent.toString(), 10) >= 100;
if (fillAll) {
if ((isNotNil(this.nzSuccessPercent) && this.nzSuccessPercent! >= 100) || this.nzSuccessPercent === undefined) {
this.inferredStatus = 'success';
}
} else {
this.inferredStatus = this.cachedStatus;
}
}

if (nzStatus || nzPercent || nzSuccessPercent || nzStrokeColor) {
this.updateIcon();
}

if (nzStrokeColor) {
this.setStrokeColor();
}

if (nzGapPosition || nzStrokeLinecap || nzGapDegree || nzType || nzPercent || nzStrokeColor || nzStrokeColor) {
this.getCirclePaths();
}

if (nzPercent || nzSteps || nzStrokeWidth) {
this.isSteps = this.nzSteps > 0;
if (this.isSteps) {
this.getSteps();
}
}
}

Check notice on line 297 in components/progress/progress.component.ts

View check run for this annotation

codefactor.io / CodeFactor

components/progress/progress.component.ts#L250-L297

Complex Method

ngOnInit(): void {
this.directionality.change?.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(direction => {
Expand Down
15 changes: 15 additions & 0 deletions components/progress/progress.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,19 @@ describe('progress', () => {
);
});

it('should indeterminate work', () => {
fixture.detectChanges();
expect(progress.nativeElement.firstElementChild!.classList).not.toContain('ant-progress-indeterminate');

testComponent.indeterminate = true;
fixture.detectChanges();
expect(progress.nativeElement.firstElementChild!.classList).toContain('ant-progress-indeterminate');

// Should only work with line type
const progressBar = progress.nativeElement.querySelector('.ant-progress-bg');
expect(progressBar).toBeTruthy();
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test correctly verifies the positive case for nzType="line". To make it more robust and prevent regressions, please also test the negative case: that ant-progress-indeterminate class is not applied when nzIndeterminate is true but nzType is not 'line' (e.g., 'circle').

You could add this at the end of the test:

      // Should not work with other types
      testComponent.type = 'circle';
      fixture.detectChanges();
      expect(progress.nativeElement.firstElementChild!.classList).not.toContain('ant-progress-indeterminate');

Comment on lines +183 to +194

Copilot AI Feb 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test could be more comprehensive. Consider adding assertions to verify: 1) that the progress bar width is set to 100% when indeterminate is true (the template sets [style.width.%]="nzIndeterminate ? 100 : nzPercent"), and 2) that the indeterminate state doesn't apply to circle or dashboard types by testing with those types.

Copilot uses AI. Check for mistakes.

it('should support steps mode', () => {
testComponent.steps = 5;
testComponent.percent = 50;
Expand Down Expand Up @@ -447,6 +460,7 @@ describe('progress', () => {
[nzStrokeColor]="strokeColor"
[nzStrokeLinecap]="strokeLinecap"
[nzSteps]="steps"
[nzIndeterminate]="indeterminate"
></nz-progress>
<ng-template #formatterTemplate let-percent>{{ percent }} / 100</ng-template>
`
Expand All @@ -463,6 +477,7 @@ export class NzTestProgressLineComponent {
strokeLinecap: NzProgressStrokeLinecapType = 'round';
steps?: number;
strokeColor?: NzProgressStrokeColorType;
indeterminate = false;
}

@Component({
Expand Down
35 changes: 35 additions & 0 deletions components/progress/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,31 @@
}
}

&-indeterminate&-line {
.@{progress-prefix-cls}-bg {
position: relative;
width: 100% !important;
overflow: hidden;
Comment on lines +127 to +129

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The width: 100% !important; rule is redundant. The component's template already sets the width to 100% via an inline style when nzIndeterminate is true. Since inline styles have higher precedence, this CSS rule is unnecessary. Removing it cleans up the code and avoids using !important, which is a good practice.

      position: relative;
      overflow: hidden;


&::before {
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 200%;
background-image: repeating-linear-gradient(
-45deg,
transparent,
transparent 8px,
rgba(255, 255, 255, 0.25) 8px,
rgba(255, 255, 255, 0.25) 16px
);
animation: ~'@{ant-prefix}-progress-indeterminate' 1s linear infinite;
content: '';
}
}
}

&-status-exception {
.@{progress-prefix-cls}-bg {
background-color: @error-color;
Expand Down Expand Up @@ -207,4 +232,14 @@
}
}

@keyframes ~"@{ant-prefix}-progress-indeterminate" {
0% {
transform: translateX(0);
}

100% {

Copilot AI Feb 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The animation translate value of -22.627px is a magic number that could benefit from a comment explaining its derivation. This value represents the diagonal length of the 16px stripe pattern (16 * √2 ≈ 22.627px), which ensures the animation loops seamlessly with the repeating diagonal gradient. Adding a comment would improve maintainability.

Suggested change
100% {
100% {
// 22.627px ≈ 16 * √2: move by one diagonal of the 16px diagonal stripe pattern
// to ensure the indeterminate animation loops seamlessly with the repeating gradient.

Copilot uses AI. Check for mistakes.
transform: translateX(-22.627px);
}
}

@import './rtl';
Loading