Field
Layout and labels for one form field.
<field.Field>
<field.FieldLabel for="field-email">Email</field.FieldLabel>
<input.Input id="field-email" type="email" placeholder="you@example.com" />
<field.FieldDescription>We never share your email.</field.FieldDescription>
</field.Field>Installation
Run the command in the app module.
gx add fieldThe command also installs input.
The command writes these files.
| File | Path in the app |
|---|---|
Field.gx |
ui/field/Field.gx |
FieldLabel.gx |
ui/field/FieldLabel.gx |
FieldDescription.gx |
ui/field/FieldDescription.gx |
FieldError.gx |
ui/field/FieldError.gx |
FieldGroup.gx |
ui/field/FieldGroup.gx |
FieldSet.gx |
ui/field/FieldSet.gx |
FieldLegend.gx |
ui/field/FieldLegend.gx |
Field.fixtures.go |
ui/field/Field.fixtures.go |
styles.go |
ui/field/styles.go |
FieldDescription.fixtures.go |
ui/field/FieldDescription.fixtures.go |
FieldError.fixtures.go |
ui/field/FieldError.fixtures.go |
FieldGroup.fixtures.go |
ui/field/FieldGroup.fixtures.go |
FieldLabel.fixtures.go |
ui/field/FieldLabel.fixtures.go |
FieldLegend.fixtures.go |
ui/field/FieldLegend.fixtures.go |
FieldSet.fixtures.go |
ui/field/FieldSet.fixtures.go |
FieldContent.gx |
ui/field/FieldContent.gx |
FieldContent.fixtures.go |
ui/field/FieldContent.fixtures.go |
FieldTitle.gx |
ui/field/FieldTitle.gx |
FieldTitle.fixtures.go |
ui/field/FieldTitle.fixtures.go |
FieldSeparator.gx |
ui/field/FieldSeparator.gx |
FieldSeparator.fixtures.go |
ui/field/FieldSeparator.fixtures.go |
Install input first.
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package field
props {
// Orientation sets the direction of the label and the control: Vertical, Horizontal or
// Responsive. Responsive is vertical in a narrow field group and horizontal in a wide one.
Orientation Orientation = Vertical
// Invalid sets data-invalid on the field. The field text takes the destructive colour.
Invalid bool = false
// Disabled sets data-disabled on the field. The label and the title fade.
Disabled bool = false
// Class adds classes to the root element.
Class string = ""
// Children is the content of the field: the label, the control and the description.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div role="group" data-slot="field" data-orientation={p.orientation()} class={gx.Cx("group/field flex w-full gap-3 data-[invalid=true]:text-destructive", orientationClass[Orientation(p.orientation())], p.Class)} {...p.attrs()}>{p.Children}</div>package field
props {
// For is the id of the control that the label names. Empty omits the for attribute.
For string = ""
// Class adds classes to the root element.
Class string = ""
// Children is the label text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<label data-slot="field-label" class={gx.Cx("flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50 has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4 has-[:checked]:border-primary has-[:checked]:bg-primary/5 dark:has-[:checked]:bg-primary/10", p.Class)} {...p.attrs()}>{p.Children}</label>package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the description text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<p data-slot="field-description" class={gx.Cx("text-sm leading-normal font-normal text-muted-foreground group-has-[[data-orientation=horizontal]]/field:text-balance last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5 [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary", p.Class)} {...p.Attrs}>{p.Children}</p>package field
props {
// Errors holds the error messages. Empty and repeated messages do not show; two or more
// show as a list.
Errors []string = nil
// Class adds classes to the root element.
Class string = ""
// Children is the content of the error. It replaces Errors.
Children gx.Node = nil
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
if p.Children != nil || len(p.messages()) > 0 {
<div role="alert" data-slot="field-error" class={gx.Cx("text-sm font-normal text-destructive", p.Class)} {...p.Attrs}>
if p.Children != nil {
{p.Children}
} else if len(p.messages()) == 1 {
{p.messages()[0]}
} else {
<ul class="ml-4 flex list-disc flex-col gap-1">
for _, message := range p.messages() {
<li>{message}</li>
}
</ul>
}
</div>
}package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the group: the fields, the field sets and the separators.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="field-group" class={gx.Cx("group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4", p.Class)} {...p.Attrs}>{p.Children}</div>package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the field set.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<fieldset data-slot="field-set" class={gx.Cx("flex flex-col gap-6 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", p.Class)} {...p.Attrs}>{p.Children}</fieldset>package field
props {
// Variant sets the text size: Legend or Label. Label is the smaller size.
Variant Variant = Legend
// Class adds classes to the root element.
Class string = ""
// Children is the legend text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<legend data-slot="field-legend" data-variant={p.variant()} class={gx.Cx("mb-3 font-medium data-[variant=legend]:text-base data-[variant=label]:text-sm", p.Class)} {...p.Attrs}>{p.Children}</legend>package field
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/input"
)
var FieldFixtures = gx.Fixtures[FieldProps]{
"LabelAndInput": {Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "field-email", Children: gx.Text("Email")}),
input.Input(input.InputProps{Id: "field-email", Type: "email", Placeholder: "you@example.com"}),
FieldDescription(FieldDescriptionProps{Children: gx.Text("We never share your email.")}),
)},
"Invalid": {Invalid: true, Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "field-invalid", Children: gx.Text("Email")}),
input.Input(input.InputProps{Id: "field-invalid", Type: "email", Value: "ada@", Attrs: gx.Attrs{{Key: "aria-invalid", Value: "true"}}}),
FieldError(FieldErrorProps{Children: gx.Text("Enter a valid email address.")}),
)},
"Disabled": {Disabled: true, Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "field-disabled", Children: gx.Text("Email")}),
input.Input(input.InputProps{Id: "field-disabled", Type: "email", Attrs: gx.Attrs{gx.Bool("disabled", true)}}),
)},
"Horizontal": {Orientation: Horizontal, Children: gx.Frag(
FieldContent(FieldContentProps{Children: gx.Frag(
FieldTitle(FieldTitleProps{Children: gx.Text("Product news")}),
FieldDescription(FieldDescriptionProps{Children: gx.Text("One message each month.")}),
)}),
gx.El("input", gx.Attrs{
{Key: "type", Value: "checkbox"},
{Key: "aria-label", Value: "Product news"},
{Key: "class", Value: "size-4 accent-primary"},
}),
)},
"Responsive": {Orientation: Responsive, Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "field-responsive", Children: gx.Text("Name")}),
input.Input(input.InputProps{Id: "field-responsive"}),
)},
}
// FieldWrap renders the field in a field group, as a form uses it. The
// group is the container that a responsive field measures.
func FieldWrap(n gx.Node) gx.Node {
return FieldGroup(FieldGroupProps{Children: n})
}package field
import "github.com/alternayte/gx"
// Variant is the size of a field legend.
type Variant string
// The variants of field.FieldLegend.
const (
Legend Variant = "legend"
Label Variant = "label"
)
// variant returns the data-variant value; a zero value is Legend. The
// legend size and the gap below it follow this attribute.
func (p FieldLegendProps) variant() string {
if p.Variant == "" {
return string(Legend)
}
return string(p.Variant)
}
// Orientation is the direction of the label and the control of a field.
type Orientation string
// The orientations of field.Field. Responsive is vertical in a narrow
// field group and horizontal in a wide one.
const (
Vertical Orientation = "vertical"
Horizontal Orientation = "horizontal"
Responsive Orientation = "responsive"
)
var orientationClass = gx.Enum[Orientation]{
Vertical: "flex-col [&>*]:w-full [&>.sr-only]:w-auto",
Horizontal: "flex-row items-center [&>[data-slot=field-label]]:flex-auto has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>:is([role=checkbox],[role=radio],input[type=checkbox],input[type=radio])]:mt-px",
Responsive: "flex-col @md/field-group:flex-row @md/field-group:items-center [&>*]:w-full @md/field-group:[&>*]:w-auto [&>.sr-only]:w-auto @md/field-group:[&>[data-slot=field-label]]:flex-auto @md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>:is([role=checkbox],[role=radio],input[type=checkbox],input[type=radio])]:mt-px",
}
// orientation returns the data-orientation value; a zero value is Vertical.
func (p FieldProps) orientation() string {
if p.Orientation == "" {
return string(Vertical)
}
return string(p.Orientation)
}
// attrs returns the state attributes of one field, then the caller's. The
// field and its label read data-invalid and data-disabled.
func (p FieldProps) attrs() gx.Attrs {
var a gx.Attrs
if p.Invalid {
a = append(a, gx.Attr{Key: "data-invalid", Value: "true"})
}
if p.Disabled {
a = append(a, gx.Attr{Key: "data-disabled", Value: "true"})
}
return append(a, p.Attrs...)
}
// attrs returns the for attribute when the label names a control, then the
// caller's attributes.
func (p FieldLabelProps) attrs() gx.Attrs {
if p.For == "" {
return p.Attrs
}
return append(gx.Attrs{{Key: "for", Value: p.For}}, p.Attrs...)
}
// messages returns the distinct, non-empty errors in their first order.
func (p FieldErrorProps) messages() []string {
seen := make(map[string]bool, len(p.Errors))
out := make([]string, 0, len(p.Errors))
for _, message := range p.Errors {
if message == "" || seen[message] {
continue
}
seen[message] = true
out = append(out, message)
}
return out
}package field
import "github.com/alternayte/gx"
var FieldDescriptionFixtures = gx.Fixtures[FieldDescriptionProps]{"Text": {Children: gx.Text("A short hint.")}}package field
import "github.com/alternayte/gx"
var FieldErrorFixtures = gx.Fixtures[FieldErrorProps]{
"Error": {Children: gx.Text("This field is required.")},
"One": {Errors: []string{"Enter a valid email address.", "Enter a valid email address."}},
"List": {Errors: []string{"Use 12 characters or more.", "Use one number."}},
}package field
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/input"
)
var FieldGroupFixtures = gx.Fixtures[FieldGroupProps]{
"TwoFields": {Children: gx.Frag(
Field(FieldProps{Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "group-name", Children: gx.Text("Name")}),
input.Input(input.InputProps{Id: "group-name"}),
)}),
FieldSeparator(FieldSeparatorProps{}),
Field(FieldProps{Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "group-email", Children: gx.Text("Email")}),
input.Input(input.InputProps{Id: "group-email", Type: "email"}),
)}),
)},
}package field
import "github.com/alternayte/gx"
var FieldLabelFixtures = gx.Fixtures[FieldLabelProps]{"Label": {For: "email", Children: gx.Text("Email")}}package field
import "github.com/alternayte/gx"
var FieldLegendFixtures = gx.Fixtures[FieldLegendProps]{
"Legend": {Children: gx.Text("Address")},
"Label": {Variant: Label, Children: gx.Text("Address")},
}
// FieldLegendWrap renders the legend in a field set, where a legend
// belongs.
func FieldLegendWrap(n gx.Node) gx.Node {
return FieldSet(FieldSetProps{Children: n})
}package field
import (
"github.com/alternayte/gx"
"github.com/alternayte/gx/registry/input"
)
var FieldSetFixtures = gx.Fixtures[FieldSetProps]{
"Address": {Children: gx.Frag(
FieldLegend(FieldLegendProps{Children: gx.Text("Address")}),
FieldDescription(FieldDescriptionProps{Children: gx.Text("We send the invoice to this address.")}),
FieldGroup(FieldGroupProps{Children: gx.Frag(
Field(FieldProps{Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "set-street", Children: gx.Text("Street")}),
input.Input(input.InputProps{Id: "set-street"}),
)}),
Field(FieldProps{Children: gx.Frag(
FieldLabel(FieldLabelProps{For: "set-city", Children: gx.Text("City")}),
input.Input(input.InputProps{Id: "set-city"}),
)}),
)}),
)},
}package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content of the column: the title and the description.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="field-content" class={gx.Cx("group/field-content flex flex-1 flex-col gap-1.5 leading-snug", p.Class)} {...p.Attrs}>{p.Children}</div>package field
import "github.com/alternayte/gx"
var FieldContentFixtures = gx.Fixtures[FieldContentProps]{
"TitleAndDescription": {Children: gx.Frag(
FieldTitle(FieldTitleProps{Children: gx.Text("Product news")}),
FieldDescription(FieldDescriptionProps{Children: gx.Text("One message each month.")}),
)},
}package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the title text.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="field-label" class={gx.Cx("flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", p.Class)} {...p.Attrs}>{p.Children}</div>package field
import "github.com/alternayte/gx"
var FieldTitleFixtures = gx.Fixtures[FieldTitleProps]{"Title": {Children: gx.Text("Product news")}}package field
props {
// Class adds classes to the root element.
Class string = ""
// Children is the text on the line. Nil shows the line only.
Children gx.Node = nil
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div data-slot="field-separator" data-content={p.Children != nil} class={gx.Cx("relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", p.Class)} {...p.Attrs}>
<div data-slot="separator" role="none" data-orientation="horizontal" class="absolute inset-0 top-1/2 h-px w-full shrink-0 bg-border"></div>
if p.Children != nil {
<span data-slot="field-separator-content" class="relative mx-auto block w-fit bg-background px-2 text-muted-foreground">{p.Children}</span>
}
</div>package field
import "github.com/alternayte/gx"
var FieldSeparatorFixtures = gx.Fixtures[FieldSeparatorProps]{
"Line": {},
"Text": {Children: gx.Text("Or continue with")},
}The theme must define these tokens: --destructive, --muted-foreground, --border, --background, --primary.
Usage
<field.FieldGroup>
<field.Field>
<field.FieldLabel for="email">Email</field.FieldLabel>
<input.Input id="email" name="email" type="email" />
<field.FieldDescription>We never share your email.</field.FieldDescription>
</field.Field>
<field.FieldSeparator>Or</field.FieldSeparator>
<field.Field orientation={field.Horizontal}>
<field.FieldContent>
<field.FieldTitle>Product news</field.FieldTitle>
<field.FieldDescription>One message each month.</field.FieldDescription>
</field.FieldContent>
<switches.Switch name="news" label="Product news" />
</field.Field>
</field.FieldGroup>Field has three orientations: Vertical, Horizontal and Responsive. A responsive field is horizontal when its FieldGroup is wide.
FieldSet and FieldLegend group related fields. FieldGroup sets the space between fields.
FieldError shows its children, or the distinct messages of Errors. It renders nothing when it has no message.
For a generated form field with rules and errors, use the gx.FormField control.
Examples
Field: Label and input
<field.Field>
<field.FieldLabel for="field-email">Email</field.FieldLabel>
<input.Input id="field-email" type="email" placeholder="you@example.com" />
<field.FieldDescription>We never share your email.</field.FieldDescription>
</field.Field>Field: Invalid
<field.Field invalid>
<field.FieldLabel for="field-invalid">Email</field.FieldLabel>
<input.Input id="field-invalid" type="email" value="ada@" attrs={gx.Attrs{{Key: "aria-invalid", Value: "true"}}} />
<field.FieldError>Enter a valid email address.</field.FieldError>
</field.Field>Field: Disabled
<field.Field disabled>
<field.FieldLabel for="field-disabled">Email</field.FieldLabel>
<input.Input id="field-disabled" type="email" attrs={gx.Attrs{gx.Bool("disabled", true)}} />
</field.Field>Field: Horizontal
<field.Field orientation={field.Horizontal}>
<field.FieldContent>
<field.FieldTitle>Product news</field.FieldTitle>
<field.FieldDescription>One message each month.</field.FieldDescription>
</field.FieldContent>
<input type="checkbox" aria-label="Product news" class="size-4 accent-primary" />
</field.Field>Field: Responsive
<field.Field orientation={field.Responsive}>
<field.FieldLabel for="field-responsive">Name</field.FieldLabel>
<input.Input id="field-responsive" />
</field.Field>FieldContent: Title and description
<field.FieldContent>
<field.FieldTitle>Product news</field.FieldTitle>
<field.FieldDescription>One message each month.</field.FieldDescription>
</field.FieldContent>FieldDescription: Text
<field.FieldDescription>A short hint.</field.FieldDescription>FieldError: Error
<field.FieldError>This field is required.</field.FieldError>FieldError: One
<field.FieldError errors={[]string{"Enter a valid email address.", "Enter a valid email address."}} />FieldError: List
<field.FieldError errors={[]string{"Use 12 characters or more.", "Use one number."}} />FieldGroup: Two fields
<field.FieldGroup>
<field.Field>
<field.FieldLabel for="group-name">Name</field.FieldLabel>
<input.Input id="group-name" />
</field.Field>
<field.FieldSeparator />
<field.Field>
<field.FieldLabel for="group-email">Email</field.FieldLabel>
<input.Input id="group-email" type="email" />
</field.Field>
</field.FieldGroup>FieldLabel: Label
<field.FieldLabel for="email">Email</field.FieldLabel>FieldLegend: Legend
<field.FieldLegend>Address</field.FieldLegend>FieldLegend: Label
<field.FieldLegend variant={field.Label}>Address</field.FieldLegend>FieldSeparator: Line
<field.FieldSeparator />FieldSeparator: Text
<field.FieldSeparator>Or continue with</field.FieldSeparator>FieldSet: Address
<field.FieldSet>
<field.FieldLegend>Address</field.FieldLegend>
<field.FieldDescription>We send the invoice to this address.</field.FieldDescription>
<field.FieldGroup>
<field.Field>
<field.FieldLabel for="set-street">Street</field.FieldLabel>
<input.Input id="set-street" />
</field.Field>
<field.Field>
<field.FieldLabel for="set-city">City</field.FieldLabel>
<input.Input id="set-city" />
</field.Field>
</field.FieldGroup>
</field.FieldSet>FieldTitle: Title
<field.FieldTitle>Product news</field.FieldTitle>API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
field.Field
| Prop | Type | Default | Description |
|---|---|---|---|
Orientation |
Orientation |
Vertical |
Orientation sets the direction of the label and the control: Vertical, Horizontal or Responsive. Responsive is vertical in a narrow field group and horizontal in a wide one. |
Invalid |
bool |
false |
Invalid sets data-invalid on the field. The field text takes the destructive colour. |
Disabled |
bool |
false |
Disabled sets data-disabled on the field. The label and the title fade. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the field: the label, the control and the description. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldContent
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the column: the title and the description. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldDescription
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the description text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldError
| Prop | Type | Default | Description |
|---|---|---|---|
Errors |
[]string |
nil |
Errors holds the error messages. Empty and repeated messages do not show; two or more show as a list. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
nil |
Children is the content of the error. It replaces Errors. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldGroup
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the group: the fields, the field sets and the separators. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldLabel
| Prop | Type | Default | Description |
|---|---|---|---|
For |
string |
"" |
For is the id of the control that the label names. Empty omits the for attribute. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the label text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldLegend
| Prop | Type | Default | Description |
|---|---|---|---|
Variant |
Variant |
Legend |
Variant sets the text size: Legend or Label. Label is the smaller size. |
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the legend text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
nil |
Children is the text on the line. Nil shows the line only. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldSet
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content of the field set. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
field.FieldTitle
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the title text. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
Do and do not
Do
- Set
Invalidon the field when a rule fails. Setaria-invalidon the control too. - Put the error in
FieldErrorbelow the control. - Set
Disabledon the field when its control is disabled.
Don't
- Do not use a field for a layout grid. Use CSS.
- Do not set
Forto an id that does not exist.
Keyboard
| Key | Action |
|---|---|
| None | The component is static. |