npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-breadcrumb

v0.2.357-11

Published

> Component hiển thị tiến trình nhiều bước (step indicator / breadcrumb) cho các quy trình làm việc trong Angular.

Readme

@libs-ui/components-breadcrumb

Component hiển thị tiến trình nhiều bước (step indicator / breadcrumb) cho các quy trình làm việc trong Angular.

Giới thiệu

@libs-ui/components-breadcrumb cung cấp hai component: LibsUiComponentsBreadcrumbComponent dùng cho breadcrumb bước đơn giản dạng số thứ tự, và LibsUiComponentsBreadcrumbMultiStepComponent dùng cho breadcrumb dạng tab liền khối (pill-style) hỗ trợ dropdown tại từng bước. Cả hai đều hỗ trợ điều khiển programmatic qua FunctionsControl, tích hợp i18n, và sử dụng Angular Signals với ChangeDetectionStrategy.OnPush.

Tính năng

  • ✅ Hiển thị các bước với số thứ tự, tiêu đề và trạng thái (đang chọn, đã hoàn thành, vô hiệu hóa)
  • ✅ Three alignment modes: center (mặc định), left, right
  • ✅ Tùy chỉnh độ rộng dải ngăn cách giữa các bước
  • ✅ Two-way binding cho completedIndexsteps qua Angular Signals model()
  • ✅ Điều khiển programmatic qua IBreadCrumbFunctionControlEvent (set selected, complete, disable, reset)
  • ✅ Sub-component MultiStep với kiểu hiển thị pill liền khối, hỗ trợ dropdown tại từng bước
  • ✅ Tích hợp @ngx-translate/core cho tiêu đề đa ngôn ngữ
  • ✅ Standalone component, ChangeDetectionStrategy.OnPush, Angular Signals
  • ✅ Hỗ trợ accessibility: keyboard navigation (Enter, Space)

Khi nào sử dụng

  • Khi cần hiển thị tiến trình của quy trình nhiều bước (wizard, multi-step form, checkout flow)
  • Khi muốn cho người dùng biết đang ở bước nào và còn bao nhiêu bước còn lại
  • Khi cần điều khiển breadcrumb từ bên ngoài (tự động chuyển bước, đánh dấu hoàn thành) qua API
  • Khi có quy trình phức tạp với từng bước có thể chọn giá trị từ dropdown (MultiStep)

Cài đặt

npm install @libs-ui/components-breadcrumb

Import

// Component breadcrumb bước đơn giản
import { LibsUiComponentsBreadcrumbComponent } from '@libs-ui/components-breadcrumb';

// Component breadcrumb dạng pill/tab liền khối có dropdown
import { LibsUiComponentsBreadcrumbMultiStepComponent } from '@libs-ui/components-breadcrumb';

// Interfaces & Types
import {
  ITabBreadCrumb,
  ITabBreadCrumbSelected,
  ITabBreadCrumbMultiStep,
  ITabBreadCrumbMultiStepSelected,
  IBreadCrumbFunctionControlEvent,
  IConfigClassMultiStep,
  TYPE_MODE_BREADCRUMB,
  TYPE_MULTI_STEP,
} from '@libs-ui/components-breadcrumb';

@Component({
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbComponent],
  // ...
})
export class YourComponent {}

Ví dụ sử dụng

1. Breadcrumb cơ bản

// your.component.ts
import { Component } from '@angular/core';
import { ITabBreadCrumb, LibsUiComponentsBreadcrumbComponent } from '@libs-ui/components-breadcrumb';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbComponent],
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  readonly steps: ITabBreadCrumb[] = [
    { number: 1, title: 'Thông tin cơ bản' },
    { number: 2, title: 'Cấu hình dịch vụ' },
    { number: 3, title: 'Xác nhận & Hoàn tất' },
  ];
}
<!-- your.component.html -->
<libs_ui-components-breadcrumb [steps]="steps" />

2. Breadcrumb với chế độ căn lề và độ rộng tùy chỉnh

// your.component.ts
import { Component } from '@angular/core';
import { ITabBreadCrumb, LibsUiComponentsBreadcrumbComponent } from '@libs-ui/components-breadcrumb';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbComponent],
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  readonly steps: ITabBreadCrumb[] = [
    { number: 1, title: 'Khởi tạo' },
    { number: 2, title: 'Thiết lập' },
    { number: 3, title: 'Hoàn thành' },
  ];
}
<!-- Căn trái, dải ngăn cách 40px -->
<libs_ui-components-breadcrumb
  [steps]="steps"
  mode="left"
  [width]="40"
/>

<!-- Căn phải, dải ngăn cách 20px -->
<libs_ui-components-breadcrumb
  [steps]="steps"
  mode="right"
  [width]="20"
/>

3. Breadcrumb với điều khiển programmatic qua FunctionsControl

// your.component.ts
import { Component, signal } from '@angular/core';
import {
  IBreadCrumbFunctionControlEvent,
  ITabBreadCrumb,
  ITabBreadCrumbSelected,
  LibsUiComponentsBreadcrumbComponent,
} from '@libs-ui/components-breadcrumb';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbComponent],
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  readonly steps: ITabBreadCrumb[] = [
    { number: 1, title: 'Nhập thông tin' },
    { number: 2, title: 'Xác minh' },
    { number: 3, title: 'Hoàn tất' },
  ];

  readonly completedSteps = signal<number[]>([]);

  private breadcrumbControl: IBreadCrumbFunctionControlEvent | undefined;

  handlerFunctionControl(event: IBreadCrumbFunctionControlEvent): void {
    this.breadcrumbControl = event;
  }

  handlerStepSelected(event: ITabBreadCrumbSelected): void {
    this.breadcrumbControl?.setSelectedStep(event.index);
  }

  async goToNextStep(): Promise<void> {
    const currentIndex = await this.breadcrumbControl?.getSelectedIndex() ?? 0;
    await this.breadcrumbControl?.setCompletedStep(true, currentIndex);
    await this.breadcrumbControl?.setSelectedStep(currentIndex + 1);
  }

  async resetAll(): Promise<void> {
    await this.breadcrumbControl?.resetCompleteIndex(true);
    await this.breadcrumbControl?.setSelectedStep(0);
  }
}
<libs_ui-components-breadcrumb
  [steps]="steps"
  [(completedIndex)]="completedSteps"
  (outFunctionControl)="handlerFunctionControl($event)"
  (outStepSelected)="handlerStepSelected($event)"
/>

<div class="flex gap-3 mt-4">
  <button (click)="goToNextStep()">Bước tiếp theo</button>
  <button (click)="resetAll()">Reset tất cả</button>
</div>

4. MultiStep breadcrumb dạng pill

// your.component.ts
import { Component } from '@angular/core';
import {
  ITabBreadCrumbMultiStep,
  ITabBreadCrumbMultiStepSelected,
  LibsUiComponentsBreadcrumbMultiStepComponent,
} from '@libs-ui/components-breadcrumb';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbMultiStepComponent],
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  readonly multiSteps: ITabBreadCrumbMultiStep[] = [
    { number: 1, title: 'Đề xuất', status: 'completed', type: 'text' },
    { number: 2, title: 'Phê duyệt', status: 'selected', type: 'text' },
    { number: 3, title: 'Thực hiện', status: 'normal', type: 'text' },
    { number: 4, title: 'Kết thúc', status: 'disabled', type: 'text' },
  ];

  handlerMultiStepSelect(event: ITabBreadCrumbMultiStepSelected<ITabBreadCrumbMultiStep>): void {
    console.log('Selected step:', event.index, 'Type:', event.type);
  }
}
<libs_ui-components-breadcrumb-multi_step
  [stepsMulti]="multiSteps"
  (outMultiStepSelect)="handlerMultiStepSelect($event)"
/>

5. Bước có trạng thái disable và class tùy chỉnh

// your.component.ts
import { Component } from '@angular/core';
import { ITabBreadCrumb, LibsUiComponentsBreadcrumbComponent } from '@libs-ui/components-breadcrumb';

@Component({
  selector: 'app-example',
  standalone: true,
  imports: [LibsUiComponentsBreadcrumbComponent],
  templateUrl: './example.component.html',
})
export class ExampleComponent {
  readonly steps: ITabBreadCrumb[] = [
    { number: 1, title: 'Khởi tạo' },
    { number: 2, title: 'Xem xét', disable: true },
    { number: 3, title: 'Phê duyệt', classInclude: 'w-[200px]' },
  ];
}
<libs_ui-components-breadcrumb
  [steps]="steps"
  [backgroundWhite]="true"
  classInclude="px-4 py-2"
/>

@Input() — LibsUiComponentsBreadcrumbComponent

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [backgroundWhite] | boolean | undefined | Áp dụng nền trắng (#ffffff) cho container | [backgroundWhite]="true" | | [classInclude] | string | undefined | Class CSS bổ sung cho container bao ngoài | classInclude="px-4 py-2" | | [(completedIndex)] | Array<number> | [] | Two-way binding — danh sách index các bước đã hoàn thành (hiển thị icon check) | [(completedIndex)]="completedSteps" | | [mode] | 'center' \| 'left' \| 'right' | 'center' | Canh lề của các bước trong container | mode="left" | | [(steps)] | Array<ITabBreadCrumb> | undefined | Two-way binding — danh sách cấu hình các bước | [(steps)]="steps" | | [width] | number | 24 | Độ rộng (px) của dải ngăn cách ngang giữa các bước | [width]="40" |

@Output() — LibsUiComponentsBreadcrumbComponent

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outFunctionControl) | IBreadCrumbFunctionControlEvent | Emit object chứa các hàm điều khiển component, phát ngay trong ngOnInit. Phải capture để gọi API programmatic. | handlerFunctionControl(event: IBreadCrumbFunctionControlEvent): void { this.control = event; } | (outFunctionControl)="handlerFunctionControl($event)" | | (outStepSelected) | ITabBreadCrumbSelected | Emit khi người dùng click vào một bước (không phát nếu bước bị disable) | handlerStepSelected(event: ITabBreadCrumbSelected): void { this.control?.setSelectedStep(event.index); } | (outStepSelected)="handlerStepSelected($event)" |

@Input() — LibsUiComponentsBreadcrumbMultiStepComponent

Kế thừa toàn bộ Input của LibsUiComponentsBreadcrumbComponent, cộng thêm:

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [configClassMultiStep] | IConfigClassMultiStep | undefined | Cấu hình class và kích thước cho từng bước pill | [configClassMultiStep]="{ maxWidth: 160, width: 120 }" | | [elementRef] | HTMLElement | undefined | Tham chiếu đến container HTMLElement để hỗ trợ auto-scroll đến bước đang chọn | [elementRef]="containerEl" | | [popoverCustomConfig] | IPopoverCustomConfig | ConfigPopupDropdown() | Cấu hình popover tùy chỉnh cho dropdown tại mỗi bước | [popoverCustomConfig]="myPopoverConfig" | | [stepsMulti] | Array<ITabBreadCrumbMultiStep> | — (required) | Danh sách cấu hình đầy đủ các bước multi-step | [stepsMulti]="multiSteps" |

@Output() — LibsUiComponentsBreadcrumbMultiStepComponent

Kế thừa toàn bộ Output của LibsUiComponentsBreadcrumbComponent, cộng thêm:

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outMultiStepSelect) | ITabBreadCrumbMultiStepSelected<any> | Emit khi người dùng chọn bước (text click hoặc chọn item từ dropdown). Kèm callBack để ẩn/hiện keys trong dropdown. | handlerMultiStepSelect(event: ITabBreadCrumbMultiStepSelected<MyStep>): void { this.onSelectStep(event); } | (outMultiStepSelect)="handlerMultiStepSelect($event)" |

FunctionsControl API — IBreadCrumbFunctionControlEvent

Capture object từ (outFunctionControl) để gọi các phương thức điều khiển:

| Method | Signature | Mô tả | |---|---|---| | getCompleteIndex | () => Promise<Array<number>> | Lấy danh sách index các bước đang được đánh dấu hoàn thành | | getSelectedIndex | () => Promise<number> | Lấy index của bước đang được chọn | | resetCompleteIndex | (resetAll: boolean, index?: number) => Promise<void> | Reset trạng thái hoàn thành — resetAll=true xóa tất cả, resetAll=false + index xóa 1 bước cụ thể | | setCompletedStep | (complete: boolean, index: number) => Promise<void> | Đánh dấu hoặc bỏ đánh dấu hoàn thành cho bước tại index | | setSelectedStep | (index: number) => Promise<void> | Thiết lập bước đang được chọn (highlight active) | | setStepDisable | (steps: Array<number>) => Promise<void> | Thiết lập danh sách các bước bị vô hiệu hóa (không thể click) |

Types & Interfaces

import {
  ITabBreadCrumb,
  ITabBreadCrumbSelected,
  ITabBreadCrumbMultiStep,
  ITabBreadCrumbMultiStepSelected,
  IBreadCrumbFunctionControlEvent,
  IConfigClassMultiStep,
  TYPE_MODE_BREADCRUMB,
  TYPE_MULTI_STEP,
} from '@libs-ui/components-breadcrumb';

/** Cấu hình một bước trong breadcrumb đơn giản */
export interface ITabBreadCrumb {
  number: number;          // Số hiển thị trong vòng tròn bước
  title: string;           // Tiêu đề bước (hỗ trợ i18n key)
  valid?: boolean;         // Trạng thái hợp lệ
  disable?: boolean;       // Vô hiệu hóa click trên bước này
  classInclude?: string;   // Class CSS bổ sung riêng cho bước này (mặc định: 'w-full')
  config?: IPopover;       // Cấu hình popover tooltip
}

/** Dữ liệu emit khi chọn bước */
export interface ITabBreadCrumbSelected {
  index: number;           // Index (0-based) của bước được chọn
}

/** Cấu hình một bước trong MultiStep breadcrumb */
export interface ITabBreadCrumbMultiStep extends ITabBreadCrumb {
  status: TYPE_MULTI_STEP;            // Trạng thái hiển thị của bước
  type: 'text' | 'dropdown';          // Kiểu tương tác: text click hoặc dropdown
  listHasButtonUnSelectOption?: boolean; // Hiện nút bỏ chọn trong dropdown
  listConfigItem?: IListConfigItem;   // Cấu hình danh sách dropdown
  popover?: IPopover;                 // Cấu hình tooltip cho tiêu đề
  listKeysHidden?: Array<string>;     // Danh sách keys ẩn trong dropdown
}

/** Dữ liệu emit khi chọn bước trong MultiStep */
export interface ITabBreadCrumbMultiStepSelected<T> {
  type: 'text' | 'dropdown';          // Kiểu tương tác đã xảy ra
  index: number;                       // Index (0-based) của bước được chọn
  step?: T;                            // Item được chọn từ dropdown (nếu type='dropdown')
  callBack?: (step: T) => void;        // Callback để cập nhật keys ẩn trong dropdown
}

/** Object điều khiển breadcrumb từ bên ngoài (emit qua outFunctionControl) */
export interface IBreadCrumbFunctionControlEvent {
  setSelectedStep: (index: number) => Promise<void>;
  setCompletedStep: (complete: boolean, index: number) => Promise<void>;
  setStepDisable: (steps: Array<number>) => Promise<void>;
  getCompleteIndex: () => Promise<Array<number>>;
  getSelectedIndex: () => Promise<number>;
  resetCompleteIndex: (resetAll: boolean, index?: number) => Promise<void>;
}

/** Cấu hình class/kích thước cho MultiStep pill */
export interface IConfigClassMultiStep {
  classTitleInclude?: string; // Class CSS bổ sung cho phần tiêu đề trong pill
  classInclude?: string;      // Class CSS bổ sung cho container pill
  maxWidth?: number;          // Chiều rộng tối đa (px) của pill
  width?: number;             // Chiều rộng cố định (px) của pill
}

/** Chế độ căn lề breadcrumb */
export type TYPE_MODE_BREADCRUMB = 'center' | 'left' | 'right';

/**
 * Trạng thái hiển thị của bước trong MultiStep:
 * - 'completed': đã hoàn thành (màu xanh lá)
 * - 'selected': đang được chọn (màu brand chính)
 * - 'failed': thất bại (màu đỏ)
 * - 'disabled': vô hiệu hóa (màu xám, không click được)
 * - 'normal': bình thường chưa thực hiện
 */
export type TYPE_MULTI_STEP = 'completed' | 'selected' | 'failed' | 'disabled' | 'normal';

Lưu ý quan trọng

⚠️ FunctionsControl emit trong ngOnInit: (outFunctionControl) phát ngay khi component khởi tạo (ngOnInit). Phải khai báo handler và lưu object vào biến class để sử dụng sau — không nhận được nếu đăng ký quá muộn.

⚠️ stepsMulti là required trong MultiStep: LibsUiComponentsBreadcrumbMultiStepComponent yêu cầu bắt buộc [stepsMulti]. Thiếu prop này sẽ văng lỗi TypeScript tại compile time.

⚠️ Bước disable không phát sự kiện: Bước có disable: true (với ITabBreadCrumb) hoặc status: 'disabled' (với ITabBreadCrumbMultiStep) sẽ không trigger outStepSelected hay outMultiStepSelect.

⚠️ completedIndex dùng model() — Two-way binding: [(completedIndex)] là Angular Signal model(), không phải @Input/@Output truyền thống. Có thể bind hai chiều hoặc chỉ bind một chiều [completedIndex].

⚠️ Auto-scroll trong MultiStep: Truyền [elementRef] (tham chiếu đến container có overflow-x: auto) để component tự động cuộn đến bước đang được chọn khi mount.

Sub-components

LibsUiComponentsBreadcrumbMultiStepComponent

Component con kế thừa từ LibsUiComponentsBreadcrumbComponent, cung cấp kiểu hiển thị breadcrumb dạng pill/tab liền khối thường dùng trong các màn hình phức tạp với nhiều trạng thái (completed, selected, failed, disabled, normal). Mỗi bước có thể là text click hoặc dropdown để chọn sub-item.

import { LibsUiComponentsBreadcrumbMultiStepComponent } from '@libs-ui/components-breadcrumb';
<!-- Selector: libs_ui-components-breadcrumb-multi_step -->
<libs_ui-components-breadcrumb-multi_step
  [stepsMulti]="steps"
  mode="left"
  (outMultiStepSelect)="handlerMultiStepSelect($event)"
/>