- Accordion
- Action Bar
- Alert Dialog
- Alert
- Announcement
- Aspect Ratio
- Autocomplete
- Avatar
- Badge
- Bottom Navigation
- Breadcrumb
- Button Group
- Button
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Circular Progress
- Circular Slider
- Clipboard
- Collapsible
- Color Picker
- Combobox
- Command
- Context Menu
- Data List
- Date Picker
- Dialog
- Drawer
- Editable
- Field
- File Upload
- Float
- Floating Panel
- Frame
- Hint
- Hover Card
- Image Cropper
- Input Group
- Input OTP
- Input
- Item
- Kbd
- Link Overlay
- Listbox
- Marquee
- Menu
- Native Select
- Number Input
- Pagination
- Popover
- Progress
- Prose
- QR Code
- Radio Group
- Rating
- Resizable
- Scroll Area
- Segment Group
- Select
- Separator
- Sheet
- Sidebar
- Signature Pad
- Skeleton
- Skip Nav
- Slider
- Spinner
- Status
- Steps
- Switch
- Table
- Tabs
- Textarea
- Timer
- Toast
- Toggle Group
- Toggle Tooltip
- Toggle
- Tooltip
- Tour
- Tree View
Shark UI builds on Ark UI's Field and Fieldset components for integrating with native form element or popular form libraries like React Hook Form and TanStack Form.
Form Libraries
For detailed guides with examples, validation, and field-type-specific patterns, see the linked pages above.
Field Context
Form components in Shark UI automatically integrate with Field through context. When nested inside a Field, they inherit disabled, invalid, required, and readOnly states automatically.
import { Field } from "@/registry/react/components/field" import { NumberField } from "@/registry/react/components/number-input" const Demo = () => ( <Field disabled> <NumberField> <NumberFieldGroup> <NumberFieldInput /> <NumberFieldIncrement /> <NumberFieldDecrement /> </NumberFieldGroup> </NumberField> </Field> )
Accessible Labels
When building accessible forms, you need to ensure that they are properly labeled and described.
FieldHelper: Used to provide additional instructions about the input.FieldLabel: Used to provide an accessible label for the input.
These components are automatically linked to the input element via the aria-describedby attribute.
Best practice: Make sure that labels are visible (and not just used as placeholders) for screen readers to read them.
import { Field, FieldLabel, FieldHelper, } from "@/registry/react/components/field" import { Input } from "@/registry/react/components/input" const Demo = () => ( <form> <Field> <FieldLabel>Username</FieldLabel> <Input placeholder="Enter your username" /> <FieldHelper>This will be your public display name.</FieldHelper> </Field> </form> )
Error Handling and Validation
When the input is invalid, you can use the FieldError component to provide an error message for the input, and pass the invalid prop to the Field component.
Best practice: Make sure to provide clear, specific error messages that are easy to understand and fix.
import { Field, FieldLabel, FieldError, } from "@/registry/react/components/field" import { Input } from "@/registry/react/components/input" const Demo = () => ( <form> <Field invalid> <FieldLabel>Username</FieldLabel> <Input placeholder="Enter your username" /> <FieldError>Username is required.</FieldError> </Field> </form> )
Required Fields
To indicate that a field is required, you can pass the required prop to the Field component.
Optionally, you can use the <FieldRequiredIndicator /> to indicate that the field is required.
import { Field, FieldLabel, FieldRequiredIndicator, FieldError, } from "@/registry/react/components/field" import { Input } from "@/registry/react/components/input" export const Demo = () => ( <form> <Field required> <FieldLabel> Username <FieldRequiredIndicator>(required)</FieldRequiredIndicator> </FieldLabel> <Input placeholder="Enter your username" /> <FieldError>Username is required.</FieldError> </Field> </form> )
Fieldset Context
When you have multiple fields in a form or a component that renders multiple input elements, you can use the FieldSet component to group them together.
Common use cases: checkbox group, radio group, input + select composition, etc.
Checkbox Group
import { FieldSet, FieldLegend, FieldDescription, FieldGroup, Field, FieldLabel, } from "@/registry/react/components/field" import { Checkbox, CheckboxGroup } from "@/registry/react/components/checkbox" const items = [ { label: "React", value: "react" }, { label: "Solid", value: "solid" }, { label: "Vue", value: "vue" }, { label: "Svelte", value: "svelte" }, ] const Demo = () => ( <FieldSet> <FieldLegend variant="label">Frameworks</FieldLegend> <FieldDescription>Choose your preferred frameworks</FieldDescription> <FieldGroup> <CheckboxGroup name="framework"> {items.map((item) => ( <Field key={item.value} orientation="horizontal"> <Checkbox value={item.value} /> <FieldLabel className="font-normal">{item.label}</FieldLabel> </Field> ))} </CheckboxGroup> </FieldGroup> </FieldSet> )
Radio Group
import { FieldSet, FieldLegend, FieldDescription, } from "@/registry/react/components/field" import { RadioGroup, RadioGroupItem } from "@/registry/react/components/radio-group" const items = [ { label: "React", value: "react" }, { label: "Solid", value: "solid" }, { label: "Vue", value: "vue" }, { label: "Svelte", value: "svelte" }, ] const Demo = () => ( <FieldSet> <FieldLegend variant="label">Frameworks</FieldLegend> <FieldDescription>Choose your preferred framework</FieldDescription> <RadioGroup name="framework"> {items.map((item) => ( <RadioGroupItem key={item.value} value={item.value}> {item.label} </RadioGroupItem> ))} </RadioGroup> </FieldSet> )