field

Composable building blocks for building accessible forms with labels, descriptions and errors.

PreviousNext
Payment Method

All transactions are secure and encrypted.

Enter your 16-digit card number.

Billing Address

The billing address associated with your payment method.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { ZardButtonComponent } from '@/shared/components/button/button.component';
import { ZardCheckboxComponent } from '@/shared/components/checkbox/checkbox.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';
import { ZardSelectImports } from '@/shared/components/select/select.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-field-default',
  imports: [
    ...ZardFieldImports,
    ZardButtonComponent,
    ZardCheckboxComponent,
    ZardInputComponent,
    ZardTextareaComponent,
    ZardSelectImports,
    FormsModule,
  ],
  template: `
    <div class="w-full min-w-md">
      <form>
        <div z-field-group>
          <fieldset z-field-set>
            <legend z-field-legend>Payment Method</legend>
            <p z-field-description>All transactions are secure and encrypted.</p>

            <div z-field-group>
              <div z-field>
                <label z-field-label for="checkout-card-name">Name on Card</label>
                <input z-input id="checkout-card-name" placeholder="Evil Rabbit" zSize="sm" required />
              </div>

              <div z-field>
                <label z-field-label for="checkout-card-number">Card Number</label>
                <input z-input id="checkout-card-number" placeholder="1234 5678 9012 3456" zSize="sm" required />
                <p z-field-description>Enter your 16-digit card number.</p>
              </div>

              <div class="grid grid-cols-3 gap-4">
                <div z-field>
                  <label z-field-label for="checkout-exp-month" class="w-fit">Month</label>
                  <z-select id="checkout-exp-month" zPlaceholder="MM" zSize="sm">
                    <z-select-item zValue="01">01</z-select-item>
                    <z-select-item zValue="02">02</z-select-item>
                    <z-select-item zValue="03">03</z-select-item>
                    <z-select-item zValue="04">04</z-select-item>
                    <z-select-item zValue="05">05</z-select-item>
                    <z-select-item zValue="06">06</z-select-item>
                    <z-select-item zValue="07">07</z-select-item>
                    <z-select-item zValue="08">08</z-select-item>
                    <z-select-item zValue="09">09</z-select-item>
                    <z-select-item zValue="10">10</z-select-item>
                    <z-select-item zValue="11">11</z-select-item>
                    <z-select-item zValue="12">12</z-select-item>
                  </z-select>
                </div>
                <div z-field>
                  <label z-field-label for="checkout-exp-year">Year</label>
                  <z-select id="checkout-exp-year" zPlaceholder="YYYY" zSize="sm">
                    <z-select-item zValue="2024">2024</z-select-item>
                    <z-select-item zValue="2025">2025</z-select-item>
                    <z-select-item zValue="2026">2026</z-select-item>
                    <z-select-item zValue="2027">2027</z-select-item>
                    <z-select-item zValue="2028">2028</z-select-item>
                    <z-select-item zValue="2029">2029</z-select-item>
                  </z-select>
                </div>
                <div z-field>
                  <label z-field-label for="checkout-cvv">CVV</label>
                  <input z-input id="checkout-cvv" placeholder="123" zSize="sm" required />
                </div>
              </div>
            </div>
          </fieldset>

          <z-field-separator />

          <fieldset z-field-set>
            <legend z-field-legend>Billing Address</legend>
            <p z-field-description>The billing address associated with your payment method.</p>

            <div z-field-group>
              <div z-field zOrientation="horizontal">
                <span
                  z-checkbox
                  zId="checkout-same-as-shipping"
                  [(ngModel)]="sameAsShipping"
                  name="sameAsShipping"
                ></span>
                <label z-field-label for="checkout-same-as-shipping" class="font-normal">
                  Same as shipping address
                </label>
              </div>
            </div>
          </fieldset>

          <fieldset z-field-set>
            <div z-field-group>
              <div z-field>
                <label z-field-label for="checkout-comments">Comments</label>
                <textarea
                  z-textarea
                  id="checkout-comments"
                  placeholder="Add any additional comments"
                  class="resize-none"
                ></textarea>
              </div>
            </div>
          </fieldset>

          <div z-field zOrientation="horizontal">
            <button z-button type="submit">Submit</button>
            <button z-button zType="outline" type="button">Cancel</button>
          </div>
        </div>
      </form>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldDefaultComponent {
  protected sameAsShipping = true;
}

Installation

Copy
npx zard-cli@latest add field

Usage

import { ZardFieldImports } from '@/shared/components/field/field.imports';
Copy
<div z-field-group>
  <div z-field>
    <label z-field-label for="email">Email</label>
    <input z-input id="email" placeholder="m@example.com" />
    <p z-field-description>We'll never share your email.</p>
  </div>
</div>
Copy

Examples

input

Choose a unique username for your account.

Must be at least 8 characters long.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-field-input',
  imports: [...ZardFieldImports, ZardInputComponent],
  template: `
    <div class="w-full min-w-xs">
      <fieldset z-field-set>
        <div z-field-group>
          <div z-field>
            <label z-field-label for="username">Username</label>
            <input z-input id="username" type="text" placeholder="Max Leiter" />
            <p z-field-description>Choose a unique username for your account.</p>
          </div>
          <div z-field>
            <label z-field-label for="password">Password</label>
            <p z-field-description>Must be at least 8 characters long.</p>
            <input z-input id="password" type="password" placeholder="••••••••" />
          </div>
        </div>
      </fieldset>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldInputComponent {}

textarea

Share your thoughts about our service.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardTextareaComponent } from '@/shared/components/textarea/textarea.component';

@Component({
  selector: 'z-demo-field-textarea',
  imports: [...ZardFieldImports, ZardTextareaComponent],
  template: `
    <div class="w-full min-w-xs">
      <fieldset z-field-set>
        <div z-field-group>
          <div z-field>
            <label z-field-label for="feedback">Feedback</label>
            <textarea z-textarea id="feedback" placeholder="Your feedback helps us improve..." rows="4"></textarea>
            <p z-field-description>Share your thoughts about our service.</p>
          </div>
        </div>
      </fieldset>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldTextareaComponent {}

select

Select your department or area of work.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardSelectImports } from '@/shared/components/select/select.imports';

@Component({
  selector: 'z-demo-field-select',
  imports: [...ZardFieldImports, ZardSelectImports],
  template: `
    <div class="w-full min-w-xs">
      <div z-field>
        <label z-field-label for="department">Department</label>
        <z-select zPlaceholder="Choose department" id="department" zSize="sm">
          <z-select-item zValue="engineering">Engineering</z-select-item>
          <z-select-item zValue="design">Design</z-select-item>
          <z-select-item zValue="marketing">Marketing</z-select-item>
          <z-select-item zValue="sales">Sales</z-select-item>
          <z-select-item zValue="support">Customer Support</z-select-item>
          <z-select-item zValue="hr">Human Resources</z-select-item>
          <z-select-item zValue="finance">Finance</z-select-item>
          <z-select-item zValue="operations">Operations</z-select-item>
        </z-select>
        <p z-field-description>Select your department or area of work.</p>
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldSelectComponent {}

slider

Volume

Set the playback volume ( 40 %).

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardSliderComponent } from '@/shared/components/slider/slider.component';

@Component({
  selector: 'z-demo-field-slider',
  imports: [...ZardFieldImports, ZardSliderComponent],
  template: `
    <div class="w-full min-w-xs">
      <div z-field>
        <div z-field-title>Volume</div>
        <p z-field-description>
          Set the playback volume (
          <span class="font-medium tabular-nums">{{ value() }}</span>
          %).
        </p>
        <z-slider
          class="mt-2 w-full"
          aria-label="Volume"
          [zDefault]="value()"
          [zMin]="0"
          [zMax]="100"
          [zStep]="1"
          (zSlideIndexChange)="value.set($event)"
        />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldSliderComponent {
  protected readonly value = signal([40]);
}

fieldset

Address Information

We need your address to deliver your order.

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardInputComponent } from '@/shared/components/input/input.component';

@Component({
  selector: 'z-demo-field-fieldset',
  imports: [...ZardFieldImports, ZardInputComponent],
  template: `
    <div class="w-full min-w-sm">
      <fieldset z-field-set>
        <legend z-field-legend>Address Information</legend>
        <p z-field-description>We need your address to deliver your order.</p>

        <div z-field-group>
          <div z-field>
            <label z-field-label for="street">Street Address</label>
            <input z-input id="street" type="text" placeholder="123 Main St" />
          </div>
          <div class="grid grid-cols-2 gap-4">
            <div z-field>
              <label z-field-label for="city">City</label>
              <input z-input id="city" type="text" placeholder="New York" />
            </div>
            <div z-field>
              <label z-field-label for="zip">Postal Code</label>
              <input z-input id="zip" type="text" placeholder="90502" />
            </div>
          </div>
        </div>
      </fieldset>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldFieldsetComponent {}

checkbox

Show these items on the desktop

Select the items you want to show on the desktop.

Your Desktop & Documents folders are being synced with iCloud Drive. You can access them from other devices.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { ZardCheckboxComponent } from '@/shared/components/checkbox/checkbox.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';

@Component({
  selector: 'z-demo-field-checkbox',
  imports: [...ZardFieldImports, ZardCheckboxComponent, FormsModule],
  template: `
    <div class="w-full min-w-xs">
      <div z-field-group>
        <fieldset z-field-set>
          <legend z-field-legend zVariant="label">Show these items on the desktop</legend>
          <p z-field-description>Select the items you want to show on the desktop.</p>

          <div z-field-group class="gap-3">
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="finder-hard-disks" [(ngModel)]="hardDisks" name="hardDisks"></span>
              <label z-field-label for="finder-hard-disks" class="font-normal">Hard disks</label>
            </div>
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="finder-external-disks" [(ngModel)]="externalDisks" name="externalDisks"></span>
              <label z-field-label for="finder-external-disks" class="font-normal">External disks</label>
            </div>
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="finder-cds" [(ngModel)]="cds" name="cds"></span>
              <label z-field-label for="finder-cds" class="font-normal">CDs, DVDs, and iPods</label>
            </div>
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="finder-servers" [(ngModel)]="servers" name="servers"></span>
              <label z-field-label for="finder-servers" class="font-normal">Connected servers</label>
            </div>
          </div>
        </fieldset>

        <z-field-separator />

        <div z-field zOrientation="horizontal">
          <span z-checkbox zId="finder-sync-folders" [(ngModel)]="syncFolders" name="syncFolders"></span>
          <div z-field-content>
            <label z-field-label for="finder-sync-folders">Sync Desktop &amp; Documents folders</label>
            <p z-field-description>
              Your Desktop &amp; Documents folders are being synced with iCloud Drive. You can access them from other
              devices.
            </p>
          </div>
        </div>
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldCheckboxComponent {
  protected hardDisks = true;
  protected externalDisks = false;
  protected cds = false;
  protected servers = false;
  protected syncFolders = true;
}

radio

Subscription Plan

Yearly and lifetime plans offer significant savings.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardRadioGroupImports } from '@/shared/components/radio-group/radio-group.imports';

@Component({
  selector: 'z-demo-field-radio',
  imports: [...ZardFieldImports, ...ZardRadioGroupImports, FormsModule],
  template: `
    <div class="w-full min-w-xs">
      <fieldset z-field-set>
        <legend z-field-legend zVariant="label">Subscription Plan</legend>
        <p z-field-description>Yearly and lifetime plans offer significant savings.</p>

        <z-radio-group class="gap-3" [(ngModel)]="plan">
          <div z-field zOrientation="horizontal">
            <z-radio zId="plan-monthly" value="monthly" />
            <label z-field-label for="plan-monthly" class="font-normal">Monthly ($9.99/month)</label>
          </div>
          <div z-field zOrientation="horizontal">
            <z-radio zId="plan-yearly" value="yearly" />
            <label z-field-label for="plan-yearly" class="font-normal">Yearly ($99.99/year)</label>
          </div>
          <div z-field zOrientation="horizontal">
            <z-radio zId="plan-lifetime" value="lifetime" />
            <label z-field-label for="plan-lifetime" class="font-normal">Lifetime ($299.99)</label>
          </div>
        </z-radio-group>
      </fieldset>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldRadioComponent {
  protected plan = 'monthly';
}

switch

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardSwitchComponent } from '@/shared/components/switch/switch.component';

@Component({
  selector: 'z-demo-field-switch',
  imports: [...ZardFieldImports, ZardSwitchComponent],
  template: `
    <div class="flex w-full min-w-xs justify-center">
      <div z-field zOrientation="horizontal" class="w-fit">
        <label z-field-label for="2fa">Multi-factor authentication</label>
        <z-switch zId="2fa" zSize="sm" />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldSwitchComponent {}

choice card

Compute Environment

Select the compute environment for your cluster.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { ZardFieldImports } from '@/shared/components/field/field.imports';
import { ZardRadioGroupImports } from '@/shared/components/radio-group/radio-group.imports';

@Component({
  selector: 'z-demo-field-choice-card',
  imports: [...ZardFieldImports, ...ZardRadioGroupImports, FormsModule],
  template: `
    <div class="w-full min-w-xs">
      <div z-field-group>
        <fieldset z-field-set>
          <legend z-field-legend zVariant="label">Compute Environment</legend>
          <p z-field-description>Select the compute environment for your cluster.</p>

          <z-radio-group class="gap-3" [(ngModel)]="env">
            <label z-field-label for="env-kubernetes">
              <div z-field zOrientation="horizontal">
                <div z-field-content>
                  <div z-field-title>Kubernetes</div>
                  <p z-field-description>Run GPU workloads on a K8s cluster.</p>
                </div>
                <z-radio zId="env-kubernetes" value="kubernetes" />
              </div>
            </label>

            <label z-field-label for="env-vm">
              <div z-field zOrientation="horizontal">
                <div z-field-content>
                  <div z-field-title>Virtual Machine</div>
                  <p z-field-description>Access a cluster to run GPU workloads.</p>
                </div>
                <z-radio zId="env-vm" value="vm" />
              </div>
            </label>
          </z-radio-group>
        </fieldset>
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldChoiceCardComponent {
  protected env = 'kubernetes';
}

field group

Get notified when ChatGPT responds to requests that take time, like research or image generation.

Get notified when tasks you've created have updates. Manage tasks

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { ZardCheckboxComponent } from '@/shared/components/checkbox/checkbox.component';
import { ZardFieldImports } from '@/shared/components/field/field.imports';

@Component({
  selector: 'z-demo-field-field-group',
  imports: [...ZardFieldImports, ZardCheckboxComponent, FormsModule],
  template: `
    <div class="w-full min-w-xs">
      <div z-field-group>
        <fieldset z-field-set>
          <label z-field-label>Responses</label>
          <p z-field-description>
            Get notified when ChatGPT responds to requests that take time, like research or image generation.
          </p>

          <div z-field-group data-slot="checkbox-group">
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="responses-push" [(ngModel)]="responsesPush" name="responsesPush" zDisabled></span>
              <label z-field-label for="responses-push" class="font-normal">Push notifications</label>
            </div>
          </div>
        </fieldset>

        <z-field-separator />

        <fieldset z-field-set>
          <label z-field-label>Tasks</label>
          <p z-field-description>
            Get notified when tasks you've created have updates.
            <a href="#">Manage tasks</a>
          </p>

          <div z-field-group data-slot="checkbox-group">
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="tasks-push" [(ngModel)]="tasksPush" name="tasksPush"></span>
              <label z-field-label for="tasks-push" class="font-normal">Push notifications</label>
            </div>
            <div z-field zOrientation="horizontal">
              <span z-checkbox zId="tasks-email" [(ngModel)]="tasksEmail" name="tasksEmail"></span>
              <label z-field-label for="tasks-email" class="font-normal">Email notifications</label>
            </div>
          </div>
        </fieldset>
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldFieldGroupComponent {
  protected responsesPush = true;
  protected tasksPush = false;
  protected tasksEmail = false;
}

API Reference

z-fieldComponent

A field container that wraps a label, control and optional description / error.

PropertyDescriptionTypeDefault
[zOrientation] Layout direction of the field 'vertical' | 'horizontal' | 'responsive' 'vertical'

z-field-setComponent

A semantic <fieldset> wrapper that vertically stacks fields with consistent spacing.

PropertyDescriptionTypeDefault

z-field-legendComponent

Legend element for a field-set. Use the label variant when grouping inline controls.

PropertyDescriptionTypeDefault
[zVariant] Visual size of the legend 'legend' | 'label' 'legend'

z-field-groupComponent

Group of fields with consistent vertical spacing. Acts as a container query parent for responsive fields.

PropertyDescriptionTypeDefault

z-field-contentComponent

Wrapper for the textual portion of a field (title + description) when used in horizontal layouts.

PropertyDescriptionTypeDefault

z-field-labelComponent

Label for a form control. Use on <label> for proper semantics, or as <z-field-label>.

PropertyDescriptionTypeDefault
[for] Associates the label with a form control by referencing the control's id. string

z-field-titleComponent

Non-interactive title for a field (e.g. when wrapping a checkbox/radio along with description).

PropertyDescriptionTypeDefault

z-field-descriptionComponent

Helper text rendered below or beside a field control.

PropertyDescriptionTypeDefault

z-field-separatorComponent

Horizontal separator with optional centered content.

PropertyDescriptionTypeDefault
[zContent] Optional text or template displayed above the separator line string | TemplateRef<void> ''

z-field-errorComponent

Renders a single error message or a list of errors. Falls back to projected content when no errors are provided.

PropertyDescriptionTypeDefault
[zErrors] Array of error objects with an optional `message` string. Duplicate messages are removed. Array<{ message?: string }> []
github iconwhatsapp icondiscord iconX icon

Made with in Brazil. Open source and available on GitHub .