Angular  

Building a Component Library Using Angular CDK and Storybook

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:

BenefitDescription
ReusabilityShare common UI components across multiple Angular projects.
ConsistencyUniform UI elements across products and teams.
ScalabilityAdd or upgrade components without affecting app stability.
DocumentationStorybook provides interactive documentation for designers and developers.
Faster DevelopmentLess 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

ModulePurpose
@angular/cdk/overlayFor tooltips, dropdowns, and dialogs
@angular/cdk/drag-dropDrag and drop utilities
@angular/cdk/portalDynamic content rendering
@angular/cdk/a11yAccessibility utilities
@angular/cdk/layoutResponsive breakpoints
@angular/cdk/scrollingVirtual 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-onPurpose
@storybook/addon-essentialsDocs, controls, and viewport tools
@storybook/addon-a11yAccessibility checks
@storybook/addon-interactionsTest component interactions
storybook-addon-designsEmbed Figma design previews
@storybook/addon-jestDisplay unit test results in stories

Example: Add Docs tab for live documentation.

15. Best Practices for Component Library Design

PracticeDescription
Use Angular CDK over MaterialGives flexibility to design your own UI style.
Follow Atomic DesignBuild components as atoms, molecules, and organisms.
Strict Type SafetyUse strong typings and input validation.
Include Accessibility (a11y)Make components keyboard and screen-reader friendly.
Document Every Component in StorybookClear usage and visual representation.
Version Control Your LibraryFollow 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.