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

@pecb-ui/components

v1.2.0

Published

Professional Angular UI Components Library with TypeScript and SCSS by PECB

Downloads

318

Readme

@pecb-ui/components

A professional Angular 17 UI components library built with TypeScript and SCSS. Features Storybook for component development and documentation, full accessibility compliance (WCAG 2.1 AA), and tree-shakeable, AOT-compatible builds.

npm version Angular License: MIT

Features

  • 🎯 Angular 17.3+ - Built with the latest Angular features
  • 📦 APF Compliant - Angular Package Format for maximum compatibility
  • 🌳 Tree-shakeable - Only import what you use
  • AOT Compatible - Optimized for Ahead-of-Time compilation
  • WCAG 2.1 AA - Full accessibility compliance
  • 🎨 SCSS Design System - Professional variables, mixins, and utilities
  • 📚 Storybook - Interactive component documentation
  • 🔒 Strict TypeScript - Full type safety

Installation

From npm (recommended)

npm install @pecb-ui/components

From local package

npm install /path/to/dist/ui-components/pecb-ui-components-1.0.0.tgz

Peer Dependencies

This library requires the following peer dependencies:

{
  "@angular/common": "^17.3.0",
  "@angular/core": "^17.3.0",
  "@angular/animations": "^17.3.0"
}

Quick Start

1. Import the Module

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { PecbComponentsModule } from '@pecb-ui/components';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    PecbComponentsModule  // Import the PECB UI components module
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

2. Import Global Styles (Optional)

If you want to use the PECB design system variables in your application:

// styles.scss
@import '@pecb-ui/components/styles/main';

Or import specific abstracts:

// In your component SCSS
@import '@pecb-ui/components/styles/abstracts/variables';
@import '@pecb-ui/components/styles/abstracts/mixins';

.my-component {
  color: $primary-color;
  padding: $spacing-md;
  @include elevation(2);
}

3. Use Components

<!-- app.component.html -->
<pecb-button variant="primary" size="medium" (clicked)="handleClick()">
  Click Me
</pecb-button>

<pecb-card elevation="md">
  <pecb-card-header>
    <h3>Welcome</h3>
  </pecb-card-header>
  <pecb-card-body>
    <p>Your content goes here</p>
  </pecb-card-body>
</pecb-card>

Components

Button Component

A versatile button component with multiple variants, sizes, and accessibility features.

<!-- Basic button -->
<pecb-button variant="primary" (clicked)="onClick()">
  Submit
</pecb-button>

<!-- With loading state -->
<pecb-button variant="primary" [loading]="isLoading">
  Save
</pecb-button>

<!-- Disabled button -->
<pecb-button variant="danger" [disabled]="true">
  Delete
</pecb-button>

<!-- Full width button -->
<pecb-button variant="success" [fullWidth]="true">
  Continue
</pecb-button>

<!-- Icon button with accessibility label -->
<pecb-button variant="secondary" ariaLabel="Close dialog" iconLeft="✕">
</pecb-button>

<!-- Toggle button -->
<pecb-button variant="secondary" [ariaPressed]="isActive" (clicked)="toggle()">
  Toggle
</pecb-button>

<!-- Button that controls a dropdown -->
<pecb-button
  variant="primary"
  [ariaExpanded]="isOpen"
  ariaHasPopup="menu"
  ariaControls="dropdown-menu"
  (clicked)="toggleDropdown()">
  Menu
</pecb-button>

Properties:

| Property | Type | Default | Description | |----------|------|---------|-------------| | variant | 'primary' \| 'secondary' \| 'success' \| 'danger' \| 'warning' \| 'info' \| 'text' | 'primary' | Visual style variant | | size | 'small' \| 'medium' \| 'large' | 'medium' | Button size | | disabled | boolean | false | Disable the button | | loading | boolean | false | Show loading spinner | | fullWidth | boolean | false | Make button full width | | type | 'button' \| 'submit' \| 'reset' | 'button' | HTML button type | | iconLeft | string | - | Icon before text | | iconRight | string | - | Icon after text | | ariaLabel | string | - | Accessible label | | ariaExpanded | boolean | - | ARIA expanded state | | ariaPressed | boolean | - | ARIA pressed state (toggle buttons) | | ariaHasPopup | boolean \| 'menu' \| 'listbox' \| 'tree' \| 'grid' \| 'dialog' | - | Popup type | | ariaControls | string | - | ID of controlled element |

Events:

| Event | Type | Description | |-------|------|-------------| | clicked | EventEmitter<MouseEvent> | Emitted on button click |

Card Component

A container component for displaying content with optional header, body, and footer sections.

<!-- Basic card -->
<pecb-card elevation="md">
  <pecb-card-header>
    <h3>Card Title</h3>
  </pecb-card-header>
  <pecb-card-body>
    <p>Card content goes here</p>
  </pecb-card-body>
  <pecb-card-footer>
    <pecb-button variant="primary">Action</pecb-button>
  </pecb-card-footer>
</pecb-card>

<!-- Hoverable card -->
<pecb-card elevation="sm" [hoverable]="true">
  <pecb-card-body>
    <p>Hover over me!</p>
  </pecb-card-body>
</pecb-card>

<!-- Card as article (accessible) -->
<pecb-card role="article" ariaLabelledBy="article-title">
  <pecb-card-header>
    <h2 id="article-title">Article Headline</h2>
  </pecb-card-header>
  <pecb-card-body>
    <p>Article content...</p>
  </pecb-card-body>
</pecb-card>

<!-- Card as region -->
<pecb-card role="region" ariaLabel="Product Information">
  <pecb-card-body>
    <p>Product details...</p>
  </pecb-card-body>
</pecb-card>

Properties:

| Property | Type | Default | Description | |----------|------|---------|-------------| | elevation | 'none' \| 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Shadow depth | | hoverable | boolean | false | Enable hover effect | | noPadding | boolean | false | Remove default padding | | role | 'article' \| 'region' \| 'group' \| 'listitem' \| 'none' | 'none' | Semantic role | | ariaLabel | string | - | Accessible label | | ariaLabelledBy | string | - | ID of labelling element | | ariaDescribedBy | string | - | ID of describing element |

Services

NotificationService

A stateless, injectable service for displaying toast notifications.

import { NotificationService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  constructor(private notificationService: NotificationService) {}

  showSuccess(): void {
    this.notificationService.success('Operation completed successfully!');
  }

  showError(): void {
    this.notificationService.error('An error occurred', 'Error');
  }

  showWarning(): void {
    this.notificationService.warning('Please review your input', 'Warning');
  }

  showInfo(): void {
    this.notificationService.info('New updates available');
  }

  showCustom(): void {
    this.notificationService.show({
      message: 'Custom notification',
      type: 'info',
      duration: 10000,
      position: 'bottom-right',
      dismissible: true
    });
  }
}

ThemeService

A stateless, injectable service for managing application themes.

import { ThemeService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  isDarkMode$ = this.themeService.theme$.pipe(
    map(config => config.resolvedTheme === 'dark')
  );

  constructor(private themeService: ThemeService) {}

  toggleTheme(): void {
    this.themeService.toggleTheme();
  }

  setDarkMode(): void {
    this.themeService.setTheme('dark');
  }

  useSystemPreference(): void {
    this.themeService.useSystemTheme();
  }

  setCustomColors(): void {
    this.themeService.setCustomVariables({
      primaryColor: '#007bff',
      backgroundColor: '#f8f9fa'
    });
  }
}

LoadingService

A stateless, injectable service for managing loading states.

import { LoadingService } from '@pecb-ui/components';

@Component({...})
export class MyComponent {
  isLoading$ = this.loadingService.isLoading$('data-fetch');

  constructor(private loadingService: LoadingService) {}

  async loadData(): Promise<void> {
    this.loadingService.start('data-fetch', 'Loading data...');
    try {
      const data = await this.fetchData();
      // Process data
    } finally {
      this.loadingService.stop('data-fetch');
    }
  }

  // Or use the helper method
  async loadDataAlt(): Promise<void> {
    const data = await this.loadingService.withLoading(
      'data-fetch',
      () => this.fetchData(),
      'Loading data...'
    );
  }
}

Utilities

The library exports utility functions for common operations:

import {
  // String utilities
  toKebabCase,
  toCamelCase,
  truncate,
  slugify,

  // DOM utilities
  generateUniqueId,
  getFocusableElements,
  trapFocus,
  copyToClipboard,

  // Accessibility utilities
  announceToScreenReader,
  getButtonAriaAttributes,
  prefersReducedMotion,

  // Error handling
  createError,
  wrapError,
  tryAsync
} from '@pecb-ui/components';

Types & Interfaces

import {
  // Common types
  Size,
  ComponentSize,
  ColorVariant,
  Position,

  // Component interfaces
  Disableable,
  Loadable,
  Focusable,
  SelectableItem,
  MenuItem,

  // Service interfaces
  NotificationConfig,
  ThemeConfig,
  LoadingState
} from '@pecb-ui/components';

SCSS Design System

Variables

// Colors
$primary-color: #1976d2;
$accent-color: #ff4081;
$success-color: #4caf50;
$warn-color: #f44336;
$info-color: #2196f3;

// Spacing (8px base unit)
$spacing-xs: 4px;
$spacing-sm: 8px;
$spacing-md: 16px;
$spacing-lg: 24px;
$spacing-xl: 32px;

// Typography
$font-family-base: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
$font-size-sm: 0.875rem;
$font-size-md: 1rem;
$font-size-lg: 1.125rem;

// Border radius
$border-radius-sm: 4px;
$border-radius-md: 8px;
$border-radius-lg: 12px;

Mixins

// Responsive breakpoints
@include respond-to('md') {
  // Styles for medium screens and up
}

// Flexbox utilities
@include flex-center;
@include flex-between;

// Elevation (shadows)
@include elevation(2);

// Focus visible
@include focus-visible {
  outline: 2px solid $primary-color;
}

// Transitions
@include transition(background-color, color);

Development

Prerequisites

  • Node.js 18+
  • npm 9+
  • Angular CLI 17.3+

Setup

# Clone the repository
git clone https://github.com/pecb-ui/components.git
cd components

# Install dependencies
npm install

# Build the library
npm run build

# Run Storybook
npm run storybook

# Run tests
npm test

Building

# Development build
npm run build

# Production build
npm run build:prod

# Create npm package
npm run publish:lib

Testing

# Run tests in watch mode
npm test

# Run tests once with coverage
npm run test:ci

Storybook

# Start Storybook dev server
npm run storybook

# Build Storybook for deployment
npm run build-storybook

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

Roadmap

Planned components:

  • Input/Form controls
  • Modal/Dialog
  • Dropdown/Select
  • Tabs
  • Accordion
  • Table
  • Pagination
  • Badge
  • Avatar
  • Tooltip
  • Alert/Toast
  • Progress indicators
  • Date picker

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes using Conventional Commits
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

MIT License - see the LICENSE file for details.

Support

For issues and questions, please use the GitHub issue tracker.