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'
import styles from 'styles/field.module.css'
export const Input = () => (
<Field.Root className={styles.Root}>
<Field.Label className={styles.Label}>Label</Field.Label>
<Field.Input className={styles.Input} />
<Field.HelperText className={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
import { Field } from '@ark-ui/solid/field'
import styles from 'styles/field.module.css'
export const Input = () => (
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Input class={styles.Input} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import styles from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="styles.Root">
<Field.Label :class="styles.Label">Label</Field.Label>
<Field.Input :class="styles.Input" />
<Field.HelperText :class="styles.HelperText">Some additional Info</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
</script>
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Input class={styles.Input} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.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'
import styles from 'styles/field.module.css'
export const Textarea = () => (
<Field.Root className={styles.Root}>
<Field.Label className={styles.Label}>Label</Field.Label>
<Field.Textarea className={styles.Textarea} />
<Field.HelperText className={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
import { Field } from '@ark-ui/solid/field'
import styles from 'styles/field.module.css'
export const Textarea = () => (
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Textarea class={styles.Textarea} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import styles from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="styles.Root">
<Field.Label :class="styles.Label">Label</Field.Label>
<Field.Textarea :class="styles.Textarea" />
<Field.HelperText :class="styles.HelperText">Some additional Info</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
</script>
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Textarea class={styles.Textarea} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</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'
import styles from 'styles/field.module.css'
export const TextareaAutoresize = () => (
<Field.Root className={styles.Root}>
<Field.Label className={styles.Label}>Label</Field.Label>
<Field.Textarea className={styles.Textarea} autoresize />
<Field.HelperText className={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
import { Field } from '@ark-ui/solid/field'
import styles from 'styles/field.module.css'
export const TextareaAutoresize = () => (
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Textarea class={styles.Textarea} autoresize />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import styles from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="styles.Root">
<Field.Label :class="styles.Label">Label</Field.Label>
<Field.Textarea :class="styles.Textarea" autoresize />
<Field.HelperText :class="styles.HelperText">Some additional Info</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
</script>
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Textarea class={styles.Textarea} autoresize />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
Select
This example demonstrates how to integrate the Field component with a select dropdown.
import { Field } from '@ark-ui/react/field'
import styles from 'styles/field.module.css'
export const Select = () => (
<Field.Root className={styles.Root}>
<Field.Label className={styles.Label}>Label</Field.Label>
<Field.Select className={styles.Select}>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText className={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
import { Field } from '@ark-ui/solid/field'
import styles from 'styles/field.module.css'
export const Select = () => (
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Select class={styles.Select}>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import styles from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="styles.Root">
<Field.Label :class="styles.Label">Label</Field.Label>
<Field.Select :class="styles.Select">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText :class="styles.HelperText">Some additional Info</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">Error Info</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
</script>
<Field.Root class={styles.Root}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Select class={styles.Select}>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</Field.Select>
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</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'
import styles from 'styles/checkbox.module.css'
import field from 'styles/field.module.css'
export const WithField = () => (
<Field.Root className={field.Root}>
<Checkbox.Root className={styles.Root}>
<Checkbox.Control className={styles.Control}>
<Checkbox.Indicator className={styles.Indicator}>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator className={styles.Indicator} indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.Label className={styles.Label}>Label</Checkbox.Label>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText className={field.HelperText}>Additional Info</Field.HelperText>
<Field.ErrorText className={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'
import styles from 'styles/checkbox.module.css'
import field from 'styles/field.module.css'
export const WithField = () => (
<Field.Root class={field.Root}>
<Checkbox.Root class={styles.Root}>
<Checkbox.Control class={styles.Control}>
<Checkbox.Indicator class={styles.Indicator}>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator class={styles.Indicator} indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.Label class={styles.Label}>Label</Checkbox.Label>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
<Field.ErrorText class={field.ErrorText}>Error Info</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Checkbox } from '@ark-ui/vue/checkbox'
import { Field } from '@ark-ui/vue/field'
import { CheckIcon, MinusIcon } from 'lucide-vue-next'
import styles from 'styles/checkbox.module.css'
import field from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="field.Root">
<Checkbox.Root :class="styles.Root">
<Checkbox.Control :class="styles.Control">
<Checkbox.Indicator :class="styles.Indicator">
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator :class="styles.Indicator" indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.Label :class="styles.Label">Label</Checkbox.Label>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText :class="field.HelperText">Additional Info</Field.HelperText>
<Field.ErrorText :class="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'
import styles from 'styles/checkbox.module.css'
import field from 'styles/field.module.css'
</script>
<Field.Root class={field.Root}>
<Checkbox.Root class={styles.Root}>
<Checkbox.Control class={styles.Control}>
<Checkbox.Indicator class={styles.Indicator}>
<CheckIcon />
</Checkbox.Indicator>
<Checkbox.Indicator class={styles.Indicator} indeterminate>
<MinusIcon />
</Checkbox.Indicator>
</Checkbox.Control>
<Checkbox.Label class={styles.Label}>Label</Checkbox.Label>
<Checkbox.HiddenInput />
</Checkbox.Root>
<Field.HelperText class={field.HelperText}>Additional Info</Field.HelperText>
<Field.ErrorText class={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'
import styles from 'styles/field.module.css'
import button from 'styles/button.module.css'
export const RootProvider = () => {
const [invalid, setInvalid] = useState(false)
const field = useField({ invalid })
return (
<>
<button className={button.Root} style={{ marginBottom: '1rem' }} onClick={() => setInvalid((prev) => !prev)}>
Toggle Invalid
</button>
<Field.RootProvider className={styles.Root} value={field}>
<Field.Label className={styles.Label}>Label</Field.Label>
<Field.Input className={styles.Input} />
<Field.HelperText className={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.RootProvider>
</>
)
}
import { Field, useField } from '@ark-ui/solid/field'
import { createMemo, createSignal } from 'solid-js'
import styles from 'styles/field.module.css'
import button from 'styles/button.module.css'
export const RootProvider = () => {
const [invalid, setInvalid] = createSignal(false)
const fieldProps = createMemo(() => ({
invalid: invalid(),
}))
const value = useField(fieldProps)
return (
<>
<button class={button.Root} style={{ 'margin-bottom': '1rem' }} onClick={() => setInvalid((prev) => !prev)}>
Toggle Invalid
</button>
<Field.RootProvider class={styles.Root} value={value}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Input class={styles.Input} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.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'
import styles from 'styles/field.module.css'
import button from 'styles/button.module.css'
const invalid = ref(false)
const fieldProps = computed<UseFieldProps>(() => ({
invalid: invalid.value,
}))
const field = useField(fieldProps)
</script>
<template>
<button :class="button.Root" style="margin-bottom: 1rem" @click="invalid = !invalid">Toggle Invalid</button>
<Field.RootProvider :class="styles.Root" :value="field">
<Field.Label :class="styles.Label">Label</Field.Label>
<Field.Input :class="styles.Input" />
<Field.HelperText :class="styles.HelperText">Some additional Info</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">Error Info</Field.ErrorText>
</Field.RootProvider>
</template>
<script lang="ts">
import { Field, useField } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
import button from 'styles/button.module.css'
const id = $props.id()
let invalid = $state(false)
const field = useField({ id, get invalid() { return invalid } })
</script>
<button class={button.Root} style="margin-bottom: 1rem" onclick={() => invalid = !invalid}>
Toggle Invalid
</button>
<Field.RootProvider class={styles.Root} value={field}>
<Field.Label class={styles.Label}>Label</Field.Label>
<Field.Input class={styles.Input} />
<Field.HelperText class={styles.HelperText}>Some additional Info</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>Error Info</Field.ErrorText>
</Field.RootProvider>
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'
import styles from 'styles/field.module.css'
export const CustomControl = () => (
<Field.Root className={styles.Root} invalid>
<Field.Label className={styles.Label}>Any Control</Field.Label>
<Field.Context>{(context) => <input {...context.getInputProps()} />}</Field.Context>
<Field.HelperText className={styles.HelperText}>Uses getInputProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText className={styles.ErrorText}>This field has an error</Field.ErrorText>
</Field.Root>
)
import { Field } from '@ark-ui/solid/field'
import styles from 'styles/field.module.css'
export const CustomControl = () => (
<Field.Root class={styles.Root} invalid>
<Field.Label class={styles.Label}>Any Control</Field.Label>
<Field.Context>{(field) => <input {...field().getInputProps()} />}</Field.Context>
<Field.HelperText class={styles.HelperText}>Uses getInputProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText class={styles.ErrorText}>This field has an error</Field.ErrorText>
</Field.Root>
)
<script setup lang="ts">
import { Field } from '@ark-ui/vue/field'
import styles from 'styles/field.module.css'
</script>
<template>
<Field.Root :class="styles.Root" invalid>
<Field.Label :class="styles.Label">Any Control</Field.Label>
<Field.Context v-slot="field">
<input v-bind="field.getInputProps()" />
</Field.Context>
<Field.HelperText :class="styles.HelperText">Uses getInputProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText :class="styles.ErrorText">This field has an error</Field.ErrorText>
</Field.Root>
</template>
<script lang="ts">
import { Field } from '@ark-ui/svelte/field'
import styles from 'styles/field.module.css'
</script>
<Field.Root class={styles.Root} invalid>
<Field.Label class={styles.Label}>Any Control</Field.Label>
<Field.Context>
{#snippet render(field)}
<input {...field().getInputProps()} />
{/snippet}
</Field.Context>
<Field.HelperText class={styles.HelperText}>Uses getInputProps() for maximum flexibility</Field.HelperText>
<Field.ErrorText class={styles.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 |