@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.
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/componentsFrom local package
npm install /path/to/dist/ui-components/pecb-ui-components-1.0.0.tgzPeer 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 testBuilding
# Development build
npm run build
# Production build
npm run build:prod
# Create npm package
npm run publish:libTesting
# Run tests in watch mode
npm test
# Run tests once with coverage
npm run test:ciStorybook
# Start Storybook dev server
npm run storybook
# Build Storybook for deployment
npm run build-storybookBrowser 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
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes using Conventional Commits
- Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see the LICENSE file for details.
Support
For issues and questions, please use the GitHub issue tracker.
