Getting StartedInstall and bootstrap headless foundations 4
Quick Start
Installation
Plain CSS Setup
Tailwind Setup
FormHeadless input and selection contracts 9
Input
Checkbox
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