Accessible Angular UI, built to be owned.
Angular 21+ components, headless primitives, theme contracts, and ownable source installs for teams building design systems and application UI.
TailNG is an open-source Angular UI system for applications and design systems that need accessible behavior, strict type safety, and implementation ownership.
The monorepo provides:
- Ready-to-use styled Angular components.
- Headless primitives for custom UI systems.
- Low-level accessibility, collection, overlay, and runtime utilities.
- Theme contracts, CSS variable tooling, and Tailwind adapters.
- A copy-source registry and CLI for shadcn-style local component ownership.
- Documentation and playground apps for package, Tailwind, plain CSS, and registry workflows.
TailNG is built with Angular 21+, standalone APIs, signals, Nx, Vitest, and strict ESLint boundaries.
| Package | Description |
|---|---|
@tailng-ui/components |
Styled Angular components built on TailNG primitives. |
@tailng-ui/primitives |
Headless, accessibility-first Angular primitives. |
@tailng-ui/cdk |
Behavior, accessibility, collection, overlay, and runtime utilities. |
@tailng-ui/theme |
Theme contracts, presets, CSS variables, component contracts, and Tailwind adapters. |
@tailng-ui/icons |
Angular icon wrappers backed by @ng-icons. |
@tailng-ui/charts |
Apache ECharts wrappers for Angular. |
@tailng-ui/registry |
Metadata for ownable component installs. |
tailng |
CLI for listing and copying ownable components into Angular apps. |
Install styled components:
pnpm add @tailng-ui/components @tailng-ui/primitives @tailng-ui/cdkInstall headless primitives:
pnpm add @tailng-ui/primitives @tailng-ui/cdkInstall the theme package:
pnpm add @tailng-ui/themeUse the ownable-source CLI without adding it permanently:
pnpm dlx tailng list
pnpm dlx tailng add buttonPrimary peer dependencies:
@angular/core^21.1.0@angular/common^21.1.0@angular/forms^21.1.0@angular/platform-browser^21.1.0@angular/router^21.1.0tslib^2.3.0
Package-specific peer dependencies are listed in each package README.
import { Component } from '@angular/core';
import { TngButton } from '@tailng-ui/components';
@Component({
standalone: true,
imports: [TngButton],
template: `<tng-button tone="success">Continue</tng-button>`,
})
export class ExampleComponent {}For headless usage:
import { Component } from '@angular/core';
import { TngPress } from '@tailng-ui/primitives';
@Component({
standalone: true,
imports: [TngPress],
template: `<button tngPress>Action</button>`,
})
export class ExampleComponent {}TailNG is organized as an Nx workspace with layered packages:
apps/
tailng-ui/
docs/ Documentation site
playground-plain-css/ Plain CSS playground
playground-registry/ Ownable install playground
playground-tailwind/ Tailwind playground
libs/
tailng/
cli/ tailng command-line tool
tailng-ui/
cdk/ Headless behavior and runtime utilities
primitives/ Headless Angular primitives
components/ Styled Angular components
theme/ Theme engine and CSS contracts
icons/ Icon wrappers
charts/ Chart wrappers
registry/ Ownable install metadata
Layering rules:
- Components depend on primitives and CDK contracts.
- Primitives depend on CDK behavior utilities.
- Styling is separated from behavior.
- Public APIs are exported from package entry points.
- Deep imports are avoided.
- Accessibility and keyboard behavior are treated as package contracts.
TailNG is moving toward a component platform that supports both package installs and source ownership.
Current priorities:
- Accessibility-first primitives and components.
- Wrapper abstractions that keep app usage simple.
- Component style contracts for slots, states, tokens, and hooks.
- No hard dependency on Tailwind or any single CSS framework.
- Copy-source installation through the
tailngCLI. - Stable package boundaries across CDK, primitives, components, theme, registry, and docs.
Requirements:
- Node.js
>=20.20.0 - pnpm
>=10.30.0
Install dependencies:
pnpm installRun the documentation site:
pnpm start:docsRun playgrounds:
pnpm start:vanilla
pnpm start:tailwindBuild packages and apps:
pnpm run buildBuild selected targets:
pnpm run build:docs
pnpm run build:theme
pnpm run build:cli
pnpm run build:vanilla
pnpm run build:tailwindBuild and publish docs locally (Cloudflare Pages):
CF_DOCS_PROJECT_NAME=taling-dev \
CLOUDFLARE_API_TOKEN=90Oh4-tjMr9Fxj8naoK_8odkfw8QdbHpS-CVNTf- \
CLOUDFLARE_ACCOUNT_ID=218f66f3a999f3f020117242ec252f18 \
./tools/build-deploy-docs.shNotes:
CF_DOCS_PROJECT_NAMEmaps to the Cloudflare Pages project name.CLOUDFLARE_API_TOKENandCLOUDFLARE_ACCOUNT_IDare required bywrangler.- If needed, you can override branch and output behavior with
CF_PAGES_BRANCHandDOCS_DIST.
Generate static output:
pnpm run seo:docs
pnpm run seo:vanilla
pnpm run seo:tailwindIf prerendering fails because Chrome is missing, install the browser once:
pnpm exec puppeteer browsers install chromeRun all package tests:
pnpm run test:packagesRun the full Vitest suite:
pnpm run test:allRun targeted tests:
pnpm run test:cdk
pnpm run test:primitives
pnpm run test:components
pnpm run test:theme
pnpm run test:icons
pnpm run test:charts
pnpm run test:registry
pnpm run test:cli
pnpm run test:docsLint and format:
pnpm run lint
pnpm run format:nx
pnpm run format:prettierTypecheck key package surfaces:
pnpm run typecheck:registry
pnpm run typecheck:cli
pnpm run typecheck:docsRun the ownable install contract checks:
pnpm run verify:ownable-contractsBuild and run the local CLI:
pnpm run build:cli
pnpm run run:tailng -- listPreview generated files:
pnpm run run:tailng -- add button --cwd apps/tailng-ui/playground-registry --dry-runGenerate files:
pnpm run run:tailng -- add button --cwd apps/tailng-ui/playground-registryOverwrite existing generated files:
pnpm run run:tailng -- add button --cwd apps/tailng-ui/playground-registry --forcetailng add <component-name> writes source under:
<cwd>/src/app/tailng-ui/<component>/
Import generated components from the local app path:
import { TngButton } from './tailng-ui/button';Common aliases supported by tailng add:
| Alias | Canonical item |
|---|---|
slide-toggle |
switch |
sidenav, sidebar, side-nav, sheet |
drawer |
expansion-panel |
accordion |
spinner |
progress-spinner |
snackbar, sonner |
toast |
- Use standalone Angular APIs.
- Prefer signals and
input()for component inputs. - Keep behavior and styling separate.
- Avoid default exports.
- Use explicit return types.
- Keep public APIs intentional and documented.
- Preserve accessibility semantics, roles, states, and keyboard behavior.
- Add or update tests when changing behavior.
- Website: https://tailng.dev
- GitHub: https://github.com/tailng/tailng-ui
- npm components: @tailng-ui/components
- npm CLI: tailng
Contributions are welcome.
Before submitting a PR:
- Run relevant tests and lint checks.
- Respect Nx boundaries and package layering.
- Avoid deep imports.
- Keep typing strict.
- Include docs or playground coverage for user-facing changes.
MIT © 2026 TailNG