1. Introduction
In modern frontend development, component libraries play a vital role in creating consistent, reusable, and maintainable UI elements across applications.
When working in large-scale enterprise projects with multiple Angular applications, you often need a shared library containing pre-built UI components — like buttons, tables, modals, and input fields — that follow the same design language.
Angular provides an excellent foundation for this through its Component Dev Kit (CDK). Combined with Storybook, developers can visually document, test, and share reusable UI components effectively.
This article will guide you step-by-step through creating a scalable component library using Angular CDK + Storybook, with explanations, best practices, and technical workflows.
2. Why Create a Component Library?
Building a component library provides several advantages:
| Benefit | Description |
|---|
| Reusability | Share common UI components across multiple Angular projects. |
| Consistency | Uniform UI elements across products and teams. |
| Scalability | Add or upgrade components without affecting app stability. |
| Documentation | Storybook provides interactive documentation for designers and developers. |
| Faster Development | Less duplication, better collaboration between teams. |
3. Understanding the Angular CDK
Angular CDK (Component Dev Kit) is part of the Angular Material library, but it is independent of Material UI.
It provides low-level tools to build custom UI components with consistent accessibility and behavior.
Common Angular CDK Features
| Module | Purpose |
|---|
@angular/cdk/overlay | For tooltips, dropdowns, and dialogs |
@angular/cdk/drag-drop | Drag and drop utilities |
@angular/cdk/portal | Dynamic content rendering |
@angular/cdk/a11y | Accessibility utilities |
@angular/cdk/layout | Responsive breakpoints |
@angular/cdk/scrolling | Virtual scrolling |
In this guide, we’ll use Angular CDK for building custom interactive UI components.
4. Project Setup
Step 1: Create a New Angular Workspace
ng new shared-ui --create-application falsecd shared-ui
This command creates a workspace without a root application — ideal for library development.
Step 2: Generate a Library
ng generate library ui-components
This creates a new library under projects/ui-components.
Structure
shared-ui/
├── projects/
│ └── ui-components/
│ ├── src/
│ │ ├── lib/
│ │ ├── public-api.ts
│ │ └── package.json
└── angular.json
5. Adding Angular CDK
Install Angular CDK
npm install @angular/cdk
6. Building the First Component Using Angular CDK
Let’s build a Custom Tooltip Component using the Angular CDK Overlay module.
Step 1: Create a Tooltip Component
ng generate component tooltip --project=ui-components
Step 2: Implement Tooltip Logic
tooltip.component.ts
import { Component, Input, ElementRef, HostListener } from '@angular/core';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { TooltipOverlayComponent } from './tooltip-overlay.component';
@Component({
selector: 'lib-tooltip',
template: `<ng-content></ng-content>`
})
export class TooltipComponent {
@Input() message = '';
private overlayRef: OverlayRef | null = null;
constructor(private overlay: Overlay, private elementRef: ElementRef) {}
@HostListener('mouseenter')
show() {
const positionStrategy = this.overlay.position()
.flexibleConnectedTo(this.elementRef)
.withPositions([{ originX: 'center', overlayX: 'center', originY: 'top', overlayY: 'bottom' }]);
this.overlayRef = this.overlay.create({ positionStrategy });
const tooltipPortal = new ComponentPortal(TooltipOverlayComponent);
const tooltipRef = this.overlayRef.attach(tooltipPortal);
tooltipRef.instance.message = this.message;
}
@HostListener('mouseleave')
hide() {
this.overlayRef?.dispose();
}
}
tooltip-overlay.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'lib-tooltip-overlay',
template: `<div class="tooltip">{{ message }}</div>`,
styles: [`
.tooltip {
background: #333;
color: white;
padding: 6px 10px;
border-radius: 4px;
font-size: 12px;
}
`]
})
export class TooltipOverlayComponent {
@Input() message = '';
}
public-api.ts
export * from './lib/tooltip/tooltip.component';
export * from './lib/tooltip/tooltip-overlay.component';
Now you have a working tooltip component powered by Angular CDK overlays.
7. Integrating Storybook
Step 1: Install Storybook
npx storybook init
Select Angular when prompted.
This creates a .storybook/ folder and some example stories.
8. Add the Library to Storybook
Modify .storybook/main.js:
module.exports = {
stories: [
'../projects/ui-components/**/*.stories.@(js|ts)',
],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/angular',
options: {},
},
};
9. Create a Story for Tooltip Component
In projects/ui-components/src/lib/tooltip/tooltip.stories.ts:
import { Meta, StoryObj } from '@storybook/angular';
import { TooltipComponent } from './tooltip.component';
import { TooltipOverlayComponent } from './tooltip-overlay.component';
const meta: Meta<TooltipComponent> = {
title: 'Components/Tooltip',
component: TooltipComponent,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<TooltipComponent>;
export const Basic: Story = {
args: {
message: 'This is a custom tooltip built with Angular CDK!',
},
template: `
<lib-tooltip message="This is a tooltip">
<button>Hover Me</button>
</lib-tooltip>
`
};
Now run:
npm run storybook
You’ll see a live preview of your Tooltip component in Storybook.
10. Adding More Components
You can now create and document more reusable components like:
Modal Dialog (CDK Overlay)
Drag-Drop Panel (CDK DragDrop)
Responsive Grid (CDK Layout)
Virtual Scroll Table (CDK Scrolling)
Each component gets its own folder, logic, and Storybook documentation.
11. Component Workflow Diagram
┌───────────────────────────┐
│ Angular CDK Utilities │
│ (Overlay, DragDrop, etc.) │
└──────────┬────────────────┘
│
▼
┌────────────────────────┐
│ Custom UI Components │
│ (Tooltip, Modal, Grid) │
└──────────┬─────────────┘
│
▼
┌────────────────────────┐
│ Component Library (Lib)│
│ projects/ui-components│
└──────────┬─────────────┘
│
▼
┌────────────────────────┐
│ Storybook Documentation│
│ Visual + Code Samples │
└──────────┬─────────────┘
│
▼
┌────────────────────────┐
│ Published npm Package │
│ or Shared via Git Repo │
└────────────────────────┘
12. Publishing the Library
To use your component library in other Angular apps, publish it as an npm package.
Step 1: Build the Library
ng build ui-components
Step 2: Publish to npm (optional)
cd dist/ui-components
npm publish --access public
Step 3: Install in Other Projects
npm install ui-components
And then:
import { UiComponentsModule } from 'ui-components';
13. Theming and Customization
For professional libraries, you should add theming support.
Use SCSS variables or CSS custom properties:
:root {
--primary-color: #007bff;
--font-family: 'Roboto', sans-serif;
}
Each component should use these theme tokens so you can easily switch between light/dark or brand-specific themes.
14. Storybook Add-ons
Storybook supports powerful add-ons that improve developer productivity:
| Add-on | Purpose |
|---|
@storybook/addon-essentials | Docs, controls, and viewport tools |
@storybook/addon-a11y | Accessibility checks |
@storybook/addon-interactions | Test component interactions |
storybook-addon-designs | Embed Figma design previews |
@storybook/addon-jest | Display unit test results in stories |
Example: Add Docs tab for live documentation.
15. Best Practices for Component Library Design
| Practice | Description |
|---|
| Use Angular CDK over Material | Gives flexibility to design your own UI style. |
| Follow Atomic Design | Build components as atoms, molecules, and organisms. |
| Strict Type Safety | Use strong typings and input validation. |
| Include Accessibility (a11y) | Make components keyboard and screen-reader friendly. |
| Document Every Component in Storybook | Clear usage and visual representation. |
| Version Control Your Library | Follow Semantic Versioning (SemVer). |
16. Versioning and CI/CD Integration
You can automate component library builds and publishing using Jenkins or GitHub Actions.
Sample GitHub Action Workflow
name: Build and Publish Libraryon:push:
branches:
- main
jobs:build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: ng build ui-components
- run: npm publish dist/ui-components --access public
This ensures automatic publishing whenever you merge into main.
17. Benefits of Using Storybook with Angular CDK
Visual Testing: Quickly test UI states without running the app.
Design Collaboration: Share stories with designers via Storybook Cloud.
Component Isolation: Debug one component without dependencies.
Automatic Documentation: Generate component usage docs.
Cross-Team Reuse: Use the same library in multiple Angular projects.
18. Real-World Use Case
Imagine a company with multiple Angular apps — Admin Dashboard, Customer Portal, and Internal Tools.
Without a shared library:
Teams duplicate buttons, forms, and UI patterns.
Inconsistent colors and UX.
Hard to apply global changes.
With a component library:
Common UI is centralized.
Changes (like color or typography) propagate instantly.
Faster development and consistent UX.
19. Future Enhancements
Add Unit Testing using Jest.
Integrate Chromatic for visual regression testing.
Add Accessibility Testing with @storybook/addon-a11y.
Integrate with Figma Tokens for real design-to-code workflows.
Use Nx Workspace for scalable monorepo architecture.
20. Conclusion
By combining Angular CDK and Storybook, developers can build a powerful, flexible, and documented component library.
This approach not only boosts productivity but also ensures consistency across multiple Angular projects.
Angular CDK provides the building blocks, and Storybook makes those components discoverable and testable.