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

ng-hub-ui-milestones

v22.3.0

Published

A lightweight, presentational timeline / progress-steps component for Angular with vertical and horizontal layouts, customizable nodes, and full CSS-variable theming.

Readme

ng-hub-ui-milestones

Español | English

npm version license

A lightweight, presentational timeline / progress-steps component for Angular: lay out milestone nodes vertically or horizontally, project any content into each node, and theme everything with CSS variables.

Documentation and Live Examples

This package is part of Hub UI, a collection of Angular component libraries for standalone apps.

  • Docs: https://hubui.dev/milestones/overview/
  • Live examples: https://hubui.dev/milestones/examples/
  • Hub UI: https://hubui.dev/

🧩 Library Family ng-hub-ui

This library is part of the Hub UI ecosystem:

📑 Table of Contents

📖 Description

ng-hub-ui-milestones renders a timeline (also known as progress steps) made of milestone nodes connected by a rail. It is purely presentational and unopinionated about your data: you compose the timeline declaratively with two components and one directive.

  • hub-milestones is the container. It lays out its child nodes either vertically or horizontally, draws the connecting rail, and numbers the nodes automatically in DOM order.
  • hub-milestone is a single node. It exposes a visual state (complete · active · pending · error), an optional per-node color override, and a label fallback. Any markup placed inside it is projected as the node's body (title, description, dates, etc.).
  • hubMilestoneNode is a structural directive that lets you project custom content inside the node circle — a number, an icon, an avatar, or any markup. When omitted, the node shows the label or the auto-generated 1-based index.

Components are standalone, signal-based, use OnPush change detection, and are SSR-safe.

✨ Features

  • Two orientations: vertical and horizontal layouts from a single input.
  • Automatic numbering: nodes are numbered (1, 2, 3 …) in DOM order, with no manual bookkeeping.
  • Visual states: complete, active, pending, and error states drive node and connector colors.
  • Custom node content: project numbers, icons, or avatars into the circle via hubMilestoneNode.
  • Per-node color override: set any CSS color on an individual node with the color input.
  • Viewport reveal animation: the accent trail "completes" up to the active node when the timeline scrolls into view — on by default, configurable globally with provideHubMilestones or per instance with [reveal]. SSR-safe and disabled under prefers-reduced-motion.
  • Active-node pulse (opt-in [pulse]): a soft wave on the active node to highlight the current step.
  • RTL ready: layout, connectors and the reveal animation flip correctly under dir="rtl".
  • Full CSS-variable theming: customize colors, sizes, spacing, and animation timings through --hub-milestone-* tokens.
  • Standalone & modern: standalone components, Angular Signals, OnPush, SSR-safe.
  • Zero runtime dependencies beyond Angular and tslib.

📦 Installation

npm install ng-hub-ui-milestones

🚀 Usage

Import the standalone components (and the directive when projecting custom node content) into your component:

import { Component } from '@angular/core';
import { HubMilestonesComponent, HubMilestoneComponent, HubMilestoneNodeDirective } from 'ng-hub-ui-milestones';

@Component({
	selector: 'app-roadmap',
	standalone: true,
	imports: [HubMilestonesComponent, HubMilestoneComponent, HubMilestoneNodeDirective],
	template: `
		<hub-milestones orientation="vertical">
			<hub-milestone state="complete">
				<h4>Project kickoff</h4>
				<p>Requirements gathered and approved.</p>
			</hub-milestone>

			<hub-milestone state="active">
				<h4>Development</h4>
				<p>Building the core features.</p>
			</hub-milestone>

			<hub-milestone state="pending">
				<ng-template hubMilestoneNode>★</ng-template>
				<h4>Release</h4>
				<p>Ship to production.</p>
			</hub-milestone>
		</hub-milestones>
	`
})
export class RoadmapComponent {}

Horizontal orientation

<hub-milestones orientation="horizontal">
	<hub-milestone state="complete"><h4>Step 1</h4></hub-milestone>
	<hub-milestone state="active"><h4>Step 2</h4></hub-milestone>
	<hub-milestone state="pending"><h4>Step 3</h4></hub-milestone>
</hub-milestones>

Labels and per-node color

<hub-milestones orientation="vertical">
	<hub-milestone state="complete" label="A">
		<h4>Phase A</h4>
	</hub-milestone>

	<hub-milestone state="active" color="#0d6efd">
		<h4>Phase B</h4>
	</hub-milestone>

	<hub-milestone state="error">
		<h4>Phase C</h4>
		<p>Something went wrong here.</p>
	</hub-milestone>
</hub-milestones>

When a node has neither a hubMilestoneNode template nor a label, it falls back to its auto-generated 1-based number.

Active-node pulse

Add [pulse] to the container to emit a soft wave on the active node, drawing attention to the current step. It is opt-in and respects prefers-reduced-motion.

<hub-milestones orientation="horizontal" [pulse]="true">
	<hub-milestone state="complete"><h4>Ordered</h4></hub-milestone>
	<hub-milestone state="active"><h4>In transit</h4></hub-milestone>
	<hub-milestone state="pending"><h4>Delivered</h4></hub-milestone>
</hub-milestones>

Viewport reveal animation

When a <hub-milestones> scrolls into view, it animates the accent trail filling from the first node up to the active node. It is on by default — no setup required. The component only animates in the browser, so SSR / no-JS renders the full trail, and the animation is disabled under prefers-reduced-motion.

Turn it off (or back on) globally by adding provideHubMilestones to your application config:

import { ApplicationConfig } from '@angular/core';
import { provideHubMilestones } from 'ng-hub-ui-milestones';

export const appConfig: ApplicationConfig = {
	providers: [
		// Disable the reveal animation for every <hub-milestones> in the app.
		provideHubMilestones({ reveal: false })
	]
};

The per-instance [reveal] input always wins over the global default:

<!-- Force the reveal on, even if it is disabled globally -->
<hub-milestones [reveal]="true"> … </hub-milestones>

📚 API Reference

HubMilestonesComponent<hub-milestones>

Inputs

| Input | Type | Default | Description | | ------------- | -------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------- | | orientation | HubMilestonesOrientation | 'vertical' | Layout direction: 'vertical' or 'horizontal'. | | pulse | boolean | false | Emits a soft wave on the active node to highlight the current step. Respects prefers-reduced-motion. | | reveal | boolean | (global) | Plays the viewport reveal animation when the timeline scrolls into view. Defaults to the provideHubMilestones value (on if unset). |

The container also auto-numbers its projected hub-milestone nodes in DOM order; no input is required for this.

provideHubMilestones(config?)

An environment provider for application-wide defaults. Add it to your ApplicationConfig providers array.

| Option | Type | Default | Description | | -------- | --------- | ------- | ---------------------------------------------------------------------------------------- | | reveal | boolean | true | Default for the viewport reveal animation. Overridden per instance by the [reveal] input. |

HubMilestoneComponent<hub-milestone>

Inputs

| Input | Type | Default | Description | | ------- | ------------------- | ----------- | ------------------------------------------------------------------------------------------------- | | state | HubMilestoneState | 'pending' | Visual state: 'complete' · 'active' · 'pending' · 'error'. Drives node/connector colors. | | color | string | '' | Per-node color override (any CSS color). Wins over the state color. | | label | string | '' | Fallback content shown inside the node when no hubMilestoneNode template is given. |

Projected (non-template) content placed inside <hub-milestone> is rendered as the node body, beside (vertical) or below (horizontal) the node circle.

HubMilestoneNodeDirective[hubMilestoneNode]

A structural directive applied to an <ng-template> to project custom content inside the node circle (a number, icon, avatar, or any markup). It has no inputs or outputs.

<hub-milestone state="complete">
	<ng-template hubMilestoneNode>✓</ng-template>
	<h4>Done</h4>
</hub-milestone>

Exported types

| Type | Values | | -------------------------- | ------------------------------------------------ | | HubMilestonesOrientation | 'vertical' \| 'horizontal' | | HubMilestoneState | 'complete' \| 'active' \| 'pending' \| 'error' | | HubMilestonesConfig | { reveal?: boolean } |

🎨 Styling

The library is themed entirely through --hub-milestone-* CSS variables, with safe fallbacks so it works standalone and re-themes at runtime. Override them on :root, on a hub-milestones selector, or per node via the color input.

| CSS Variable | Default | Description | | -------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------- | | --hub-milestone-node-size | 2.75rem | Diameter of the node circle. | | --hub-milestone-node-font-size | 1.05rem | Font size of the node content. | | --hub-milestone-node-color | var(--hub-sys-color-primary, #0d6efd) | Node background color (complete/active). Also drives the trail. | | --hub-milestone-node-text | var(--hub-ref-color-white, #ffffff) | Node text/content color. | | --hub-milestone-pending-bg | var(--hub-sys-surface-elevated, #f8f9fa) | Background of a pending node. | | --hub-milestone-pending-color | var(--hub-sys-text-muted, #6c757d) | Text color of a pending node. | | --hub-milestone-pending-border | var(--hub-sys-border-color-default, #dee2e6) | Border of a pending node. | | --hub-milestone-error-bg | var(--hub-sys-color-danger, #dc3545) | Background of an error node. | | --hub-milestone-connector-thickness | 3px | Thickness of the connecting rail. | | --hub-milestone-connector-bg | var(--hub-milestone-node-color) | Connector fill for completed segments (follows the node accent). | | --hub-milestone-connector-pending-bg | var(--hub-sys-border-color-default, #dee2e6) | Connector fill for segments leading into a pending node. | | --hub-milestone-gap | 1rem | Gap between the node and its body. | | --hub-milestone-spacing | 1.75rem | Spacing between consecutive milestones. | | --hub-milestone-body-color | var(--hub-sys-text-primary, #212529) | Body text color. | | --hub-milestone-body-muted | var(--hub-sys-text-muted, #6c757d) | Muted body text color. | | --hub-milestone-pulse-color | var(--hub-milestone-node-color) | Color of the active-node pulse wave ([pulse]). | | --hub-milestone-pulse-duration | 1.6s | Duration of one pulse cycle. | | --hub-milestone-pulse-spread | 0.75rem | How far the pulse wave expands from the node. | | --hub-milestone-reveal-duration | 0.5s | Duration of each connector's fill during the viewport reveal. | | --hub-milestone-reveal-stagger | 0.14s | Delay between consecutive connectors filling (cascading reveal). |

Framework-agnostic customization example:

hub-milestones {
	--hub-milestone-node-size: 3rem;
	--hub-milestone-node-color: #2563eb; // also tints the connector trail
	--hub-milestone-spacing: 2rem;
}

Bootstrap integration example (optional):

hub-milestones {
	--hub-milestone-node-color: var(--bs-primary);
	--hub-milestone-error-bg: var(--bs-danger);
	--hub-milestone-pending-bg: var(--bs-secondary-bg);
	--hub-milestone-body-color: var(--bs-body-color);
}

📝 Changelog

See the full CHANGELOG.md for the complete version history.

🤝 Contributing

Contributions are welcome. Please open an issue to discuss significant changes before submitting a pull request, and follow the existing code style and conventions.

  • Repository: https://github.com/carlos-morcillo/ng-hub-ui-milestones
  • Issues: https://github.com/carlos-morcillo/ng-hub-ui/issues

📞 Support

📄 License

MIT © Carlos Morcillo


Made with ❤️ by the Hub UI team