@libs-ui/components-process-bar-steps
v0.2.357-4
Published
> Component hiển thị thanh tiến trình dạng bước (stepper) với hỗ trợ Simple Mode và Advanced Mode.
Readme
@libs-ui/components-process-bar-steps
Component hiển thị thanh tiến trình dạng bước (stepper) với hỗ trợ Simple Mode và Advanced Mode.
Giới thiệu
LibsUiComponentsProcessBarStepsComponent là một standalone Angular component dùng để hiển thị các bước tiến trình (stepper/process bar). Component hỗ trợ hai chế độ cấu hình: Simple Mode cho phép cấu hình nhanh bằng tổng số bước và bước hiện tại, và Advanced Mode cho phép tùy chỉnh chi tiết từng bước bao gồm label, màu sắc, và trạng thái riêng biệt. Toàn bộ state được quản lý qua Angular Signals và tích hợp OnPush để tối ưu hiệu năng.
Tính năng
- ✅ Simple Mode: Cấu hình nhanh với
totalStep,currentStepvà màu sắc chung - ✅ Advanced Mode: Tùy chỉnh chi tiết từng bước (label, màu hoàn thành, màu đang xử lý, custom class)
- ✅ Label Position: Hỗ trợ 3 vị trí label —
top,bottom,inner - ✅ Label Alignment: Căn chỉnh
start,center,end - ✅ Customizable Dimensions: Tùy chỉnh
width,height,borderRadiuscho từng bước - ✅ Global Default Token: Inject token để cấu hình default toàn app qua
PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT - ✅ Reactive Signals: Toàn bộ state đều là Signal — cập nhật realtime khi signal thay đổi
- ✅ OnPush Change Detection: Tối ưu hiệu năng render
Khi nào sử dụng
- Hiển thị trạng thái đơn hàng (Order Tracking): Đặt hàng → Xử lý → Đã giao
- Hiển thị các bước trong quy trình đăng ký, onboarding hoặc wizard form
- Hiển thị lộ trình học tập, milestones hoặc checklist tiến trình
- Bất kỳ UI nào cần visualize tiến độ theo từng giai đoạn
Cài đặt
npm install @libs-ui/components-process-bar-stepsImport
import { LibsUiComponentsProcessBarStepsComponent } from '@libs-ui/components-process-bar-steps';
import { IProcessBarStepConfigInterface, IProcessBarStepSimpleConfigInterface, IProcessBarStepAdvancedConfigInterface } from '@libs-ui/components-process-bar-steps';
@Component({
standalone: true,
imports: [LibsUiComponentsProcessBarStepsComponent],
// ...
})
export class YourComponent {}Ví dụ sử dụng
Ví dụ 1 — Simple Mode (cấu hình nhanh)
<!-- your-component.component.html -->
<libs_ui-components-process_bar-steps [config]="configSimple()" />// your-component.component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsProcessBarStepsComponent, IProcessBarStepConfigInterface, IProcessBarStepSimpleConfigInterface } from '@libs-ui/components-process-bar-steps';
@Component({
standalone: true,
imports: [LibsUiComponentsProcessBarStepsComponent],
templateUrl: './your-component.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class YourComponent {
private readonly simpleConfigSignal = signal<IProcessBarStepSimpleConfigInterface>({
totalStep: 4,
currentStep: 2,
completedStep: 1,
currentStepColor: '#3B82F6',
stepCompletedColor: '#10B981',
});
protected readonly configSimple = signal<IProcessBarStepConfigInterface>({
simpleConfig: this.simpleConfigSignal,
widthStep: '60px',
heightStep: '8px',
radiusStep: 4,
backgroundColorStep: '#E5E7EB',
});
}Ví dụ 2 — Advanced Mode (tùy chỉnh từng bước, có label)
<!-- your-component.component.html -->
<libs_ui-components-process_bar-steps [config]="configAdvanced()" />// your-component.component.ts
import { Component, signal } from '@angular/core';
import { LibsUiComponentsProcessBarStepsComponent, IProcessBarStepConfigInterface, IProcessBarStepAdvancedConfigInterface } from '@libs-ui/components-process-bar-steps';
@Component({
standalone: true,
imports: [LibsUiComponentsProcessBarStepsComponent],
templateUrl: './your-component.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class YourComponent {
private readonly step1 = signal<IProcessBarStepAdvancedConfigInterface>({
label: 'Đặt hàng',
processCompleted: true,
processCompletedColor: '#10B981',
});
private readonly step2 = signal<IProcessBarStepAdvancedConfigInterface>({
label: 'Đang xử lý',
isCurrentProcess: true,
currentProcessColor: '#3B82F6',
});
private readonly step3 = signal<IProcessBarStepAdvancedConfigInterface>({
label: 'Đã giao',
processCompleted: false,
});
private readonly step4 = signal<IProcessBarStepAdvancedConfigInterface>({
label: 'Hoàn thành',
processCompleted: false,
});
protected readonly configAdvanced = signal<IProcessBarStepConfigInterface>({
advancedConfig: signal([this.step1, this.step2, this.step3, this.step4]),
positionLabel: 'bottom',
justifyLabel: 'center',
widthStep: '120px',
heightStep: '12px',
radiusStep: 6,
});
// Cập nhật trạng thái khi sự kiện xảy ra
protected handlerMarkShipped(): void {
this.step3.update((s) => ({ ...s, processCompleted: true, processCompletedColor: '#10B981' }));
this.step4.update((s) => ({ ...s, isCurrentProcess: true, currentProcessColor: '#3B82F6' }));
}
}Ví dụ 3 — Reactive với computed (tự động cập nhật)
<!-- your-component.component.html -->
<libs_ui-components-process_bar-steps [config]="configInteractive()" />// your-component.component.ts
import { Component, computed, signal, WritableSignal, effect } from '@angular/core';
import { LibsUiComponentsProcessBarStepsComponent, IProcessBarStepConfigInterface, IProcessBarStepSimpleConfigInterface } from '@libs-ui/components-process-bar-steps';
@Component({
standalone: true,
imports: [LibsUiComponentsProcessBarStepsComponent],
templateUrl: './your-component.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class YourComponent {
protected currentStep = signal(1);
protected totalSteps = signal(5);
private readonly simpleConfigValues = computed<IProcessBarStepSimpleConfigInterface>(() => ({
totalStep: this.totalSteps(),
currentStep: this.currentStep(),
completedStep: this.currentStep() - 1,
currentStepColor: '#8B5CF6',
stepCompletedColor: '#F59E0B',
}));
// WritableSignal wrapper bắt buộc vì IProcessBarStepConfigInterface yêu cầu WritableSignal
private readonly simpleConfigSignal: WritableSignal<IProcessBarStepSimpleConfigInterface> = signal(this.simpleConfigValues());
protected readonly configInteractive = computed<IProcessBarStepConfigInterface>(() => ({
simpleConfig: this.simpleConfigSignal,
positionLabel: 'top',
justifyLabel: 'center',
widthStep: '80px',
heightStep: '10px',
radiusStep: 5,
}));
constructor() {
// Đồng bộ computed → writableSignal để truyền vào config
effect(() => {
untracked(() => this.simpleConfigSignal.set(this.simpleConfigValues()));
});
}
protected handlerNextStep(): void {
this.currentStep.update((v) => Math.min(v + 1, this.totalSteps()));
}
protected handlerPrevStep(): void {
this.currentStep.update((v) => Math.max(v - 1, 1));
}
}Ví dụ 4 — Cấu hình Global Default Token (toàn app)
// app.config.ts hoặc providers của module root
import { ApplicationConfig } from '@angular/core';
import { PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT } from '@libs-ui/utils';
import { IProcessBarStepConfigInterface } from '@libs-ui/components-process-bar-steps';
export const appConfig: ApplicationConfig = {
providers: [
{
provide: PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT,
useValue: {
widthStep: '80px',
heightStep: '12px',
backgroundColorStep: '#F3F4F6',
radiusStep: 20,
} satisfies Partial<IProcessBarStepConfigInterface>,
},
],
};@Input()
| Input | Type | Default | Mô tả | Ví dụ |
| ---------- | -------------------------------- | ------------ | ----------------------------------------------------------------------------------------------- | --------------------------- |
| [config] | IProcessBarStepConfigInterface | Bắt buộc | Object cấu hình toàn bộ process bar — bao gồm kích thước, màu sắc, vị trí label và dữ liệu bước | [config]="configSimple()" |
Types & Interfaces
import { IProcessBarStepConfigInterface, IProcessBarStepSimpleConfigInterface, IProcessBarStepAdvancedConfigInterface } from '@libs-ui/components-process-bar-steps';IProcessBarStepConfigInterface
Config chính truyền vào [config]. Cần chọn một trong hai chế độ: simpleConfig hoặc advancedConfig.
| Property | Type | Default | Mô tả | Ví dụ |
| --------------------- | ------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------ | ------------------------------------------------------------- |
| simpleConfig | WritableSignal<IProcessBarStepSimpleConfigInterface> | undefined | Cấu hình Simple Mode — tự động sinh các bước từ totalStep | simpleConfig: signal({ totalStep: 4, currentStep: 2, ... }) |
| advancedConfig | WritableSignal<Array<WritableSignal<IProcessBarStepAdvancedConfigInterface>>> | undefined | Cấu hình Advanced Mode — mảng signal cho từng bước | advancedConfig: signal([step1, step2, step3]) |
| positionLabel | 'top' \| 'bottom' \| 'inner' | 'top' | Vị trí hiển thị label của từng bước | positionLabel: 'bottom' |
| justifyLabel | 'start' \| 'center' \| 'end' | 'center' | Căn chỉnh ngang của label và nội dung bên trong bước | justifyLabel: 'start' |
| widthStep | string | '80px' | Chiều rộng mỗi thanh bước | widthStep: '60px' |
| heightStep | string | '12px' | Chiều cao mỗi thanh bước | heightStep: '8px' |
| backgroundColorStep | string | '#F8F9FA' | Màu nền mặc định cho các bước chưa active và chưa hoàn thành | backgroundColorStep: '#E5E7EB' |
| radiusStep | number | 20 | Border radius (đơn vị px) — 20 tạo hình pill đầy đủ | radiusStep: 4 |
| classInclude | string | '' | Class CSS bổ sung cho thẻ container bao ngoài | classInclude: 'my-[16px]' |
IProcessBarStepSimpleConfigInterface
Dùng trong simpleConfig — component tự động tạo các bước dựa trên config này.
| Property | Type | Default | Mô tả | Ví dụ |
| -------------------- | -------- | --------------- | --------------------------------------------------------------------------------------------------------------- | ------------------------------- |
| totalStep | number | Bắt buộc | Tổng số bước cần hiển thị | totalStep: 5 |
| currentStep | number | Bắt buộc | Index bước hiện tại (bắt đầu từ 1) | currentStep: 3 |
| completedStep | number | = currentStep | Số bước đã hoàn thành (index <= completedStep được tô màu completed). Mặc định bằng currentStep nếu không set | completedStep: 2 |
| currentStepColor | string | Bắt buộc | Màu của thanh bước đang ở vị trí currentStep | currentStepColor: '#3B82F6' |
| stepCompletedColor | string | Bắt buộc | Màu của các thanh bước đã hoàn thành (index <= completedStep) | stepCompletedColor: '#10B981' |
IProcessBarStepAdvancedConfigInterface
Dùng trong advancedConfig — mỗi bước là một WritableSignal<IProcessBarStepAdvancedConfigInterface>.
| Property | Type | Default | Mô tả | Ví dụ |
| ----------------------- | --------- | ----------- | ----------------------------------------------------------- | ----------------------------------- |
| processCompleted | boolean | false | Bước đã hoàn thành — áp dụng processCompletedColor | processCompleted: true |
| processCompletedColor | string | '#33DA8A' | Màu nền khi bước đã hoàn thành | processCompletedColor: '#10B981' |
| isCurrentProcess | boolean | false | Bước đang được xử lý — áp dụng currentProcessColor | isCurrentProcess: true |
| currentProcessColor | string | '#4E8CF7' | Màu nền khi bước đang được xử lý | currentProcessColor: '#3B82F6' |
| label | string | undefined | Text label hiển thị theo positionLabel | label: 'Đặt hàng' |
| classLabel | string | '' | Class CSS bổ sung cho thẻ label | classLabel: 'text-green-600' |
| classIncludeStep | string | '' | Class CSS bổ sung cho thanh bước (step bar) | classIncludeStep: 'shadow-sm' |
| classIncludeContainer | string | '' | Class CSS bổ sung cho container bao bọc bước (step + label) | classIncludeContainer: 'px-[4px]' |
Thứ tự ưu tiên màu sắc
Với mỗi bước, màu nền được xác định theo thứ tự ưu tiên sau:
processCompletedColor(nếuprocessCompleted: true)currentProcessColor(nếuisCurrentProcess: true)backgroundColorSteptừ config (màu mặc định cho bước chưa active)
Lưu ý quan trọng
⚠️ Chọn một trong hai mode: simpleConfig và advancedConfig không dùng cùng nhau. Nếu cả hai đều được set, advancedConfig có độ ưu tiên cao hơn vì template sử dụng config().advancedConfig?.() || simpleSteps().
⚠️ WritableSignal bắt buộc: Cả simpleConfig và advancedConfig đều phải là WritableSignal, không thể dùng computed() trực tiếp. Khi cần reactive từ computed, dùng effect() để sync giá trị vào WritableSignal (xem Ví dụ 3).
⚠️ completedStep trong Simple Mode: Nếu không set completedStep, nó mặc định bằng currentStep. Bước có index <= completedStep sẽ tô màu stepCompletedColor, bước có index === currentStep tô màu currentStepColor.
⚠️ Advanced Mode — Color Priority: Màu processCompletedColor ghi đè currentProcessColor. Nếu một bước vừa có processCompleted: true vừa có isCurrentProcess: true, màu hoàn thành sẽ được hiển thị.
⚠️ Global Default Token: Dùng PROCESS_BAR_STEPS_CONFIG_DEFAULT_TOKEN_INJECT (từ @libs-ui/utils) để thiết lập giá trị mặc định cho widthStep, heightStep, backgroundColorStep, radiusStep ở cấp app — tránh lặp lại config trong từng component.
Demo
npx nx serve core-uiTruy cập: http://localhost:4500/components/process-bar/steps
