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-label

v0.2.357-9

Published

> Component nhãn đa năng hỗ trợ tooltip, toggle switch, nút thao tác, bộ đếm ký tự và văn bản mô tả — dùng làm header cho các trường nhập liệu trong form.

Downloads

3,808

Readme

@libs-ui/components-label

Component nhãn đa năng hỗ trợ tooltip, toggle switch, nút thao tác, bộ đếm ký tự và văn bản mô tả — dùng làm header cho các trường nhập liệu trong form.

Giới thiệu

@libs-ui/components-label là component nhãn (label) linh hoạt dùng để trang trí tiêu đề cho các ô nhập liệu, form field hoặc nhóm nội dung. Nó hỗ trợ hiển thị nhãn trái/phải, đánh dấu bắt buộc (dấu sao đỏ), tooltip hướng dẫn, tích hợp toggle switch, thêm nút thao tác nhanh (trái/phải/mô tả), và bộ đếm ký tự theo giới hạn. Toàn bộ văn bản hỗ trợ đa ngôn ngữ qua TranslateModule.

Tính năng

  • ✅ Hiển thị nhãn bên trái (labelLeft) và nhãn bên phải (labelRight) đồng thời
  • ✅ Đánh dấu trường bắt buộc bằng dấu sao đỏ (required)
  • ✅ Tooltip hướng dẫn tích hợp sẵn qua popover với icon tùy chỉnh
  • ✅ Tích hợp Toggle Switch (hasToggle) với vị trí linh hoạt (trước hoặc sau nhãn)
  • ✅ Thêm mảng nút bấm (IButton[]) ở vùng trái, phải hoặc vùng mô tả
  • ✅ Văn bản mô tả phụ (description) hiển thị bên dưới nhãn chính
  • ✅ Bộ đếm ký tự (count / limitLength) dùng cho textarea, rich text editor
  • ✅ Hỗ trợ đa ngôn ngữ qua TranslateModule (i18n key)
  • ✅ Standalone component, OnPush, Angular Signals

Khi nào sử dụng

  • Làm nhãn tiêu đề cho Input, Select, Textarea, DatePicker trong form
  • Cần hiển thị tooltip hướng dẫn đính kèm nhãn (icon ? hover)
  • Cần thanh tiêu đề có nút thao tác nhanh (thêm mới, chỉnh sửa, cài đặt)
  • Hiển thị cài đặt bật/tắt kèm mô tả chi tiết (Toggle + Description)
  • Hiển thị bộ đếm ký tự còn lại cho ô nhập liệu có giới hạn độ dài

Cài đặt

npm install @libs-ui/components-label

Import

import { LibsUiComponentsLabelComponent } from '@libs-ui/components-label';
import { ILabel } from '@libs-ui/components-label';

@Component({
  standalone: true,
  imports: [LibsUiComponentsLabelComponent],
})
export class MyFormComponent {}

Ví dụ sử dụng

1. Nhãn cơ bản với dấu bắt buộc và tooltip

<libs_ui-components-label
  [labelLeft]="'Họ và tên'"
  [required]="true"
  [popover]="{ config: { content: 'Vui lòng nhập đầy đủ họ tên như trong giấy khai sinh.' } }">
</libs_ui-components-label>

2. Nhãn tích hợp nút thao tác nhanh

import { Component } from '@angular/core';
import { LibsUiComponentsLabelComponent } from '@libs-ui/components-label';
import { IButton } from '@libs-ui/components-buttons-button';

@Component({
  standalone: true,
  imports: [LibsUiComponentsLabelComponent],
  template: `
    <libs_ui-components-label
      [labelLeft]="'Danh sách thành viên'"
      [buttonsRight]="buttonsRight"
      (outClickButton)="handlerClickButton($event)">
    </libs_ui-components-label>
  `,
})
export class TeamSectionComponent {
  protected buttonsRight: IButton[] = [
    { classIconLeft: 'libs-ui-icon-add', key: 'add', popover: { dataView: 'Thêm mới' } },
    { classIconLeft: 'libs-ui-icon-arrange', key: 'settings', popover: { dataView: 'Cài đặt' } },
  ];

  protected handlerClickButton(button: IButton): void {
    button.action?.(button);
  }
}

3. Nhãn tích hợp Toggle Switch và mô tả

import { Component, signal } from '@angular/core';
import { LibsUiComponentsLabelComponent } from '@libs-ui/components-label';
import { ISwitchEvent } from '@libs-ui/components-switch';

@Component({
  standalone: true,
  imports: [LibsUiComponentsLabelComponent],
  template: `
    <libs_ui-components-label
      [labelLeft]="'Chế độ bảo mật 2 lớp'"
      [hasToggle]="true"
      [toggleActive]="securityEnabled()"
      [description]="'Khi bật, ứng dụng yêu cầu xác thực OTP mỗi lần đăng nhập.'"
      (outSwitchEvent)="handlerToggle($event)">
    </libs_ui-components-label>
  `,
})
export class SecuritySettingComponent {
  protected securityEnabled = signal(false);

  protected handlerToggle(event: ISwitchEvent): void {
    this.securityEnabled.set(event.active);
  }
}

4. Nhãn với bộ đếm ký tự

import { Component, signal } from '@angular/core';
import { LibsUiComponentsLabelComponent } from '@libs-ui/components-label';

@Component({
  standalone: true,
  imports: [LibsUiComponentsLabelComponent],
  template: `
    <libs_ui-components-label
      [labelLeft]="'Mô tả bản thân'"
      [count]="charCount()"
      [limitLength]="200">
    </libs_ui-components-label>
    <textarea (input)="handlerTextareaInput($event)" maxlength="200"></textarea>
  `,
})
export class BioFieldComponent {
  protected charCount = signal(0);

  protected handlerTextareaInput(event: Event): void {
    event.stopPropagation();
    const target = event.target as HTMLTextAreaElement;
    this.charCount.set(target.value.length);
  }
}

5. Nhãn trái/phải với toggle trước nhãn

<libs_ui-components-label
  [labelLeft]="'Nhận thông báo email'"
  [labelRight]="'Tùy chỉnh'"
  [hasToggle]="true"
  [labelLeftBehindToggleButton]="true"
  [toggleActive]="true"
  [toggleSize]="'large'"
  (outSwitchEvent)="handlerToggle($event)"
  (outLabelRightClick)="handlerLabelRightClick($event)">
</libs_ui-components-label>

6. Sử dụng với interface ILabel (truyền config dạng object)

import { ILabel } from '@libs-ui/components-label';
import { IButton } from '@libs-ui/components-buttons-button';

const labelConfig: ILabel = {
  labelLeft: 'Số điện thoại',
  required: true,
  description: 'Nhập số điện thoại có mã quốc gia, ví dụ: +84901234567',
  buttonsRight: [
    { key: 'verify', label: 'Xác minh', type: 'button-link-primary' },
  ],
};
<libs_ui-components-label
  [labelLeft]="labelConfig.labelLeft"
  [required]="labelConfig.required"
  [description]="labelConfig.description"
  [buttonsRight]="labelConfig.buttonsRight">
</libs_ui-components-label>

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | buttonsDescription | IButton[] | [] | Danh sách nút bấm hiển thị vùng mô tả bên dưới nhãn | [buttonsDescription]="[{ key: 'add', label: 'Thêm' }]" | | buttonsDescriptionContainerClass | string | 'flex libs-ui-label-description-button' | Class CSS container bọc ngoài nhóm nút mô tả | [buttonsDescriptionContainerClass]="'flex gap-2'" | | buttonsLeft | IButton[] | [] | Danh sách nút bấm hiển thị vùng trái (sau nhãn left) | [buttonsLeft]="[{ classIconLeft: 'libs-ui-icon-add', key: 'add' }]" | | buttonsRight | IButton[] | [] | Danh sách nút bấm hiển thị vùng phải | [buttonsRight]="[{ classIconLeft: 'libs-ui-icon-edit-line', key: 'edit' }]" | | classInclude | string | 'libs-ui-label' | Class CSS bổ sung cho wrapper ngoài cùng của component | [classInclude]="'my-custom-label'" | | count | number | 0 | Số ký tự hiện tại để hiển thị trên bộ đếm | [count]="charCount()" | | description | string | undefined | Văn bản mô tả phụ hiển thị bên dưới nhãn chính (hỗ trợ i18n key) | [description]="'i18n_field_hint'" | | descriptionClass | string | 'libs-ui-label-description libs-ui-font-h5r' | Class CSS bổ sung cho vùng mô tả | [descriptionClass]="'text-orange-500'" | | disableButtonsDescription | boolean | undefined | Vô hiệu hóa tất cả nút trong vùng mô tả | [disableButtonsDescription]="isReadonly()" | | disableButtonsLeft | boolean | undefined | Vô hiệu hóa tất cả nút bên trái | [disableButtonsLeft]="isReadonly()" | | disableButtonsRight | boolean | undefined | Vô hiệu hóa tất cả nút bên phải | [disableButtonsRight]="isReadonly()" | | hasToggle | boolean | undefined | Hiển thị toggle switch trong nhãn | [hasToggle]="true" | | iconPopoverClass | string | 'libs-ui-icon-tooltip-outline' | Class CSS của icon tooltip (hiển thị khi có popover) | [iconPopoverClass]="'libs-ui-icon-tooltip-outline'" | | labelLeft | string | undefined | Văn bản nhãn bên trái (hỗ trợ i18n key) | [labelLeft]="'i18n_field_name'" | | labelLeftBehindToggleButton | boolean | undefined | Khi true, toggle switch hiển thị trước nhãn trái; khi false/undefined, toggle ở sau | [labelLeftBehindToggleButton]="true" | | labelLeftClass | string | 'libs-ui-label-left-text libs-ui-font-h6m' | Class CSS bổ sung cho text nhãn trái | [labelLeftClass]="'text-blue-600'" | | labelRight | string | undefined | Văn bản nhãn bên phải, có thể click (hỗ trợ i18n key) | [labelRight]="'Tùy chỉnh'" | | labelRightClass | string | '' | Class CSS bổ sung cho text nhãn phải | [labelRightClass]="'text-blue-500 cursor-pointer'" | | labelRightRequired | string | undefined | Text hiển thị bắt buộc vùng phải (thay thế dấu *) | [labelRightRequired]="'(Bắt buộc)'" | | limitLength | number | 0 | Giới hạn ký tự tối đa — khi > 0 hiển thị dạng count/limitLength | [limitLength]="200" | | onlyShowCount | boolean | undefined | Khi true, chỉ hiển thị số đếm hiện tại (không hiển thị giới hạn) | [onlyShowCount]="true" | | popover | IPopover | undefined | Cấu hình tooltip hiển thị khi hover vào icon | [popover]="{ config: { content: 'Hướng dẫn nhập liệu' } }" | | required | boolean | undefined | Hiển thị dấu sao đỏ * đánh dấu trường bắt buộc | [required]="true" | | timerDestroyPopover | number | 0 | Thời gian (ms) sau đó popover tự đóng (0 = không tự đóng) | [timerDestroyPopover]="3000" | | toggleActive | boolean | undefined | Trạng thái bật/tắt của toggle switch | [toggleActive]="isEnabled()" | | toggleDisable | boolean | undefined | Vô hiệu hóa toggle switch | [toggleDisable]="isReadonly()" | | toggleSize | 'default' \| 'large' | 'default' | Kích thước toggle switch | [toggleSize]="'large'" | | zIndexPopover | number | 10 | z-index của popover (tăng khi bị che bởi các lớp khác) | [zIndexPopover]="100" |

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outClickButton) | IButton | Phát ra khi click vào bất kỳ nút nào (trái, phải hoặc mô tả) trong component | handlerClickButton(button: IButton): void { button.action?.(button); } | (outClickButton)="handlerClickButton($event)" | | (outLabelLeftClick) | MouseEvent | Phát ra khi click vào vùng nhãn trái | handlerLabelLeftClick(event: MouseEvent): void { event.stopPropagation(); } | (outLabelLeftClick)="handlerLabelLeftClick($event)" | | (outLabelRightClick) | boolean | Phát ra true khi click vào nhãn phải | handlerLabelRightClick(clicked: boolean): void { } | (outLabelRightClick)="handlerLabelRightClick($event)" | | (outSwitchEvent) | ISwitchEvent | Phát ra khi trạng thái toggle switch thay đổi | handlerToggle(event: ISwitchEvent): void { this.isEnabled.set(event.active); } | (outSwitchEvent)="handlerToggle($event)" |

Types & Interfaces

import { ILabel } from '@libs-ui/components-label';

ILabel

Interface dùng để xây dựng object cấu hình cho component, thuận tiện khi cần truyền config từ TS thay vì bind từng input riêng lẻ.

import { ILabel } from '@libs-ui/components-label';
import { IButton } from '@libs-ui/components-buttons-button';
import { IPopover } from '@libs-ui/components-popover';

interface ILabel {
  classInclude?: string;

  labelLeft?: string;
  labelLeftClass?: string;
  labelLeftBehindToggleButton?: boolean;

  popover?: IPopover;
  iconPopoverClass?: string;
  zIndexPopover?: number;
  timerDestroyPopover?: number;

  required?: boolean;

  buttonsLeft?: IButton[];
  disableButtonsLeft?: boolean;

  buttonsRight?: IButton[];
  disableButtonsRight?: boolean;

  labelRight?: string;
  labelRightClass?: string;
  labelRightRequired?: string;

  hasToggle?: boolean;
  toggleActive?: boolean;
  toggleDisable?: boolean;
  toggleSize?: 'default' | 'large';

  description?: string;
  descriptionClass?: string;

  buttonsDescription?: IButton[];
  disableButtonsDescription?: boolean;
  buttonsDescriptionContainerClass?: string;

  onlyShowCount?: boolean;
  limitLength?: number;
  count?: number;
}

ISwitchEvent (từ @libs-ui/components-switch)

import { ISwitchEvent } from '@libs-ui/components-switch';

// ISwitchEvent chứa ít nhất:
// { active: boolean }

IButton (từ @libs-ui/components-buttons-button)

import { IButton } from '@libs-ui/components-buttons-button';

// Các field thường dùng:
// {
//   key?: string;
//   label?: string;
//   type?: string;        // 'button-link-primary' | 'button-primary' | ...
//   classIconLeft?: string;
//   classIconRight?: string;
//   classInclude?: string;
//   classLabel?: string;
//   sizeButton?: string;
//   disable?: boolean;
//   popover?: object;
//   action?: (button: IButton) => void;
// }

Custom Description Slot

Component hỗ trợ ng-content projection với selector div.libs-ui-custom-description để inject nội dung tùy chỉnh bên dưới nhãn:

<libs_ui-components-label [labelLeft]="'Tệp đính kèm'">
  <div class="libs-ui-custom-description">
    <span class="text-gray-400 libs-ui-font-h7r">Hỗ trợ PDF, DOCX, tối đa 10MB</span>
  </div>
</libs_ui-components-label>

Lưu ý quan trọng

⚠️ Bộ đếm ký tự: Để bộ đếm hoạt động, cần truyền cả [count][limitLength]. Nếu chỉ muốn hiển thị số đếm mà không giới hạn, dùng [onlyShowCount]="true" kết hợp [count].

⚠️ Toggle switch và vị trí nhãn: Khi [labelLeftBehindToggleButton]="true", toggle xuất hiện ở bên trái nhãn. Khi false hoặc không truyền, toggle xuất hiện ở bên phải nhãn.

⚠️ Nhãn phải và giới hạn chiều rộng: Khi có labelRight, limitLength hoặc onlyShowCount, vùng nhãn trái (libs-ui-label-left) tự động co xuống maxWidth: 70% để dành chỗ cho vùng phải.

⚠️ i18n: Tất cả labelLeft, labelRight, description đều được pipe translate tự động — có thể truyền i18n key trực tiếp hoặc text thường.

⚠️ Custom description content: Chỉ nội dung trong <div class="libs-ui-custom-description"> mới được inject qua ng-content. Các tag khác sẽ bị bỏ qua.