Input
A native input wrapped in a styled flex container that drives its focus, disabled and read-only look purely from the input's own state, with optional icon slots and a character counter.
InputGroup wraps a native <input> in a styled flex container — no JavaScript state duplication, every
visual state (focus, disabled, read-only) is driven by CSS has-[] selectors reading the native control's own
state.
Minimal example
A plain text field
import { Component } from "@angular/core";
import { InputComponent, InputControlDirective } from "@sinequa/galactik";
@Component({
selector: "sample-component",
imports: [InputComponent, InputControlDirective],
template: `
<input-group>
<input input-control type="text" placeholder="Enter your name" />
</input-group>
`,
})
export class SampleComponent {}Recipes
Icon, character counter and validation together
An email field combining an icon, a live counter and an error scheme
import { Component, computed, signal } from "@angular/core";
import { InputComponent, InputControlDirective, InputCounterComponent } from "@sinequa/galactik";
@Component({
selector: "advanced-email-field",
imports: [InputComponent, InputControlDirective, InputCounterComponent],
template: `
<div class="flex flex-col gap-1">
<input-group [scheme]="scheme()">
<input
input-control
type="email"
maxlength="60"
placeholder="you@example.com"
[value]="email()"
(input)="email.set($any($event.target).value)" />
<input-counter [scheme]="scheme()">{{ email().length }} / 60</input-counter>
</input-group>
@if (scheme() === 'error') {
<span class="text-(length:--size-sm) text-(--font-error-base)">Please enter a valid email address.</span>
}
</div>
`,
})
export class AdvancedEmailFieldComponent {
email = signal("");
scheme = computed<"default" | "error">(() =>
this.email().length === 0 || this.email().includes("@") ? "default" : "error",
);
}Options
Prop
Type