Getting StartedInstall and bootstrap headless foundations 4
LayoutHeadless structural primitives for expandable and container patterns 6
OverlayHeadless modal and floating layer behavior 3
FeedbackHeadless notification and status communication patterns 5
FormHeadless input and selection contracts 17
UtilityReusable action, identity, and clipboard behavior 6
NavigationHeadless trails, trees, menus, and command surfaces 7

Input Group

<tng-input-group> is the headless shell primitive for one projected input[tngInput] or textarea[tngInput] plus optional tngPrefix/tngSuffix content.

Reach for it when you want the layout, state mirroring, and slot structure of a grouped field while keeping complete ownership of the surface styles.

Imports

Headless imports

ts
import { TngInput, TngInputGroup, TngPrefix, TngSuffix } from '@tailng-ui/primitives';
import { TngIcon } from '@tailng-ui/icons';

Basic composition

The primitive expects exactly one projected control with tngInput. Leading and trailing regions render only when matching slot content exists.

Minimal input group

html
<tng-input-group>
  <input tngInput type="text" placeholder="Project name" />
</tng-input-group>

Grouped search field

html
<tng-input-group>
  <span tngPrefix aria-hidden="true">
    <tng-icon icon="search"></tng-icon>
  </span>
  <input tngInput type="search" placeholder="Search docs..." />
  <span tngSuffix aria-hidden="true">Ctrl+K</span>
</tng-input-group>

Grouped field variants

Compare the same headless input-group composition across plain CSS and Tailwind CSS while keeping the shell primitive in charge of layout and state mirroring.

Input Group (Plain-CSS)

Mirrored state contract

tngInputGroup mirrors focus, invalid, disabled, readonly, and slot-presence state onto the host. That gives you stable styling hooks without owning the shell layout plumbing yourself.

Host state selectors

html
<tng-input-group class="docs-headless-search-shell">
  <input tngInput type="email" aria-invalid="true" />
</tng-input-group>

.docs-headless-search-shell[data-focused] {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}

.docs-headless-search-shell[data-invalid] {
  border-color: #dc2626;
}

Accessibility baseline

  • Give the projected control a real accessible name with a label or ARIA.
  • Mark decorative prefix and suffix content as aria-hidden="true".
  • Trailing buttons should keep their own explicit accessible labels.

Accessible grouped field

html
<label for="docs-search">Search docs</label>
<tng-input-group>
  <span tngPrefix aria-hidden="true">
    <tng-icon icon="search"></tng-icon>
  </span>
  <input id="docs-search" tngInput type="search" />
  <button tngSuffix type="button" aria-label="Clear search">Clear</button>
</tng-input-group>