CentercodeDitto
DittoPorygonAPI

Field Primitives

Standalone field components for visual consistency outside FormBlock

Overview

Field primitives provide the visual building blocks for form fields when you can't use FormBlock. They match the styling of FormBlock forms so participants see consistent forms regardless of how they're built.

Key Features

  • Visual consistency with FormBlock forms
  • Works without react-hook-form context
  • Five components: Wrapper, Label, Description, Error, HelpText
  • Composable with any input primitives

When to Use

Use Field Primitives When

  • Building forms in wizard steps controlled by parent state
  • Creating dynamic form renderers (FormEngineBlock)
  • Needing consistent field styling without FormBlock

Skip When

  • -Building standalone forms with Zod schemas (use FormBlock)
  • -Forms with auto-save or complex validation (use FormBlock)

Examples

Basic Field

Simple field with label and required indicator.

With Description

Field with description and help text for additional context.

We'll use this for notifications

Your email will never be shared

Error State

Field showing validation error.

Password must be at least 8 characters

Long Text Field

Textarea field with description and help text.

Tell us about yourself

Maximum 500 characters

Module Exports

ComponentPurpose
FieldWrapperContainer with consistent spacing (space-y-2)
FieldLabelLabel with optional required indicator
FieldDescriptionHelper text above the input (text-sm)
FieldErrorError message display (text-destructive)
FieldHelpTextAdditional hints below input (text-xs)

Props Reference

FieldLabel Props

PropTypeDefaultDescription
childrenReactNode-Label text content
requiredbooleanfalseShows red asterisk (*) indicator
htmlForstring-Associates label with input via id
classNamestring-Additional CSS classes

Usage

import { FieldWrapper, FieldLabel, FieldDescription, FieldError, FieldHelpText } from '@/ui/blocks';
import { Input, Textarea } from '@/ui/primitives';

// Basic field with label and input
<FieldWrapper>
  <FieldLabel htmlFor="name" required>Name</FieldLabel>
  <Input id="name" placeholder="Enter your name" />
</FieldWrapper>

// Field with description and help text
<FieldWrapper>
  <FieldLabel htmlFor="email">Email</FieldLabel>
  <FieldDescription>We'll use this for notifications</FieldDescription>
  <Input id="email" type="email" />
  <FieldHelpText>Your email will never be shared</FieldHelpText>
</FieldWrapper>

// Field with error state
<FieldWrapper>
  <FieldLabel htmlFor="password" required>Password</FieldLabel>
  <Input id="password" type="password" className="border-destructive" />
  <FieldError>Password must be at least 8 characters</FieldError>
</FieldWrapper>

// Long text field
<FieldWrapper>
  <FieldLabel htmlFor="bio">Bio</FieldLabel>
  <FieldDescription>Tell us about yourself</FieldDescription>
  <Textarea id="bio" rows={4} />
  <FieldHelpText>Maximum 500 characters</FieldHelpText>
</FieldWrapper>