Fieldset
Group related form controls with legends, descriptions, and actions
Import
import { AvFieldsetImports } from '@avesra/angular';Usage
Apply av-fieldset to a native <fieldset>. Compose av-fieldset-legend, av-fieldset-group, and av-fieldset-actions with shared form primitives like av-label, av-description, and av-field-error.
import { Component, signal } from '@angular/core';
import {
AvButtonComponent,
AvDescriptionComponent,
AvFieldErrorComponent,
AvFieldsetImports,
AvFormComponent,
AvInputComponent,
AvLabelComponent,
AvTextareaComponent,
} from '@avesra/angular';
@Component({
selector: 'app-fieldset-basic-demo',
imports: [
AvFormComponent,
AvFieldsetImports,
AvLabelComponent,
AvDescriptionComponent,
AvFieldErrorComponent,
AvInputComponent,
AvTextareaComponent,
AvButtonComponent,
],
host: { class: 'w-full max-w-96' },
template: `<form
av-form
class="w-full max-w-96"
aria-label="Profile settings"
(submit)="onSubmit($event)"
>
<fieldset av-fieldset>
<legend av-fieldset-legend>Profile Settings</legend>
<p av-description>Update your profile information.</p>
<div av-fieldset-group>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-name" required>Name</label>
<input
av-input
full-width
id="fieldset-name"
name="name"
placeholder="John Doe"
required
minlength="3"
[invalid]="nameError()"
(input)="onNameInput($event)"
/>
<p av-field-error [visible]="nameError()">Name must be at least 3 characters</p>
</div>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-email" required>Email</label>
<input
av-input
full-width
id="fieldset-email"
name="email"
type="email"
placeholder="john@example.com"
required
[invalid]="emailError()"
(input)="onEmailInput($event)"
/>
<p av-field-error [visible]="emailError()">Please enter a valid email address</p>
</div>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-bio" required>Bio</label>
<textarea
av-textarea
full-width
id="fieldset-bio"
name="bio"
rows="4"
placeholder="Tell us about yourself..."
required
minlength="10"
[invalid]="bioError()"
(input)="onBioInput($event)"
></textarea>
<p av-description>Minimum 10 characters</p>
<p av-field-error [visible]="bioError()">Bio must be at least 10 characters</p>
</div>
</div>
<div av-fieldset-actions>
<button av-button type="submit">Save changes</button>
<button av-button type="reset" variant="secondary">Cancel</button>
</div>
</fieldset>
</form>`,
})
export class FieldsetBasicDemo {
readonly nameError = signal(false);
readonly emailError = signal(false);
readonly bioError = signal(false);
onNameInput(event: Event): void {
const value = (event.target as HTMLInputElement).value;
this.nameError.set(value.length > 0 && value.length < 3);
}
onEmailInput(event: Event): void {
const value = (event.target as HTMLInputElement).value;
const isValid = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value);
this.emailError.set(value.length > 0 && !isValid);
}
onBioInput(event: Event): void {
const value = (event.target as HTMLTextAreaElement).value;
this.bioError.set(value.length > 0 && value.length < 10);
}
onSubmit(event: Event): void {
event.preventDefault();
alert('Form submitted successfully!');
}
}Anatomy
Import the Fieldset parts and compose them with attribute selectors on native elements.
<fieldset av-fieldset>
<legend av-fieldset-legend></legend>
<div av-fieldset-group>
<!-- form fields go here -->
</div>
<div av-fieldset-actions>
<!-- action buttons go here -->
</div>
</fieldset>In Surface
When used inside a Surface component, use variant="secondary" on form controls (Input, Textarea, etc.) to apply the lower emphasis variant suitable for surface backgrounds.
import { Component, signal } from '@angular/core';
import {
AvButtonComponent,
AvDescriptionComponent,
AvFieldErrorComponent,
AvFieldsetImports,
AvFormComponent,
AvInputComponent,
AvLabelComponent,
AvSurfaceComponent,
AvTextareaComponent,
} from '@avesra/angular';
@Component({
selector: 'app-fieldset-on-surface-demo',
imports: [
AvFormComponent,
AvFieldsetImports,
AvLabelComponent,
AvDescriptionComponent,
AvFieldErrorComponent,
AvInputComponent,
AvTextareaComponent,
AvButtonComponent,
AvSurfaceComponent,
],
host: { class: 'flex w-full items-center justify-center' },
template: `<div class="flex w-full items-center justify-center rounded-3xl bg-surface p-6">
<div av-surface class="w-full min-w-[380px] max-w-96 p-6">
<form av-form aria-label="Profile settings" (submit)="onSubmit($event)">
<fieldset av-fieldset class="w-full">
<legend av-fieldset-legend>Profile Settings</legend>
<p av-description>Update your profile information.</p>
<div av-fieldset-group>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-surface-name" required>Name</label>
<input
av-input
full-width
id="fieldset-surface-name"
name="name"
placeholder="John Doe"
variant="secondary"
required
minlength="3"
[invalid]="nameError()"
(input)="onNameInput($event)"
/>
<p av-field-error [visible]="nameError()">Name must be at least 3 characters</p>
</div>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-surface-email" required>Email</label>
<input
av-input
full-width
id="fieldset-surface-email"
name="email"
type="email"
placeholder="john@example.com"
variant="secondary"
required
[invalid]="emailError()"
(input)="onEmailInput($event)"
/>
<p av-field-error [visible]="emailError()">Please enter a valid email address</p>
</div>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-surface-bio" required>Bio</label>
<textarea
av-textarea
full-width
id="fieldset-surface-bio"
name="bio"
rows="4"
placeholder="Tell us about yourself..."
variant="secondary"
required
minlength="10"
[invalid]="bioError()"
(input)="onBioInput($event)"
></textarea>
<p av-description>Minimum 10 characters</p>
<p av-field-error [visible]="bioError()">Bio must be at least 10 characters</p>
</div>
</div>
<div av-fieldset-actions>
<button av-button type="submit">Save changes</button>
<button av-button type="reset" variant="tertiary">Cancel</button>
</div>
</fieldset>
</form>
</div>
</div>`,
})
export class FieldsetOnSurfaceDemo {
readonly nameError = signal(false);
readonly emailError = signal(false);
readonly bioError = signal(false);
onNameInput(event: Event): void {
const value = (event.target as HTMLInputElement).value;
this.nameError.set(value.length > 0 && value.length < 3);
}
onEmailInput(event: Event): void {
const value = (event.target as HTMLInputElement).value;
const isValid = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(value);
this.emailError.set(value.length > 0 && !isValid);
}
onBioInput(event: Event): void {
const value = (event.target as HTMLTextAreaElement).value;
this.bioError.set(value.length > 0 && value.length < 10);
}
onSubmit(event: Event): void {
event.preventDefault();
alert('Form submitted successfully!');
}
}Disabled
Set the disabled attribute on the fieldset to disable descendant form controls. The host also exposes data-disabled="true" for styling.
import { Component } from '@angular/core';
import {
AvButtonComponent,
AvDescriptionComponent,
AvFieldsetImports,
AvInputComponent,
AvLabelComponent,
} from '@avesra/angular';
@Component({
selector: 'app-fieldset-disabled-demo',
imports: [
AvFieldsetImports,
AvLabelComponent,
AvDescriptionComponent,
AvInputComponent,
AvButtonComponent,
],
host: { class: 'w-full max-w-96' },
template: `<fieldset av-fieldset disabled>
<legend av-fieldset-legend>Profile Settings</legend>
<p av-description>This fieldset is disabled.</p>
<div av-fieldset-group>
<div class="flex flex-col gap-1">
<label av-label for="fieldset-disabled-name">Name</label>
<input av-input full-width id="fieldset-disabled-name" name="name" value="John Doe" />
</div>
</div>
<div av-fieldset-actions>
<button av-button type="button">Save changes</button>
</div>
</fieldset>`,
})
export class FieldsetDisabledDemo {}Styling
Pass utility classes on host elements, or override BEM classes in @layer components.
CSS Classes
The Fieldset compound component exposes these CSS selectors:
.av-fieldset— Root container.av-fieldset__legend— Legend element.av-fieldset__field-group— Wrapper for grouped fields.av-fieldset__actions— Action bar below the fields
API
Fieldset root accepts a disabled input. Legend, group, and actions parts have no Angular inputs — project content via ng-content and style with classes on the host.
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | false | Disables the fieldset and descendant form controls. Sets data-disabled when true. |