AvesraAvesrabeta

Input

Primitive single-line text input. Apply av-input to a native <input> element. Accepts standard HTML attributes and implements ControlValueAccessor for Angular forms.

Import

import { AvInputComponent } from '@avesra/angular';

For labels, descriptions, and validation errors, compose with av-label, av-description, and av-field-error. For form-level validation and submission, see Form.

Usage

import { Component } from '@angular/core';
import { AvInputComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-basic-demo',
  imports: [AvInputComponent],
  host: { class: 'flex w-full items-center justify-center' },
  template: `<input
      av-input
      class="w-64"
      type="text"
      placeholder="Enter your name"
      aria-label="Name"
    />`,
})
export class InputBasicDemo {}

Anatomy

Input uses the av-input attribute selector on a native <input> element. Compose with shared label and error primitives as needed.

<label av-label for="name">Name</label>
<input av-input id="name" type="text" placeholder="Enter your name" />
<p av-description>Your public display name.</p>
<p av-field-error [visible]="false">Name is required</p>

Variants

The Input component supports two visual variants:

  • primary (default) — Standard styling with shadow, suitable for most use cases
  • secondary — Lower emphasis variant without shadow, suitable for use in Surface components
import { Component } from '@angular/core';
import { AvInputComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-variants-demo',
  imports: [AvInputComponent],
  host: { class: 'flex w-full max-w-[240px] flex-col gap-2' },
  template: `<input av-input full-width placeholder="Primary input" variant="primary" />
      <input av-input full-width placeholder="Secondary input" variant="secondary" />`,
})
export class InputVariantsDemo {}

In Surface

When used inside a Surface component, use variant="secondary" to apply the lower emphasis variant suitable for surface backgrounds.

import { Component } from '@angular/core';
import { AvInputComponent, AvSurfaceComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-on-surface-demo',
  imports: [AvInputComponent, AvSurfaceComponent],
  host: { class: 'flex w-full items-center justify-center' },
  template: `<div
      av-surface
      class="flex h-[180px] w-[280px] items-center justify-center rounded-3xl p-4"
    >
      <input
        av-input
        class="w-full"
        placeholder="Your name"
        variant="secondary"
        aria-label="Name"
      />
    </div>`,
})
export class InputOnSurfaceDemo {}

Full Width

Set full-width to expand the input to its container width.

import { Component } from '@angular/core';
import { AvInputComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-full-width-demo',
  imports: [AvInputComponent],
  host: { class: 'w-full max-w-[400px]' },
  template: `<input av-input full-width placeholder="Full width input" aria-label="Full width" />`,
})
export class InputFullWidthDemo {}

Input Types

Use the native type attribute for email, password, number, and other HTML input types. Pair with av-label via matching for and id.

import { Component } from '@angular/core';
import { AvInputComponent, AvLabelComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-input-types-demo',
  imports: [AvInputComponent, AvLabelComponent],
  host: { class: 'flex w-full max-w-xs flex-col gap-4' },
  template: `<div class="flex flex-col gap-1">
        <label av-label for="input-type-email">Email</label>
        <input
          av-input
          id="input-type-email"
          type="email"
          placeholder="jane&#64;example.com"
        />
      </div>
      <div class="flex flex-col gap-1">
        <label av-label for="input-type-number">Age</label>
        <input
          av-input
          id="input-type-number"
          type="number"
          min="0"
          placeholder="30"
        />
      </div>
      <div class="flex flex-col gap-1">
        <label av-label for="input-type-password">Password</label>
        <input
          av-input
          id="input-type-password"
          type="password"
          placeholder="••••••••"
        />
      </div>`,
})
export class InputInputTypesDemo {}

Controlled

Bind the value with [(ngModel)] (requires FormsModule) or formControlName / [formControl] with ReactiveFormsModule.

https://avesra.dev
import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AvInputComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-controlled-demo',
  imports: [FormsModule, AvInputComponent],
  host: { class: 'flex w-full max-w-xs flex-col gap-2' },
  template: `<input
      av-input
      class="w-full"
      type="text"
      placeholder="domain"
      aria-label="Domain"
      [(ngModel)]="value"
    />
    <span class="px-1 text-sm text-muted">https://{{ value || 'your-domain' }}</span>`,
})
export class InputControlledDemo {
  value = 'avesra.dev';
}

Styling

Passing Tailwind CSS classes

Pass utility classes on the host <input>, or compose with av-label for labeled fields.

import { Component } from '@angular/core';
import { AvInputComponent, AvLabelComponent } from '@avesra/angular';

@Component({
  selector: 'app-input-custom-styling-demo',
  imports: [AvInputComponent, AvLabelComponent],
  host: { class: 'flex w-full max-w-sm justify-center' },
  template: `<div class="flex flex-col gap-2">
      <label av-label for="custom-input">Project name</label>
      <input
        av-input
        id="custom-input"
        class="rounded-xl border border-border/70 bg-surface px-4 py-2 text-sm shadow-sm"
        placeholder="New web app"
      />
    </div>`,
})
export class InputCustomStylingDemo {}

Customizing the component classes

The base class .av-input powers every instance. Override it once with @layer components.

@layer components {
  .av-input {
    @apply rounded-lg border border-border bg-surface px-4 py-2 text-sm shadow-sm transition-colors;

    &:hover,
    &[data-hovered="true"] {
      @apply bg-surface-secondary border-border/80;
    }

    &:focus-visible,
    &[data-focus-visible="true"] {
      @apply border-accent ring-2 ring-accent/20;
    }

    &[data-invalid="true"] {
      @apply border-danger bg-danger-soft text-danger;
    }
  }
}

CSS Classes

  • .av-input — Native input element styling
  • .av-input--primary — Primary visual variant
  • .av-input--secondary — Secondary visual variant
  • .av-input--full-width — Full-width layout

Interactive States

  • Hover::hover or [data-hovered="true"]
  • Focus Visible::focus-visible or [data-focus-visible="true"]
  • Invalid:[data-invalid="true"] (also syncs with aria-invalid)
  • Disabled::disabled or [data-disabled="true"]
  • Read Only: native readonly / [aria-readonly="true"]

API

Input accepts all standard HTML <input> attributes plus the following Angular inputs. Use [(ngModel)] or reactive forms via ControlValueAccessor. For field-level validation UI, compose with av-label, av-description, av-field-error, and optionally Form.

PropTypeDefaultDescription
variant'primary' | 'secondary''primary'Visual variant. primary is the default style with shadow. secondary is a lower emphasis variant without shadow, suitable for use in surfaces.
full-widthbooleanfalseWhether the input should take full width of its container.
disabledbooleanfalseDisables the input.
invalidbooleanfalseMarks the input as invalid and sets aria-invalid / data-invalid.
ngModel / formControlNamestring—Bound value via ControlValueAccessor. Use FormsModule (ngModel) or ReactiveFormsModule.
typestring'text'Native input type (text, email, password, number, etc.).
placeholderstring—Placeholder text.
namestring—Name for form submission.
readonlybooleanfalseNative read-only attribute.
requiredbooleanfalseNative required attribute for HTML validation.

Made with ❤ by SyntaxHertz. Open source and available on GitHub.