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-skeleton

v22.2.1

Published

Dynamic Angular skeleton placeholders with presets, inline DSL templates, responsive variants, and programmatic preset registration.

Readme

ng-hub-ui-skeleton

Español | English

npm version license

Dynamic Angular skeleton placeholders driven by a compact Emmet-like DSL, reusable presets, responsive values, variants, and programmatic preset registration.

Documentation and Live Examples

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

  • Docs: https://hubui.dev/skeleton/overview/
  • Live examples: https://hubui.dev/skeleton/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-skeleton renders loading placeholders for Angular standalone apps. Instead of hand-crafting a markup tree per loading state, you describe the placeholder with a single compact string — a small Emmet-inspired DSL — or you pick one of the bundled presets. Skeletons are fully responsive (values can change per breakpoint), support visual variants, and can be extended at the application level with your own preset catalogue.

The <hub-skeleton> component resolves the active breakpoint from the viewport width, expands presets and aliases recursively, interpolates any {{param}} placeholders, and paints animated shimmer surfaces with CSS — no external dependencies.

✨ Features

  • Compact DSL: Describe entire placeholder trees with a single Emmet-like string.
  • Bundled presets: Ready-made layouts for cards, lists, tables, forms, dashboards, charts, profiles, feeds, and empty states.
  • Preset composition: Reference any preset by name inside the DSL as an alias (e.g. list-item*4).
  • Responsive values: Per-breakpoint tokens (base, sm, md, lg, xl) resolved from the viewport width.
  • Variants: Named preset variants (such as compact) selected with the variant input or inline name@variant.
  • Parameters: Inject runtime values via {{param}} interpolation and the params input.
  • Programmatic registration: Add custom presets app-wide with provideHubSkeletonPresets.
  • Appearance presets: default, subtle, and contrast tones.
  • CSS shimmer animation: Toggleable, fully CSS-driven, no JavaScript animation loop.
  • Standalone & SSR-aware: Standalone component, OnPush change detection, and browser-only resize handling.
  • Lightweight: No external runtime dependencies.

📦 Installation

npm install ng-hub-ui-skeleton

🚀 Usage

Import the standalone component (or the optional HubSkeletonModule for module-based apps):

import { HubSkeletonComponent } from 'ng-hub-ui-skeleton';

@Component({
	selector: 'app-demo',
	standalone: true,
	imports: [HubSkeletonComponent],
	template: `...`
})
export class DemoComponent {}

Render a bundled preset

<hub-skeleton preset="card"></hub-skeleton>
<hub-skeleton preset="list-item"></hub-skeleton>
<hub-skeleton preset="dashboard-widget"></hub-skeleton>

Bundled preset names: card, list-item, table-row, detail-view, form-section, dashboard-widget, stat-card, chart-panel, profile-summary, master-detail, kanban-card, feed-item, search-result, table-toolbar, filter-bar, empty-state-skeleton.

Render an inline DSL template

<hub-skeleton
	template="stack(gap:12)>circle(size:48)+stack(gap:8)>line(width:40%)+line(width:72%)"
></hub-skeleton>

You can also pass a template definition object instead of a string (see Responsive templates).

Parameterized presets

Presets expose {{param}} placeholders that you can override through the params input. Any value passed in params is merged on top of the preset defaults.

<!-- The "card" preset accepts `rows`, `radius`, `titleWidth`, etc. -->
<hub-skeleton preset="card" [params]="{ rows: 4, radius: 8 }"></hub-skeleton>

<!-- The "table-row" preset adapts to the column count -->
<hub-skeleton preset="table-row" [params]="{ columns: 6 }"></hub-skeleton>

Variants

Some presets define named variants (for example card and list-item ship a compact variant). Select one with the variant input:

<hub-skeleton preset="card" variant="compact"></hub-skeleton>

Inside the DSL, a variant can be selected per node with the name@variant syntax:

<hub-skeleton template="card@compact"></hub-skeleton>

Responsive templates

Pass a HubSkeletonTemplateDefinition with breakpoint-specific DSL replacements:

import { HubSkeletonTemplateDefinition } from 'ng-hub-ui-skeleton';

readonly responsiveTemplate: HubSkeletonTemplateDefinition = {
	dsl: 'grid(columns:1,gap:12)>block(height:120)*2',
	responsive: {
		md: 'grid(columns:2,gap:16)>block(height:160)*4',
		lg: 'grid(columns:4,gap:20)>block(height:200)*4'
	}
};
<hub-skeleton [template]="responsiveTemplate"></hub-skeleton>

Individual modifier values can also be made responsive inline (see The Template DSL).

Register custom presets

Register your own preset catalogue at the application level. Custom presets are merged on top of the bundled ones (matching names override).

import { ApplicationConfig } from '@angular/core';
import { provideHubSkeletonPresets } from 'ng-hub-ui-skeleton';

export const appConfig: ApplicationConfig = {
	providers: [
		provideHubSkeletonPresets([
			{
				name: 'profile-card',
				description: 'Custom profile card placeholder',
				template:
					'stack(gap:16)>circle(size:72)+line(width:52%,height:18)+line(width:70%,height:12)+grid(columns:2|md=4,gap:10)>block(height:56)*4',
				defaults: { rows: 2 },
				variants: {
					compact: { defaults: { rows: 1 } }
				}
			}
		])
	]
};
<hub-skeleton preset="profile-card"></hub-skeleton>

✍️ The Template DSL

The DSL is a compact, Emmet-inspired grammar that compiles into a tree of skeleton nodes.

Node types

| Node | Surface? | Description | | -------- | -------- | ------------------------------------------------ | | line | Yes | A thin text-line placeholder | | block | Yes | A rectangular block (media, button, image, etc.) | | circle | Yes | A circular placeholder (avatars, icons) | | stack | No | Flex container (column by default) | | grid | No | CSS grid container |

Any name that is not a built-in node type is resolved as a preset alias and expanded recursively.

Operators

| Operator | Meaning | Example | | ----------- | ---------------------------------------------------- | -------------------------------- | | > | Child — nest the following siblings inside the node | stack>line+line | | + | Sibling — add another node at the same level | circle+line | | *N | Repeat — repeat the preceding node N times | line*3 | | (k:v,...) | Modifiers — set properties on a node | block(height:120,radius:18) | | @variant | Variant — select a preset variant for an alias node | card@compact | | {{param}} | Parameter — interpolated from params/preset values | line(width:{{titleWidth}}) |

Modifiers

Modifiers are key/value pairs inside parentheses, comma-separated. A modifier with no value defaults to true (e.g. grow is equivalent to grow:true).

| Modifier | Applies to | Description | | ---------- | ---------------- | ---------------------------------------------------------- | | width | line/block/circle| Node width (percentage or length; raw numbers → px) | | height | line/block/circle| Node height (raw numbers → px) | | size | circle | Diameter (raw numbers → px) | | radius | surface nodes | Border radius (raw numbers → px) | | gap | stack/grid | Gap between children (raw numbers → px) | | columns | grid | Number of grid columns | | direction| stack | column (default) or row | | align | stack/grid | align-items value (e.g. center, flex-start) | | justify | stack | justify-content value (e.g. space-between, flex-end) | | grow | any node | When true, the node flex-grows to fill space |

Responsive modifier values

A single modifier value can carry breakpoint-specific overrides using the | separator and breakpoint=value syntax. The bare value (no =) is the base value, and each breakpoint applies from its width upward.

grid(columns:1|md=2|lg=4)
block(height:220|lg=280)

Supported breakpoints and their min-widths: sm (576px), md (768px), lg (992px), xl (1280px). base applies below sm.

Full example

stack(gap:16)>block(height:180,radius:18)+line(height:18,width:56%)+stack(gap:10)>line(width:100%)*2+line(width:76%)

📖 API Reference

HubSkeletonComponent

Selector: hub-skeleton

Inputs

| Input | Type | Default | Description | | ------------ | --------------------------------- | ------------------------ | --------------------------------------------------------------------------- | | preset | string \| null | null | Built-in or registered preset name to render. | | template | HubSkeletonTemplateInput \| null| null | Inline DSL string or template definition object. | | params | HubSkeletonParams | {} | Serializable values interpolated into {{param}} placeholders. | | variant | string \| null | null | Named preset variant to apply. | | animated | boolean | true | Toggles the shimmer animation. | | appearance | HubSkeletonAppearance | 'default' | Visual tone: 'default' \| 'subtle' \| 'contrast'. | | ariaLabel | string | 'Loading placeholder' | Accessible label applied to the container. |

Either preset or template must be provided; otherwise the component throws. An unknown preset name also throws.

This component has no outputs.

provideHubSkeletonPresets(presets)

Environment provider that appends custom presets to the bundled catalogue for the active injector tree.

function provideHubSkeletonPresets(presets: readonly HubSkeletonPreset[]): EnvironmentProviders;

It is multi-provider backed (token HUB_SKELETON_PRESETS), so multiple calls accumulate. Later presets override earlier ones with the same name.

HubSkeletonPresetRegistryService

Injectable (providedIn: 'root') service that resolves the merged preset catalogue.

| Member | Signature | Description | | ------------------ | ----------------------------------------------- | -------------------------------------------- | | presets | Signal<Map<string, HubSkeletonPreset>> | All presets merged by name. | | getPreset(name) | (name: string) => HubSkeletonPreset \| undefined | Returns a single preset by name. |

Exported types

type HubSkeletonBreakpoint = 'base' | 'sm' | 'md' | 'lg' | 'xl';
type HubSkeletonPrimitive = string | number | boolean;
type HubSkeletonResponsiveValue<T extends HubSkeletonPrimitive = HubSkeletonPrimitive> =
	| T
	| Partial<Record<HubSkeletonBreakpoint, T>>;
type HubSkeletonParams = Record<string, HubSkeletonPrimitive | undefined>;
type HubSkeletonAppearance = 'default' | 'subtle' | 'contrast';
type HubSkeletonTemplateInput = string | HubSkeletonTemplateDefinition;

interface HubSkeletonTemplateDefinition {
	readonly dsl: string;
	readonly responsive?: Partial<Record<Exclude<HubSkeletonBreakpoint, 'base'>, string>>;
}

interface HubSkeletonPreset {
	readonly name: string;
	readonly template: HubSkeletonTemplateInput;
	readonly defaults?: HubSkeletonParams;
	readonly variants?: Record<string, {
		readonly template?: HubSkeletonTemplateInput;
		readonly defaults?: HubSkeletonParams;
	}>;
	readonly description?: string;
}

Additional DSL helpers are also exported (parseHubSkeletonDsl, interpolateHubSkeletonParams, resolveTemplateDsl, resolveResponsiveToken, resolveBreakpointFromWidth, resolveHubSkeletonNodes) along with the HUB_SKELETON_DEFAULT_PRESETS catalogue and the HubSkeletonModule.

🎨 Styling / CSS Variables

The component styles itself with CSS custom properties scoped to the .hub-skeleton container. Override them on the host to theme skeletons:

| Variable | Default | Description | | ------------------------------------- | -------------------------------- | ------------------------------------ | | --hub-skeleton-bg | rgba(148, 163, 184, 0.18) | Base surface color. | | --hub-skeleton-highlight | rgba(255, 255, 255, 0.52) | Shimmer highlight color. | | --hub-skeleton-radius | 12px | Default surface border radius. | | --hub-skeleton-gap | 12px | Default gap for stack/grid nodes. | | --hub-skeleton-animation-duration | 1.35s | Shimmer animation duration. |

hub-skeleton {
	--hub-skeleton-bg: rgba(0, 0, 0, 0.08);
	--hub-skeleton-highlight: rgba(255, 255, 255, 0.6);
	--hub-skeleton-radius: 8px;
	--hub-skeleton-animation-duration: 1.6s;
}

The appearance input swaps the base/highlight colors for subtle and contrast tones. Per-node modifiers (width, height, size, radius, gap, columns, align, justify) are applied as scoped --hub-skeleton-node-* custom properties.

The hub-skeleton-theme() Sass mixin

For Sass-based projects, the hub-skeleton-theme() mixin overrides the --hub-skeleton-* tokens in a single include. Every parameter is optional and defaults to null, so only the ones you pass are emitted — the rest keep the component defaults. It is token-based and self-contained (no Bootstrap dependency). A skeleton is a neutral placeholder, so there is no semantic color variant: tune the base / highlight surfaces, the corner radius, the gap between nodes and the shimmer speed instead (per-node sizes still come from the template DSL / presets).

@use 'ng-hub-ui-skeleton/styles/mixins/skeleton-theme' as *;

hub-skeleton.on-dark {
	@include hub-skeleton-theme(
		$bg: rgba(255, 255, 255, 0.1),
		$highlight: rgba(255, 255, 255, 0.22),
		$radius: 8px,
		$animation-duration: 1.8s
	);
}

Available parameters: $bg, $highlight, $radius, $gap, $animation-duration.

📊 Changelog

See CHANGELOG.md for the full version history.

🤝 Contribution

Contributions are welcome. Please open an issue to discuss substantial changes before submitting a pull request, and make sure to document every library change in CHANGELOG.md.

☕ Support

📄 License

MIT © Carlos Morcillo


Made with ❤️ by the Hub UI team