Floating labels
Float labels above textual form fields when a value is present or the field is focused.
Examples
Pass label to FloatingInput and wrap a TextInput, Select, or Textarea to enable floating
labels with textual form fields. FloatingInput renders the floating <label> itself and ties it
to the control inside, so pass neither label nor an id to the wrapped control. A placeholder
is required on each <TextInput>, since this CSS-only technique relies on the
:placeholder-shown pseudo-class.
import { FloatingInput, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<>
<FloatingInput className="mb-md" label="Email address">
<TextInput type="email" placeholder="name@example.com" />
</FloatingInput>
<FloatingInput label="Password">
<TextInput autoComplete="current-password" type="password" placeholder="Password" />
</FloatingInput>
</>
)
}The label floats automatically when the wrapped control already has a value.
import { FloatingInput, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput label="Input with value">
<TextInput type="email" placeholder="name@example.com" defaultValue="test@example.com" />
</FloatingInput>
)
}Help and feedback
Passing help, invalid/invalidFeedback, or valid/validFeedback wraps the floating input
in a .form-field and renders the corresponding text below it, same as the other form components.
The control inside is described by the text that shows. Set invalid/valid on the control as
well: its state is what shows the feedback and draws its border.
import { FloatingInput, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput help="We'll never share your email." label="Email address">
<TextInput type="email" placeholder="name@example.com" />
</FloatingInput>
)
}Textareas
A <Textarea> renders at the same height as a <TextInput> by default.
import { FloatingInput, Textarea } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput label="Comments">
<Textarea placeholder="Leave a comment here"></Textarea>
</FloatingInput>
)
}Set an explicit height (inline or via custom CSS) for a custom <Textarea> height instead of the
rows attribute, which floating labels don't account for.
import { FloatingInput, Textarea } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput label="Comments">
<Textarea placeholder="Leave a comment here" style={{ height: '100px' }}></Textarea>
</FloatingInput>
)
}Selects
Floating labels also work with <Select>, though a select's label always renders in its floated
state rather than overlapping the value. Selects with size or multiple set aren't supported.
import { FloatingInput, Select } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput label="Works with selects">
<Select>
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</Select>
</FloatingInput>
)
}Layout
Place floating inputs in the columns of a <Grid> to lay them
out side by side.
import { FloatingInput, Grid, Select, TextInput } from '@chassis-ui/react'
export const Example = () => {
return (
<Grid columns={{ base: 1, md: 2 }} gap="sm">
<div>
<FloatingInput label="Email address">
<TextInput type="email" placeholder="name@example.com" defaultValue="email@example.com" />
</FloatingInput>
</div>
<div>
<FloatingInput label="Works with selects">
<Select>
<option>Open this select menu</option>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</Select>
</FloatingInput>
</div>
</Grid>
)
}Other controls
FloatingInput generates the ids of its label, help and feedback, and a TextInput, Select or
Textarea inside takes them by itself. Any other control, such as a native <input>, takes them
by hand: choose the ids, pass them through the ids prop, and repeat them on the control, as for
a <FormField>. The control needs the
.form-input class and has to be a direct child, which is what the label floats over.
import { FloatingInput } from '@chassis-ui/react'
export const Example = () => {
return (
<FloatingInput
help="As it appears on your passport."
ids={{ help: 'floatingNativeHelp', input: 'floatingNative' }}
label="Full name"
>
<input
aria-describedby="floatingNativeHelp"
className="form-input"
id="floatingNative"
placeholder="Jane Doe"
type="text"
/>
</FloatingInput>
)
}ids also replaces a generated id with one of your own, for a test or a link to the field:
ids={{ input: 'email' }} gives the wrapped TextInput the id email. In development,
FloatingInput warns when no element has the id its label points at.
API
FloatingInput
| Prop | Type | Default |
|---|---|---|
children | ReactNode | — |
The form control (e.g. a TextInput, Select, or Textarea) the floating label attaches
to. Chassis-css's floating-label CSS relies on a label:has(~ .form-input) selector, so this
must render an element carrying the form-input class as a direct child. | ||
className? | string | — |
A string of all className you want applied to the .form-floating element. | ||
help? | ReactNode | — |
A description for the field, rendered below the control. Setting this (or invalidFeedback/
validFeedback) wraps the floating input in a .form-field. | ||
ids? | FormFieldIds | — |
The ids that tie the label, help and feedback to the wrapped control, in place of the ones
FloatingInput generates. A field component of this library (TextInput, Select,
Textarea) takes them by itself and needs none. Any other control, such as a native
<input>, takes them by hand: input is the label's htmlFor and goes on the control as
its id, label is the label's own id, for a control named through aria-labelledby,
and help and feedback are the ids of the help and feedback text, for the control's
aria-describedby. label without input leaves the label with no htmlFor. | ||
invalid? | boolean | — |
| Set field validation state to invalid. | ||
invalidFeedback? | ReactNode | — |
An error message for the field, rendered below the control when invalid is set. | ||
label | ReactNode | — |
The field's caption, rendered as a floating FormLabel associated with the wrapped control. | ||
valid? | boolean | — |
| Set field validation state to valid. | ||
validFeedback? | ReactNode | — |
A success message for the field, rendered below the control when valid is set. | ||