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-preview',
  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 ZardDemoFieldPreviewComponent {
  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

Stack z-field-label, z-input and z-field-description inside z-field; z-field-description can be placed above or below the control depending on where it sits in the template.

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

Compose z-field with z-field-label, z-textarea and z-field-description the same way as an input.

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

Compose z-field with z-field-label, z-select and z-field-description to label and describe a select control.

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

Use z-field-title instead of z-field-label when the control has no natural for target, and update z-field-description live from the z-slider's (zSlideIndexChange) output.
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"
          [zValue]="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

Group related z-fields under z-field-set with a z-field-legend and a shared z-field-description; lay fields out side by side with a plain grid inside z-field-group.
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

Set zOrientation="horizontal" on z-field to put z-checkbox before its z-field-label; use z-field-content when a checkbox needs both a title and a description.
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

Pair each z-radio (inside z-radio-group) with a horizontal z-field and z-field-label, wrapped in a z-field-set whose z-field-legend uses the label variant.
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

Pair z-switch with z-field-label and zOrientation="horizontal" on z-field for a single inline toggle.
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" />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldSwitchComponent {}

choice card

Wrap z-field inside z-field-label (instead of the other way around) to make the whole card clickable, and use z-field-content for the title and description next to a z-radio.
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

Stack z-field-set blocks with z-field-group and divide them with z-field-separator; nest a data-slot="checkbox-group" z-field-group for tighter spacing between related checkboxes.

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;
}

invalid

Bind the data-invalid attribute on z-field and aria-invalid on the control to a reactive form control's invalid && touched state, then render the message from control.hasError(...) inside z-field-error — the pattern every other invalid-state demo in the library builds on.

We'll only use this to send you a receipt.

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';

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

@Component({
  selector: 'z-demo-field-invalid',
  imports: [...ZardFieldImports, ZardInputComponent, ReactiveFormsModule],
  template: `
    <div class="w-full min-w-xs">
      <form [formGroup]="signupForm">
        @let emailControl = signupForm.controls.email;
        @let emailInvalid = emailControl.invalid && emailControl.touched;
        <div z-field [attr.data-invalid]="emailInvalid || null">
          <label z-field-label for="signup-email">Email</label>
          <input
            z-input
            type="email"
            id="signup-email"
            placeholder="you@example.com"
            formControlName="email"
            [attr.aria-invalid]="emailInvalid || null"
          />
          @if (emailInvalid) {
            <z-field-error>
              @if (emailControl.hasError('required')) {
                Email is required.
              } @else if (emailControl.hasError('email')) {
                Enter a valid email address.
              }
            </z-field-error>
          } @else {
            <p z-field-description>We'll only use this to send you a receipt.</p>
          }
        </div>
      </form>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldInvalidComponent {
  protected readonly signupForm = new FormGroup({
    email: new FormControl('', { nonNullable: true, validators: [Validators.required, Validators.email] }),
  });
}

rtl

To enable RTL support in zard/ui, see the RTL configuration guide.
الملف الشخصي

حدّث بياناتك الشخصية.

هكذا يظهر اسمك للآخرين.

احصل على تحديثات المنتج مرة واحدة شهريًا.

// You will notice this example is rendered inside a wrapper that sets the dir and data-lang attributes, and
// reads its text from a translations helper. This is because this site is not RTL by default.
// In your application you won't need either: set dir="rtl" on <html> (or use the CDK Dir directive on a subtree)
// and write the text of your own language. See the RTL guide: https://zardui.com/docs/rtl

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

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 { injectRtlTranslation, type ZardRtlTranslations } from '@/shared/demo-utils/rtl-translation';

const translations: ZardRtlTranslations<{
  legend: string;
  description: string;
  name: string;
  namePlaceholder: string;
  nameHelp: string;
  email: string;
  emailPlaceholder: string;
  newsletter: string;
  newsletterHelp: string;
}> = {
  en: {
    dir: 'ltr',
    values: {
      legend: 'Profile',
      description: 'Update your personal details.',
      name: 'Full name',
      namePlaceholder: 'Jane Doe',
      nameHelp: 'This is how your name appears to others.',
      email: 'Email',
      emailPlaceholder: 'jane@example.com',
      newsletter: 'Subscribe to the newsletter',
      newsletterHelp: 'Get product updates once a month.',
    },
  },
  ar: {
    dir: 'rtl',
    values: {
      legend: 'الملف الشخصي',
      description: 'حدّث بياناتك الشخصية.',
      name: 'الاسم الكامل',
      namePlaceholder: 'محمد أحمد',
      nameHelp: 'هكذا يظهر اسمك للآخرين.',
      email: 'البريد الإلكتروني',
      emailPlaceholder: 'mohamed@example.com',
      newsletter: 'الاشتراك في النشرة البريدية',
      newsletterHelp: 'احصل على تحديثات المنتج مرة واحدة شهريًا.',
    },
  },
  he: {
    dir: 'rtl',
    values: {
      legend: 'פרופיל',
      description: 'עדכנו את הפרטים האישיים שלכם.',
      name: 'שם מלא',
      namePlaceholder: 'ישראל ישראלי',
      nameHelp: 'כך השם שלכם מופיע לאחרים.',
      email: 'אימייל',
      emailPlaceholder: 'israel@example.com',
      newsletter: 'הרשמה לניוזלטר',
      newsletterHelp: 'קבלו עדכוני מוצר פעם בחודש.',
    },
  },
};

@Component({
  selector: 'z-demo-field-rtl',
  imports: [...ZardFieldImports, ZardCheckboxComponent, ZardInputComponent],
  template: `
    <div class="w-full min-w-xs">
      <fieldset z-field-set>
        <legend z-field-legend>{{ i18n.t().legend }}</legend>
        <p z-field-description>{{ i18n.t().description }}</p>

        <div z-field-group>
          <div z-field>
            <label z-field-label for="field-rtl-name">{{ i18n.t().name }}</label>
            <input z-input id="field-rtl-name" [placeholder]="i18n.t().namePlaceholder" />
            <p z-field-description>{{ i18n.t().nameHelp }}</p>
          </div>

          <div z-field>
            <label z-field-label for="field-rtl-email">{{ i18n.t().email }}</label>
            <input z-input id="field-rtl-email" type="email" [placeholder]="i18n.t().emailPlaceholder" />
          </div>

          <div z-field zOrientation="horizontal">
            <span z-checkbox zId="field-rtl-newsletter"></span>
            <div z-field-content>
              <label z-field-label for="field-rtl-newsletter">{{ i18n.t().newsletter }}</label>
              <p z-field-description>{{ i18n.t().newsletterHelp }}</p>
            </div>
          </div>
        </div>
      </fieldset>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoFieldRtlComponent {
  protected readonly i18n = injectRtlTranslation(translations);
}

API Reference

z-fieldComponent

A field container that wraps a label, control and optional description / error, exposed as `role="group"`. Set the `data-invalid` attribute (e.g. `[attr.data-invalid]="control.invalid && control.touched"`) to switch the whole field into its destructive styling; pair it with `aria-invalid` on the control itself.

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''
[zOrientation] Layout direction of the field: vertical stacks, horizontal aligns label and control in a row, responsive stacks until the parent `z-field-group` container query crosses its `@md` breakpoint. 'vertical' | 'horizontal' | 'responsive' 'vertical'

z-field-setComponent

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

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''

z-field-legendComponent

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

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''
[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
[class] Custom CSS classes ClassValue ''

z-field-contentComponent

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

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''

z-field-labelComponent

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

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''
[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
[class] Custom CSS classes ClassValue ''

z-field-descriptionComponent

Helper text rendered below or beside a field control.

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''

z-field-separatorComponent

Horizontal separator with optional centered content.

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

z-field-errorComponent

Renders validation messages for a field, exposed as `role="alert"`. Pass the errors to show through `[zErrors]` — e.g. from a reactive form control's `errors` — or project static content when there is nothing to compute.

PropertyDescriptionTypeDefault
[class] Custom CSS classes ClassValue ''
[zErrors] Array of error objects with an optional `message` string. A single entry renders inline, multiple render as a bulleted list, and duplicate messages are removed. Falls back to projected content when the array is empty. ReadonlyArray<{ message?: string } | undefined> []
github iconwhatsapp icondiscord iconX icon

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