InputGroup
Related input fields with a shared hover surface and validation messages.
Installation
Import from the Reflow workspace package.
Playground
Open demoimport { InputGroup, InputField } from '@rtzll/reflow'
import { type Handle } from 'remix/component'
export function Example(handle: Handle) {
return () => (
<>
<InputGroup>
<InputField label="Name" name="name" />
<InputField label="Email" name="email" type="email" />
</InputGroup>
</>
)
}Multiple Fields
import { InputGroup, InputField } from '@rtzll/reflow'
import { type Handle } from 'remix/component'
export function Example(handle: Handle) {
const icon = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 6h16M4 12h16M4 18h16" /></svg>
return () => (
<>
<InputGroup>
<InputField label="Name" placeholder="Your name" />
<InputField label="Email" type="email" placeholder="you@example.com" icon={mailIcon} />
</InputGroup>
</>
)
}Error State
import { InputGroup, InputField } from '@rtzll/reflow'
import { type Handle } from 'remix/component'
export function Example(handle: Handle) {
const icon = <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 6h16M4 12h16M4 18h16" /></svg>
return () => (
<>
<InputGroup>
<InputField label="Email" type="email" icon={mailIcon} error="Please enter a valid email address." defaultValue="bad@" />
</InputGroup>
</>
)
}API Reference
Public props for the Reflow implementation. Native controls also accept their standard HTML attributes and Remix event mixes.
InputGroup
| Prop | Type | Default | Description |
|---|---|---|---|
children | RemixNode | — | Child nodes to render inside the element. |
size | "default" | "compact" | — | Control density or icon-button dimensions. |
InputField
| Prop | Type | Default | Description |
|---|---|---|---|
disabled | boolean | — | The `disabled` HTML attribute. |
name | string | — | The `name` HTML attribute. |
type | "number" | "hidden" | "color" | "button" | "search" | "checkbox" | "radio" | "date" | "time" | "text" | "submit" | "reset" | "range" | "email" | "image" | "tel" | "url" | "datetime-local" | "file" | "month" | "password" | "week" | — | Single or multiple expansion mode. |
value | string | number | — | The `value` HTML attribute. |
size | "default" | "compact" | — | Control density or icon-button dimensions. |
checked | boolean | — | The `checked` HTML attribute. |
defaultChecked | boolean | — | The `defaultChecked` HTML attribute. |
defaultValue | string | number | — | The `defaultValue` HTML attribute. |
indeterminate | boolean | — | The `indeterminate` HTML attribute. |
placeholder | string | — | The `placeholder` HTML attribute. |
required | boolean | — | The `required` HTML attribute. |
id | string | — | Stable identifier. |
label* | string | — | Accessible name or visible label for the control. |
labelHidden | boolean | — | Keeps the label accessible while hiding it visually. |
description | RemixNode | — | Additional explanatory text. |
error | RemixNode | — | Validation message or error state. |
icon | RemixNode | — | Icon content. |
onChange | ((value: string, event: Event) => void) | — | Called with the updated value. |