Skip to content
Navigation

Field

Added 14 October 2026

React

Codecomponents/react/field-demo.tsx
import {
    Field,
    FieldContent,
    FieldDescription,
    FieldError,
    FieldGroup,
    FieldLabel,
    FieldLegend,
    FieldSeparator,
    FieldSet,
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@stroeer-labs/design-library/react';

const formats = [
    {label: 'Billboard', value: 'billboard'},
    {label: 'City Light', value: 'city-light'},
    {label: 'Mega Light', value: 'mega-light'},
];

const budgets = [
    {label: 'Low', value: 'low'},
    {label: 'Mid', value: 'mid'},
    {label: 'High', value: 'high'},
];

export function FieldDemo() {
    return (
        <div className="w-full max-w-md">
            <FieldSet>
                <FieldLegend>Campaign details</FieldLegend>
                <FieldDescription>Configure how your campaign is booked.</FieldDescription>
                <FieldGroup>
                    <Field orientation="vertical">
                        <FieldLabel htmlFor="field-format">Format</FieldLabel>
                        <FieldContent>
                            <Select items={formats}>
                                <SelectTrigger id="field-format" className="w-full">
                                    <SelectValue placeholder="Select a format" />
                                </SelectTrigger>
                                <SelectContent>
                                    {formats.map((f) => (
                                        <SelectItem key={f.value} value={f.value}>
                                            {f.label}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <FieldDescription>Choose the inventory format to book.</FieldDescription>
                        </FieldContent>
                    </Field>

                    <FieldSeparator>Or</FieldSeparator>

                    <Field orientation="vertical">
                        <FieldLabel htmlFor="field-budget">Budget tier</FieldLabel>
                        <FieldContent>
                            <Select items={budgets}>
                                <SelectTrigger id="field-budget" aria-invalid aria-describedby="field-budget-error" className="w-full">
                                    <SelectValue placeholder="Select a budget tier" />
                                </SelectTrigger>
                                <SelectContent>
                                    {budgets.map((b) => (
                                        <SelectItem key={b.value} value={b.value}>
                                            {b.label}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                            <FieldError id="field-budget-error">A budget tier is required.</FieldError>
                        </FieldContent>
                    </Field>

                    <Field orientation="horizontal">
                        <FieldLabel>Auto-renew</FieldLabel>
                        <FieldContent>
                            <FieldDescription>Renew the booking each period.</FieldDescription>
                        </FieldContent>
                    </Field>
                </FieldGroup>
            </FieldSet>
        </div>
    );
}

Angular

Codecomponents/angular/field-demo.ts
import {Component} from '@angular/core';
import {HlmFieldImports, HlmSelectImports} from '@stroeer-labs/design-library/angular';

@Component({
    selector: 'dl-field-demo',
    standalone: true,
    imports: [HlmFieldImports, HlmSelectImports],
    template: `
    <div class="w-full max-w-md">
      <fieldset hlmFieldSet>
        <legend hlmFieldLegend>Campaign details</legend>
        <p hlmFieldDescription>Configure how your campaign is booked.</p>
        <div hlmFieldGroup>
          <div hlmField orientation="vertical">
            <label hlmFieldLabel>Format</label>
            <div hlmFieldContent>
              <hlm-select [itemToString]="formatToString">
                <hlm-select-trigger class="w-full">
                  <hlm-select-value placeholder="Select a format" />
                </hlm-select-trigger>
                <hlm-select-content *hlmSelectPortal>
                  @for (item of formats; track item.value) {
                    <hlm-select-item [value]="item.value">{{ item.label }}</hlm-select-item>
                  }
                </hlm-select-content>
              </hlm-select>
              <p hlmFieldDescription>Choose the inventory format to book.</p>
            </div>
          </div>

          <hlm-field-separator>Or</hlm-field-separator>

          <div hlmField orientation="vertical">
            <label hlmFieldLabel>Budget tier</label>
            <div hlmFieldContent>
              <hlm-select [itemToString]="budgetToString">
                <hlm-select-trigger forceInvalid class="w-full">
                  <hlm-select-value placeholder="Select a budget tier" />
                </hlm-select-trigger>
                <hlm-select-content *hlmSelectPortal>
                  @for (item of budgets; track item.value) {
                    <hlm-select-item [value]="item.value">{{ item.label }}</hlm-select-item>
                  }
                </hlm-select-content>
              </hlm-select>
              <hlm-field-error forceShow>A budget tier is required.</hlm-field-error>
            </div>
          </div>

          <div hlmField orientation="horizontal">
            <label hlmFieldLabel>Auto-renew</label>
            <div hlmFieldContent>
              <p hlmFieldDescription>Renew the booking each period.</p>
            </div>
          </div>
        </div>
      </fieldset>
    </div>
  `,
})
export class FieldDemoComponent {
    readonly formats = [
        {label: 'Billboard', value: 'billboard'},
        {label: 'City Light', value: 'city-light'},
        {label: 'Mega Light', value: 'mega-light'},
    ];

    readonly budgets = [
        {label: 'Low', value: 'low'},
        {label: 'Mid', value: 'mid'},
        {label: 'High', value: 'high'},
    ];

    readonly formatToString = (value: string) => this.formats.find((f) => f.value === value)?.label || '';
    readonly budgetToString = (value: string) => this.budgets.find((b) => b.value === value)?.label || '';
}