Components
Field
A set of composable primitives for building accessible form fields — label, description, and error message — that wrap any input.
This is your public display name.
Import
import {
AppField,
AppFieldLabel,
AppFieldDescription,
AppFieldError,
} from "@/components/primitives/AppField"Examples
Required
Pass required on AppFieldLabel to append a red asterisk.
We will never share your email.
Invalid
Use AppFieldError to show a validation error. Add border-destructive to the input to complete the visual.
Username must be at least 3 characters.
Grid
Compose multiple fields in a CSS grid for multi-column layouts.
With badge
Place an AppBadge next to the label to signal optional or beta fields.
Leave blank to use the default key.
Input group
Attach a static prefix or suffix to the input using a bordered span and rounded-l-none.
Enter your domain without the protocol.
Button group
Pair an input with a button using a flex wrapper.
Search group
Search across all available components.
API Reference
AppField
A flex column container with gap-1.5. Accepts all <div> attributes.
AppFieldLabel
| Prop | Type | Default | Description |
|---|---|---|---|
| required | boolean | false | Appends a red asterisk after the label text. |
| htmlFor | string | — | Associates the label with an input by id. |
| className | string | — | Additional Tailwind classes merged via cn(). |
AppFieldDescription & AppFieldError
Both render a <p> and accept all paragraph HTML attributes. AppFieldDescription uses text-muted-foreground. AppFieldError uses text-destructive.
Source
"use client"
import * as React from "react"
import { Label } from "@/components/ui/label"
import { cn } from "@/lib/utils"
function AppField({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
return <div className={cn("flex flex-col gap-1.5", className)} {...props} />
}
type AppFieldLabelProps = React.ComponentPropsWithoutRef<typeof Label> & {
required?: boolean
}
const AppFieldLabel = React.forwardRef<
React.ComponentRef<typeof Label>,
AppFieldLabelProps
>(({ className, required, children, ...props }, ref) => (
<Label ref={ref} className={cn(className)} {...props}>
{children}
{required && <span className="text-destructive">*</span>}
</Label>
))
AppFieldLabel.displayName = "AppFieldLabel"
const AppFieldDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
))
AppFieldDescription.displayName = "AppFieldDescription"
const AppFieldError = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p ref={ref} className={cn("text-sm text-destructive", className)} {...props} />
))
AppFieldError.displayName = "AppFieldError"
export { AppField, AppFieldLabel, AppFieldDescription, AppFieldError }
export type { AppFieldLabelProps }