Getting StartedInstall and bootstrap headless foundations 4
Quick Start
Installation
Plain CSS Setup
Tailwind Setup
FormHeadless input and selection contracts 14
Input
Textarea
Label
Checkbox
Toggle
Switch
Radio
Button Toggle
ListBox
AutoComplete
MultiAutocomplete
SelectBox
MultiSelect
Chips
UtilityReusable action and clipboard behavior 3
Codeblock
CopyButton
Button
NavigationHeadless menu and command surfaces 3
Menubar
Menu
Context Menu

Headless — Quick Start

TailNG headless components are behavior-only primitives: they handle accessibility, keyboard and pointer behavior, and state while you own the markup and styling.

Getting Started

Quick Start

Create a first headless-driven page with keyboard-safe interaction defaults.

What is Headless?

Primitives live in @tailng-ui/primitives and expose interaction behavior through directives and data attributes (for example tngCheckbox, tngToggle, tngAccordion).

Styled components in @tailng-ui/components are built on these primitives. You can use them directly or copy and own source via CLI.

1. Install TailNG

Option A — Primitives only (headless)

pnpm

bash
pnpm add @tailng-ui/primitives @tailng-ui/cdk

If you are building headless UI only, this is the required runtime install.

Option B — Full set (headless + styled + theme + icons)

pnpm

bash
pnpm add @tailng-ui/components @tailng-ui/primitives @tailng-ui/cdk @tailng-ui/theme @tailng-ui/icons

@tailng-ui/cdk is required by headless primitives. Add @tailng-ui/theme if you use TailNG theme tokens, and @tailng-ui/icons if you use the icon set.

2. Include components in your project

You do not need to install @tailng-ui/registry directly. The registry package is consumed by the tailng CLI for copy/source workflows.

Option A — Copy source into your app (shadcn-style, ownable)

Use tailng list to inspect the supported ownable registry items for the current package version before running tailng add.

CLI setup

bash
# Install CLI (once)
pnpm add -D tailng

# Or run without installing
pnpm dlx tailng add button
npx tailng add button

Add components

bash
tailng add <component-name>

tailng add button
tailng add checkbox
tailng add accordion
tailng add tooltip
tailng add drawer

CLI options

bash
--cwd <path>   # App root where files are generated (default: current directory)
--dry-run      # Show what would be created without writing files
--force        # Overwrite existing generated files

tailng add button --cwd apps/my-app
tailng add dialog --dry-run
tailng add checkbox --force

Import generated source

ts
import { TngButton } from './tailng-ui/button';

Option B — Use npm packages directly

Import primitives (and optionally styled components) from package exports and register them in standalone components or NgModules.

Direct package imports

ts
import { TngCheckbox, TngToggle } from '@tailng-ui/primitives';
// optional styled components
import { TngCheckboxComponent, TngButtonComponent } from '@tailng-ui/components';

3. Example: using headless primitives

Checkbox (headless)

ts
import { Component, signal } from '@angular/core';
import { TngCheckbox } from '@tailng-ui/primitives';

@Component({
  imports: [TngCheckbox],
  template: `
    <label>
      <input
        type="checkbox"
        tngCheckbox
        [checked]="checked()"
        (checkedChange)="checked.set($event)"
      />
      <span>Accept terms</span>
    </label>
  `,
})
export class MyForm {
  checked = signal(false);
}

Toggle (headless)

ts
import { Component, signal } from '@angular/core';
import { TngToggle } from '@tailng-ui/primitives';

@Component({
  imports: [TngToggle],
  template: `
    <button
      type="button"
      tngToggle
      [pressed]="on()"
      (pressedChange)="on.set($event)"
    >
      Toggle
    </button>
  `,
})
export class MyToolbar {
  on = signal(false);
}

Accordion (headless)

ts
import { Component, signal } from '@angular/core';
import {
  TngAccordion,
  TngAccordionItem,
  TngAccordionTrigger,
  TngAccordionPanel,
} from '@tailng-ui/primitives';

@Component({
  imports: [TngAccordion, TngAccordionItem, TngAccordionTrigger, TngAccordionPanel],
  template: `
    <section
      tngAccordion
      type="single"
      [value]="open()"
      (valueChange)="open.set($event)"
    >
      <article tngAccordionItem value="a">
        <button tngAccordionTrigger>Section A</button>
        <div tngAccordionPanel>Content A</div>
      </article>
      <article tngAccordionItem value="b">
        <button tngAccordionTrigger>Section B</button>
        <div tngAccordionPanel>Content B</div>
      </article>
    </section>
  `,
})
export class MyAccordion {
  open = signal<string | null>('a');
}

Style via data attributes (for example [data-state="open"], [data-checked]) or your own classes.

4. Theme (optional)

If you use @tailng-ui/theme, register provideTailngTheme() in your app configuration.

app.config.ts

ts
import { ApplicationConfig } from '@angular/core';
import { provideTailngTheme } from '@tailng-ui/theme';

export const appConfig: ApplicationConfig = {
  providers: [
    provideTailngTheme(),
  ],
};

5. CLI component aliases

You writeResolves to
slide-toggle switch
sidenav / sidebar / sheet drawer
expansion-panel accordion
spinner progress-spinner
snackbar / sonner toast

6. List available components

Use this command to see all valid values for tailng add <component-name>. The command output is the source of truth for the current registry surface.

List components

bash
tailng list
pnpm dlx tailng list