Styling contract
Input styling is slot/state driven. Style against stable data attributes for visual appearance, while tngInputGroup provides the base structural layout for grouped composition.
CSS contracts
Use these selectors as the public styling surface for tngInput and tngInputGroup. The primitive owns the internal leading/control/trailing layout, and consumers style the group surface and projected content.
Slot selectors
| Selector | Scope | Purpose |
|---|---|---|
[data-slot="input"] | Input host | Base control styles: typography, background, placeholder, and visual reset. |
[data-slot="input-group"] | Group container | Container shell: border, radius, background, focus container effects, and surface styling. |
[data-slot="input-leading"] | Projected prefix element | Style the actual prefix/adornment content, such as text or an icon button. |
[data-slot="input-trailing"] | Projected suffix element | Style the actual suffix/action content, such as a clear button or helper meta. |
[data-slot="input-group-leading"] | Leading region | Optional structural hook for the generated leading region. Normal grouped layout does not require consumer styling here. |
[data-slot="input-group-control"] | Control region | Structural hook for the generated flexible control region. Available for optional customization. |
[data-slot="input-group-trailing"] | Trailing region | Optional structural hook for the generated trailing region. Normal suffix placement does not require consumer styling here. |
State hooks
| State attribute | Applied on | Use case |
|---|---|---|
[data-focused] | Group host | Focus ring, focused border, and elevated active styling. |
[data-invalid] | Control and group host | Error border/message color system integration. |
[data-disabled] | Control and group host | Muted visuals, cursor changes, and interaction lock styles. |
[data-readonly] | Control and group host | Readonly visual treatment separate from disabled state. |
[data-has-leading] | Group host | Optional visual adjustments when leading content is present. |
[data-has-trailing] | Group host | Optional visual adjustments when trailing content is present. |
Public input tokens
| Token | Controls |
|---|---|
--tng-input-gap | Inline spacing between the leading region, control region, and trailing region. |
--tng-input-bg | Grouped input background color. |
--tng-input-border | Grouped input border color. |
--tng-input-radius | Grouped input border radius. |
--tng-input-fg | Foreground color inherited by the grouped shell and projected input. |
--tng-input-min-height | Minimum height of the grouped shell. |
--tng-input-px | Inline padding applied to the grouped shell. |
--tng-input-py | Block padding applied to the grouped shell. |
--tng-input-focus-ring | Focus ring color used when the group emits [data-focused]. |
Layout note
tngInputGroup provides the base grouped layout for leading, control, and trailing regions. Consumers typically style the group surface, the projected input, and the projected prefix/suffix content. Direct wrapper styling should be optional, not required for normal grouped composition.
In most cases, consumers style [data-slot="input-group"], [data-slot="input"], [data-slot="input-leading"], and [data-slot="input-trailing"]. The generated group region wrappers [data-slot="input-group-leading"], [data-slot="input-group-control"], and [data-slot="input-group-trailing"] are available as optional structural hooks, but standard grouped layout does not require styling them directly.
User scenario style examples
Account profile form styling patterns across headless plain CSS and headless Tailwind strategies.
Account profile form
Account profile form
Different styling pattern examples
Use these patterns as building blocks when documenting forms, search bars, and settings surfaces.
Theme token override
Prefer overriding the public input tokens on the host instead of reaching into internal DOM for routine visual changes.
Theme token override
.settings-input {
--tng-input-gap: 0.55rem;
--tng-input-bg: var(--tng-semantic-background-base);
--tng-input-border: color-mix(in srgb, var(--tng-semantic-border-strong) 82%, transparent);
--tng-input-radius: 0.75rem;
--tng-input-fg: var(--tng-semantic-foreground-primary);
--tng-input-min-height: 2.5rem;
--tng-input-px: 0.8rem;
--tng-input-py: 0;
--tng-input-focus-ring: color-mix(in srgb, var(--tng-semantic-accent-brand) 20%, transparent);
}
Density control
Tune field density through the token surface instead of replacing the shell layout.
Density control
.compact-input {
--tng-input-min-height: 2.2rem;
--tng-input-px: 0.68rem;
--tng-input-gap: 0.45rem;
--tng-input-radius: 0.65rem;
}
State-aware shell
Use the emitted state attrs when the visual treatment must react to focus, invalid, or disabled state.
State-aware shell
.settings-input {
--tng-input-border: color-mix(in srgb, var(--tng-semantic-border-strong) 82%, transparent);
--tng-input-focus-ring: color-mix(in srgb, var(--tng-semantic-accent-brand) 20%, transparent);
}
.settings-input [data-slot="input-group"][data-invalid] {
border-color: var(--tng-semantic-accent-danger);
}
.settings-input [data-slot="input-group"][data-disabled] {
opacity: 0.58;
cursor: not-allowed;
}