Field
Provides a flexible container for form inputs, labels, and helper text.
Examples
The Field component provides contexts such as invalid, disabled, required, and readOnly for form elements.
While most Ark UI components natively support these contexts, you can also use the Field component with standard HTML
form elements.
Input
This example shows how to use the Field component with a standard input field.
import { Field } from '@ark-ui/react/field'
export const Input = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
import { Field } from '@ark-ui/solid/field'
export const Input = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
</script>
<template>
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
</script>
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
Textarea
This example illustrates how to use the Field component with a textarea element.
import { Field } from '@ark-ui/react/field'
export const Textarea = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
import { Field } from '@ark-ui/solid/field'
export const Textarea = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
</script>
<template>
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
</script>
<Field.Root>
<Field.Label>Message</Field.Label>
<Field.Textarea placeholder="Enter your message..." />
<Field.HelperText>Please provide as much detail as possible</Field.HelperText>
</Field.Root>
Textarea Autoresize
Pass the autoresize prop to the Textarea component to enable automatic resizing as the user types.
import { Field } from '@ark-ui/react/field'
export const TextareaAutoresize = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea autoresize />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
import { Field } from '@ark-ui/solid/field'
export const TextareaAutoresize = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea autoresize />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
</script>
<template>
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Textarea autoresize />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
</script>
<Field.Root>
<Field.Label>Message</Field.Label>
<Field.Textarea placeholder="Enter your message..." autoresize />
<Field.HelperText>Please provide as much detail as possible</Field.HelperText>
</Field.Root>
Select
This example demonstrates how to integrate the Field component with a select dropdown.
import { Field } from '@ark-ui/react/field'
export const Select = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
import { Field } from '@ark-ui/solid/field'
export const Select = () => {
return (
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
</script>
<template>
<Field.Root>
<Field.Label>Label</Field.Label>
<Field.Select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
</script>
<Field.Root>
<Field.Label>Country</Field.Label>
<Field.Select>
<option value="">Select a country</option>
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
<option value="de">Germany</option>
</Field.Select>
<Field.HelperText>Please select your country of residence</Field.HelperText>
</Field.Root>
Checkbox
This example demonstrates how to integrate the Field and Checkbox components.
import { Checkbox } from '@ark-ui/react/checkbox'
import { Field } from '@ark-ui/react/field'
import { CheckIcon, MinusIcon } from 'lucide-react'
export const WithField = (props: Field.RootProps) => (
<Field.Root {...props}>
<Checkbox.Root>
<Checkbox.Label>Label</Checkbox.Label>
<Checkbox.Control>
<Checkbox.Indicator>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
import { Checkbox } from '@ark-ui/solid/checkbox'
import { Field } from '@ark-ui/solid/field'
import { CheckIcon, MinusIcon } from 'lucide-solid'
export const WithField = (props: Field.RootProps) => (
<Field.Root {...props}>
<Checkbox.Root>
<Checkbox.Label>Label</Checkbox.Label>
<Checkbox.Control>
<Checkbox.Indicator>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Checkbox } from '@ark-ui/vue/checkbox'
import { Field, type FieldRootProps } from '@ark-ui/vue/field'
import { CheckIcon, MinusIcon } from 'lucide-vue-next'
const props = defineProps<FieldRootProps>()
</script>
<template>
<Field.Root v-bind="props">
<Checkbox.Root>
<Checkbox.Label>Label</Checkbox.Label>
<Checkbox.Control>
<Checkbox.Indicator>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Checkbox } from '@ark-ui/svelte/checkbox'
import { Field } from '@ark-ui/svelte/field'
import { CheckIcon, MinusIcon } from 'lucide-svelte'
</script>
<Field.Root>
<Checkbox.Root>
<Checkbox.Label>Label</Checkbox.Label>
<Checkbox.Control>
<Checkbox.Indicator>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
Root Provider
Use the useField hook to create the field store and pass it to the Field.RootProvider component. This allows you to
have maximum control over the field programmatically.
import { Field, useField } from '@ark-ui/react/field'
import { useState } from 'react'
export const RootProvider = () => {
const [invalid, setInvalid] = useState(false)
const value = useField({
invalid,
})
return (
<>
<button onClick={() => setInvalid((prev) => !prev)}>Toggle Invalid</button>
<Field.RootProvider value={value}>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.RootProvider>
</>
)
}
import { Field, useField } from '@ark-ui/solid/field'
import { createMemo, createSignal } from 'solid-js'
export const RootProvider = () => {
const [invalid, setInvalid] = createSignal(false)
const fieldProps = createMemo(() => ({
invalid: invalid(),
}))
const value = useField(fieldProps)
return (
<>
<button onClick={() => setInvalid((prev) => !prev)}>Toggle Invalid</button>
<Field.RootProvider value={value}>
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.RootProvider>
</>
)
}
<script setup lang="ts">
import { Field, type UseFieldProps, useField } from '@ark-ui/vue/field'
import { computed, ref } from 'vue'
const invalid = ref(false)
const fieldProps = computed<UseFieldProps>(() => ({
invalid: invalid.value,
}))
const field = useField(fieldProps)
</script>
<template>
<button @click="invalid = !invalid">Toggle Invalid</button>
<Field.RootProvider :value="field">
<Field.Label>Label</Field.Label>
<Field.Input />
<Field.HelperText>Some additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.RootProvider>
</template>
<script lang="ts">
import { Field, useField } from '@ark-ui/svelte/field'
const id = $props.id()
const field = useField({ id, invalid: true, required: true })
</script>
<Field.RootProvider value={field}>
<Field.Label>
Label
<Field.RequiredIndicator>*</Field.RequiredIndicator>
</Field.Label>
<Field.Input />
<Field.ErrorText>This field has an error</Field.ErrorText>
</Field.RootProvider>
<Field.Context>
{#snippet render(field)}
<p>Field ID: {field().ids.control}</p>
<p>Required: {field().required}</p>
<p>Invalid: {field().invalid}</p>
{/snippet}
</Field.Context>
If you're using the
Field.RootProvidercomponent, you don't need to use theField.Rootcomponent.
Custom Control
Use the Field.Context or useFieldContext hook to access the internal state of the field.This can help you wire up
custom controls with the Field component.
import { Field } from '@ark-ui/react/field'
export const CustomControl = () => {
return (
<Field.Root invalid>
<Field.Label>Any Control</Field.Label>
<Field.Context>{(field) => <input {...field.getInputProps()} />}</Field.Context>
<Field.HelperText>Uses getControlProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText>This field has an error</Field.ErrorText>
</Field.Root>
)
}
import { Field } from '@ark-ui/solid/field'
export const CustomControl = () => {
return (
<Field.Root invalid>
<Field.Label>Any Control</Field.Label>
<Field.Context>{(field) => <input {...field().getInputProps()} />}</Field.Context>
<Field.HelperText>Uses getControlProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText>This field has an error</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
</script>
<template>
<Field.Root invalid>
<Field.Label>Any Control</Field.Label>
<Field.Context v-slot="field">
<input v-bind="field.getInputProps()" />
</Field.Context>
<Field.HelperText>Uses getControlProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText>This field has an error</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
</script>
<Field.Root invalid>
<Field.Label>Any Control</Field.Label>
<Field.Context>
{#snippet render(field)}
<input {...field().getInputProps()} />
{/snippet}
</Field.Context>
<Field.HelperText>Uses getControlProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText>This field has an error</Field.ErrorText>
</Field.Root>
API Reference
Root
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
disabled | booleanIndicates whether the field is disabled. | |
ids | ElementIdsThe ids of the field parts. | |
invalid | booleanIndicates whether the field is invalid. | |
readOnly | booleanIndicates whether the field is read-only. | |
required | booleanIndicates whether the field is required. |
ErrorText
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
HelperText
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Input
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Label
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
RequiredIndicator
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
fallback | string | number | bigint | boolean | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable<ReactNode> | ReactPortal | Promise<...> |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | { ariaDescribedby: string | undefined; ids: { root: string; control: string; label: string; errorText: string; helperText: string; }; refs: { rootRef: RefObject<HTMLDivElement | null>; }; ... 11 more ...; getRequiredIndicatorProps: () => Omit<...>; } | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Select
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Textarea
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
autoresize | false | booleanWhether the textarea should autoresize |