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-buttons-group

v0.2.355-15

Published

> Component Button Group cho phép nhóm nhiều button thành một nhóm liền kề với trạng thái active.

Readme

@libs-ui/components-buttons-group

Component Button Group cho phép nhóm nhiều button thành một nhóm liền kề với trạng thái active.

Giới thiệu

LibsUiComponentsButtonsGroupComponent là một standalone Angular component được thiết kế để hiển thị một nhóm các button liền kề nhau. Component hỗ trợ quản lý trạng thái active và cho phép chuyển đổi giữa các button trong nhóm.

Tính năng

  • ✅ Nhóm nhiều button thành một group liền kề
  • ✅ Quản lý trạng thái active với visual feedback rõ ràng
  • ✅ Two-way binding cho index button đang active
  • ✅ Hỗ trợ disable toàn bộ group hoặc từng button
  • ✅ Tích hợp popover cho từng button
  • ✅ Hỗ trợ icon cho button
  • ✅ Tự động xử lý border radius cho button đầu/cuối/giữa
  • ✅ Angular Signals cho tính phản hồi cao
  • ✅ OnPush Change Detection tối ưu hiệu năng

Khi nào sử dụng

  • Khi cần nhóm các button có liên quan với nhau
  • Khi cần toggle giữa các options (như tab buttons)
  • Khi cần hiển thị một nhóm actions liền kề
  • Phù hợp cho filter groups, view switchers, segmented controls

Cài đặt

# npm
npm install @libs-ui/components-buttons-group

# yarn
yarn add @libs-ui/components-buttons-group

Import

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

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

Ví dụ

Basic Usage

<libs_ui-components-buttons-group
  [buttons]="viewButtons"
  [(indexActive)]="activeIndex"
  (outChange)="handleChange($event)" />
viewButtons: IButton[] = [
  { label: 'List View', key: 'list' },
  { label: 'Grid View', key: 'grid' },
  { label: 'Card View', key: 'card' }
];

activeIndex = 0;

handleChange(button: IButton) {
  console.log('Selected:', button);
}

With Icons

<libs_ui-components-buttons-group
  [buttons]="viewButtonsWithIcons"
  [(indexActive)]="activeView" />
viewButtonsWithIcons: IButton[] = [
  {
    label: 'List',
    key: 'list',
    classIconLeft: 'libs-ui-icon-list'
  },
  {
    label: 'Grid',
    key: 'grid',
    classIconLeft: 'libs-ui-icon-grid'
  },
  {
    label: 'Card',
    key: 'card',
    classIconLeft: 'libs-ui-icon-card'
  }
];

activeView = 0;

Icon Only Buttons

<libs_ui-components-buttons-group
  [buttons]="iconOnlyButtons"
  [(indexActive)]="selectedIndex" />
iconOnlyButtons: IButton[] = [
  {
    key: 'bold',
    classIconLeft: 'libs-ui-icon-bold',
    iconOnlyType: true
  },
  {
    key: 'italic',
    classIconLeft: 'libs-ui-icon-italic',
    iconOnlyType: true
  },
  {
    key: 'underline',
    classIconLeft: 'libs-ui-icon-underline',
    iconOnlyType: true
  }
];

With Disabled State

<!-- Disable entire group -->
<libs_ui-components-buttons-group
  [buttons]="buttons"
  [disable]="true"
  [(indexActive)]="activeIndex" />

<!-- Disable specific buttons -->
<libs_ui-components-buttons-group
  [buttons]="buttonsWithDisabled"
  [(indexActive)]="activeIndex" />
buttonsWithDisabled: IButton[] = [
  { label: 'Option 1', key: '1' },
  { label: 'Option 2', key: '2', disable: true },
  { label: 'Option 3', key: '3' }
];

With Popover

<libs_ui-components-buttons-group
  [buttons]="buttonsWithPopover"
  [(indexActive)]="activeIndex"
  (outFunctionsControl)="handlePopoverControl($event)" />
buttonsWithPopover: IButton[] = [
  {
    label: 'Info',
    key: 'info',
    popover: {
      content: 'This is information button',
      mode: 'hover'
    }
  },
  {
    label: 'Warning',
    key: 'warning',
    popover: {
      content: 'This is warning button',
      mode: 'hover'
    }
  }
];

handlePopoverControl(control: IPopoverFunctionControlEvent) {
  console.log('Popover control:', control);
}

Filter Group Example

<libs_ui-components-buttons-group
  [buttons]="filterButtons"
  [(indexActive)]="activeFilter"
  (outChange)="applyFilter($event)" />
filterButtons: IButton[] = [
  { label: 'All', key: 'all' },
  { label: 'Active', key: 'active' },
  { label: 'Completed', key: 'completed' },
  { label: 'Archived', key: 'archived' }
];

activeFilter = 0;

applyFilter(button: IButton) {
  // Apply filter based on button.key
  console.log('Filtering by:', button.key);
}

Custom Styling

<libs_ui-components-buttons-group
  [buttons]="styledButtons"
  [(indexActive)]="activeIndex" />
styledButtons: IButton[] = [
  {
    label: 'Primary',
    key: '1',
    classInclude: 'custom-button-class'
  },
  {
    label: 'Secondary',
    key: '2',
    classInclude: 'custom-button-class'
  }
];

API

libs_ui-components-buttons-group

Inputs

| Property | Type | Default | Description | | ----------------- | ---------------- | -------- | ---------------------------------------------- | | [buttons] | Array<IButton> | required | Danh sách các button trong group | | [(indexActive)] | number | 0 | Index của button đang active (two-way binding) | | [disable] | boolean | false | Disable toàn bộ button group |

Outputs

| Property | Type | Description | | ----------------------- | ------------------------------ | --------------------------------- | | (outChange) | IButton | Emit khi chuyển đổi button active | | (outFunctionsControl) | IPopoverFunctionControlEvent | Emit functions điều khiển popover |

Public Methods

| Method | Description | | ------------------ | --------------------------------------- | | FunctionsControl | Getter để lấy popover control functions |

Types & Interfaces

IButton Interface

Button group sử dụng interface IButton từ @libs-ui/components-buttons-button:

export interface IButton {
  /** Unique key cho button */
  key?: string;

  /** Kiểu button (sẽ được override bởi component) */
  type?: TYPE_BUTTON;

  /** Kích thước button */
  sizeButton?: TYPE_SIZE_BUTTON;

  /** Chỉ hiển thị icon, ẩn label */
  iconOnlyType?: boolean;

  /** Label hiển thị trên button */
  label?: string;

  /** Disable button này */
  disable?: boolean;

  /** Class CSS bổ sung */
  classInclude?: string;

  /** Class icon bên trái */
  classIconLeft?: string;

  /** Class icon bên phải */
  classIconRight?: string;

  /** Class cho label */
  classLabel?: string;

  /** Cấu hình popover */
  popover?: IPopover;

  /** Không stop propagation event */
  ignoreStopPropagationEvent?: boolean;

  /** Z-index cho button */
  zIndex?: number;

  /** Trạng thái pending */
  isPending?: boolean;

  /** Action callback */
  action?: (data?: any) => Promise<void>;

  /** Style cho icon trái */
  styleIconLeft?: Record<string, any>;

  /** Style cho button */
  styleButton?: Record<string, any>;

  /** Custom color (khi type là button-custom) */
  buttonCustom?: IColorButton;
}

TYPE_BUTTON

export type TYPE_BUTTON =
  | 'button-primary'
  | 'button-primary-revert'
  | 'button-secondary'
  | 'button-secondary-red'
  | 'button-outline-secondary'
  | 'button-third'
  | 'button-outline'
  | 'button-danger-high'
  | 'button-outline-hover-danger'
  | 'button-third-hover-danger'
  | 'button-danger-low'
  | 'button-green'
  | 'button-violet'
  | 'button-secondary-green'
  | 'button-outline-green'
  | 'button-custom'
  | 'button-link-primary'
  | 'button-link-third'
  | 'button-link-danger-high'
  | 'button-link-danger-low'
  | 'button-link-green'
  | 'button-link-violet'
  | 'button-link-custom'
  | string;

TYPE_SIZE_BUTTON

export type TYPE_SIZE_BUTTON = 'large' | 'medium' | 'small' | 'smaller';

Styling

Component tự động xử lý styling cho button group:

  • First button: Border radius trái (top-left, bottom-left)
  • Middle buttons: Không có border radius, border-left bị loại bỏ
  • Last button: Border radius phải (top-right, bottom-right), border-left bị loại bỏ
  • Active button: Sử dụng button-primary type
  • Inactive buttons: Sử dụng button-primary-revert type

CSS Variables

Component sử dụng CSS variable:

--libs-ui-button-other-color-border: #226ff5; // Border color cho disabled state

Behavior

Active State Management

  • Khi click vào một button, nó sẽ trở thành active
  • Click vào button đang active sẽ không có effect (không emit event)
  • Index active được quản lý qua two-way binding [(indexActive)]
  • Active button hiển thị với style button-primary
  • Inactive buttons hiển thị với style button-primary-revert

Disable Behavior

  • Khi [disable]="true": Toàn bộ group bị disable
  • Khi button cụ thể có disable: true: Chỉ button đó bị disable
  • Disabled buttons vẫn giữ border styling phù hợp với vị trí trong group

Công nghệ

| Technology | Version | Purpose | | --------------- | ------- | ---------------- | | Angular | 18+ | Framework | | Angular Signals | - | State management | | SCSS | - | Styling | | OnPush | - | Change Detection |

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/buttons/group

Unit Tests

# Chạy tests
npx nx test components-buttons-group

# Coverage
npx nx test components-buttons-group --coverage

# Watch mode
npx nx test components-buttons-group --watch

Dependencies

  • @angular/core: >=18.0.0
  • @libs-ui/components-buttons-button: 0.2.355-14
  • @libs-ui/components-popover: 0.2.355-14
  • @ngx-translate/core: ^15.0.0

Important Notes

⚠️ Type Override

Component tự động override type property của buttons:

  • Active button → button-primary
  • Inactive button → button-primary-revert

Nếu bạn muốn custom type, cần modify component source code.

⚠️ Border Styling

Component sử dụng ::ng-deep để style nested components. Điều này cần thiết để style các button components bên trong nhưng có thể ảnh hưởng đến global styles nếu không cẩn thận.

⚠️ Index-based Active State

Component sử dụng index thay vì key để quản lý active state. Đảm bảo array buttons không thay đổi thứ tự nếu bạn muốn maintain active state.

Best Practices

  1. Sử dụng key duy nhất: Luôn cung cấp key unique cho mỗi button để dễ identify
  2. Limit số lượng buttons: Nên giới hạn 3-5 buttons trong một group để UX tốt
  3. Consistent labels: Sử dụng label ngắn gọn, rõ ràng và có độ dài tương đương
  4. Icon consistency: Nếu dùng icon, nên dùng cho tất cả buttons hoặc không dùng
  5. Responsive design: Cân nhắc sử dụng icon-only mode trên mobile

Troubleshooting

Button không chuyển active state

  • Kiểm tra [(indexActive)] binding
  • Đảm bảo không có logic nào block event handler
  • Verify button không bị disable

Border styling không đúng

  • Kiểm tra ViewEncapsulation của parent component
  • Verify CSS variables được define
  • Check xem có CSS conflicts không

Popover không hoạt động

  • Đảm bảo đã import @libs-ui/components-popover
  • Verify popover config đúng format
  • Check z-index conflicts

License

MIT