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.
Maintainers
Readme
ng-hub-ui-milestones
Español | English
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:
- ng-hub-ui-accordion (deprecated — use ng-hub-ui-panels)
- ng-hub-ui-action-sheet
- ng-hub-ui-avatar
- ng-hub-ui-board
- ng-hub-ui-breadcrumbs
- ng-hub-ui-calendar
- ng-hub-ui-dropdown
- ng-hub-ui-ds
- ng-hub-ui-forms
- ng-hub-ui-history
- ng-hub-ui-milestones ← You are here
- ng-hub-ui-modal
- ng-hub-ui-nav
- ng-hub-ui-paginable
- ng-hub-ui-panels
- ng-hub-ui-portal
- ng-hub-ui-skeleton
- ng-hub-ui-sortable
- ng-hub-ui-stepper
- ng-hub-ui-utils
📑 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-milestonesis 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-milestoneis a single node. It exposes a visualstate(complete·active·pending·error), an optional per-nodecoloroverride, and alabelfallback. Any markup placed inside it is projected as the node's body (title, description, dates, etc.).hubMilestoneNodeis 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 thelabelor the auto-generated 1-based index.
Components are standalone, signal-based, use OnPush change detection, and are SSR-safe.
✨ Features
- Two orientations:
verticalandhorizontallayouts from a single input. - Automatic numbering: nodes are numbered (1, 2, 3 …) in DOM order, with no manual bookkeeping.
- Visual states:
complete,active,pending, anderrorstates 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
colorinput. - Viewport reveal animation: the accent trail "completes" up to the active node when the timeline scrolls into view — on by default, configurable globally with
provideHubMilestonesor per instance with[reveal]. SSR-safe and disabled underprefers-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-milestonenodes 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
- Issues: GitHub Issues
- Author: Carlos Morcillo
📄 License
MIT © Carlos Morcillo
Made with ❤️ by the Hub UI team
