Scalability of Angular. Simplicity of Tailwind.
A modern Angular 21+ component system built with Signals, Standalone APIs, and strict architectural discipline.
โจ What is TailNG?
TailNG is an open-source Angular component system designed for:
- Large applications
- Enterprise design systems
- Strict type safety
- Accessibility-first development
- Signal-based architecture
- Tailwind-compatible styling
It combines:
- Angular 21+
- Standalone Components
- Angular Signals
- Strict ESLint architecture
- Nx monorepo discipline
- Optional Tailwind integration
๐ฏ Product Direction
TailNG is evolving toward a framework-agnostic component platform with:
- Accessibility-first primitives built on Angular CDK and
@angular/aria(experimental) - Wrapper abstractions that make component composition simpler for app developers
- Additional in-house components implemented using ARIA authoring principles
- Micro-level styling control for each component (slots, states, tokens, and hooks)
- No required dependency on Tailwind or any specific CSS framework
- Zero hard coupling between component behavior and styling systems
- Shadcn-style copy/paste distribution mode in addition to package install
Risk Decision (@angular/aria)
- Primary path: use
@angular/ariaas the basis for new primitives - Current tradeoff: accept experimental risk while Angular 22 direction matures
- Fallback policy: do not build full CDK fallback now
- Constraint: keep an adapter seam now so fallback can be implemented later without rewrites
- Rule: components depend on TailNG primitive contracts, not direct
@angular/ariaimports
๐ฆ Packages
| Package | Description |
|---|---|
@tailng-ui/ui |
Main component library |
@tailng-ui/cdk |
Behavior primitives & utilities |
@tailng-ui/theme |
Design tokens & Tailwind adapter |
@tailng-ui/icons |
Icon wrappers |
๐ Installation
Peer dependencies:
@angular/core^21@angular/common^21@angular/forms^21
โก Quick Example
import { Component } from '@angular/core'; import { TngButton } from '@tailng-ui/ui'; @Component({ standalone: true, imports: [TngButton], template: ` <tng-button variant="primary"> Click me </tng-button> `, }) export class ExampleComponent {}
๐ Architecture
TailNG follows a layered structure:
apps/ docs/ โ Documentation site playground/ โ Component sandbox
libs/ ui/ โ Styled components cdk/ โ Behavior primitives theme/ โ Tokens & adapters icons/ โ Icon library
Design principles:
- Composition over prop explosion
- Behavior separated from styling
- Strict architectural boundaries (Nx enforced)
- Public API discipline
- No deep imports
- Exhaustive state safety
๐ง Philosophy
TailNG is:
- Headless-friendly
- Tailwind-compatible (not required)
- Accessibility-aware
- Strictly typed
- Enterprise-ready
- Open-source forever (MIT)
We aim to provide:
- Clean APIs
- Predictable behavior
- Scalable structure
- Zero vendor lock-in
๐งช Development
Install dependencies
Run playground
Run registry CLI playground:
Run docs site
Build static output for Cloudflare Pages:
Build static playground output for Cloudflare Pages:
Build static vanilla playground output for Cloudflare Pages:
pnpm playground:vanilla:seo
Lint
Test
Run all library tests directly with Nx:
Run only theme tests:
Run CLI integration tests (tailng add ... end-to-end in temp directories):
Run in watch mode:
pnpm nx run theme:vite:test --watch
Run with coverage:
pnpm nx run theme:vite:test --coverage
Run directly with Vitest (without Nx):
pnpm exec vitest run --config libs/tailng-ui/theme/vitest.config.tsTailNG CLI (local)
Build and run the tailng CLI:
pnpm build:tailng pnpm tailng -- list pnpm tailng -- add button --cwd apps/tailng-ui/playground-vanilla --dry-run pnpm tailng -- add button --cwd apps/tailng-ui/playground-registry --dry-run
Registry command reference:
- List available registry items:
- Preview file generation without writing:
pnpm tailng -- add button --cwd apps/tailng-ui/playground-registry --dry-run
- Generate files:
pnpm tailng -- add button --cwd apps/tailng-ui/playground-registry
- Overwrite existing generated files:
pnpm tailng -- add button --cwd apps/tailng-ui/playground-registry --force
Note:
--dry-runshowsCREATE,SKIP, orOVERWRITEbehavior.--cwdshould point to the app root where files must be generated.tailng add buttonfollows shadcn-style source copy. It writes local files to:src/app/tailng-ui/button/tng-button-primitive.tssrc/app/tailng-ui/button/tng-button.tssrc/app/tailng-ui/button/tng-button.htmlsrc/app/tailng-ui/button/tng-button.csssrc/app/tailng-ui/button/index.ts
- Import locally in your app:
import { TngButton } from './tailng-ui/button';
๐ท Component Guidelines
- Use Angular Signals (
input()) - Standalone components only
- No default exports
- Explicit return types
- Exhaustive switch checks
- Complexity โค 8
- Max params โค 3
- Accessibility-first markup
- Strict ESLint enforced
๐ Documentation
- Website: https://tailng.dev
- npm: https://www.npmjs.com/package/@tailng-ui/ui
- GitHub: https://github.com/tailng/tailng-ui
๐ค Contributing
Contributions are welcome.
Before submitting a PR:
- Follow ESLint rules
- Respect architectural boundaries
- Avoid deep imports
- Maintain strict typing
- Include playground demo
๐ License
MIT ยฉ 2026 TailNG