Skip to Content
Prisma UI - React component library
ComponentsComponentsFloating Label Input

Floating Label Input

An input component with a label that floats above the field when focused or filled. Uses a compound component pattern (FloatingLabel, FloatingLabel.Input, FloatingLabel.Label) for full styling control. Inspired by shadcn/ui Expansions .

Installation

npx shadcn@latest add https://prismaui.com/components/floating-label-input.json

The direct URL serves the radix-vega variant. The Floating Label Input is style-aware — its underlying input height, radius, and label offsets differ per shadcn style. To let the CLI pick the variant that matches your project’s theme automatically, register the @prisma namespace once (see Styles & Themes) and install by name:

npx shadcn@latest add @prisma/floating-label-input

Import

import { FloatingLabel } from '@/components/ui/floating-label-input';

Preview

<FloatingLabel> <FloatingLabel.Input id='email' type='email' /> <FloatingLabel.Label htmlFor='email'>Email</FloatingLabel.Label> </FloatingLabel>

Multiple Fields

<div className='flex flex-col gap-4'> <FloatingLabel> <FloatingLabel.Input id='name' /> <FloatingLabel.Label htmlFor='name'>Full Name</FloatingLabel.Label> </FloatingLabel> <FloatingLabel> <FloatingLabel.Input id='email' type='email' /> <FloatingLabel.Label htmlFor='email'>Email</FloatingLabel.Label> </FloatingLabel> <FloatingLabel> <FloatingLabel.Input id='password' type='password' /> <FloatingLabel.Label htmlFor='password'>Password</FloatingLabel.Label> </FloatingLabel> </div>

Custom Styling

Each sub-component accepts its own className, giving full control without extra wrapper props.

<FloatingLabel> <FloatingLabel.Input id='username' className='rounded-full border-primary/50 px-5 focus:border-primary' /> <FloatingLabel.Label htmlFor='username' className='left-3 text-primary'> Username </FloatingLabel.Label> </FloatingLabel>

With Field (Description)

Wrap FloatingLabel inside a shadcn Field to add descriptions, errors, and accessible form layouts.

We’ll never share your email.

import { Field, FieldDescription } from '@/components/ui/field';
<Field> <FloatingLabel> <FloatingLabel.Input id='email' type='email' /> <FloatingLabel.Label htmlFor='email'>Email</FloatingLabel.Label> </FloatingLabel> <FieldDescription>We'll never share your email.</FieldDescription> </Field>

With Field (Error)

Use data-invalid on Field and aria-invalid on the input to show validation errors.

import { Field, FieldError } from '@/components/ui/field';
<Field data-invalid> <FloatingLabel> <FloatingLabel.Input id='email' type='email' aria-invalid /> <FloatingLabel.Label htmlFor='email'>Email</FloatingLabel.Label> </FloatingLabel> <FieldError>Enter a valid email address.</FieldError> </Field>

With Field (Validation)

A complete example with interactive validation — the error appears when the input loses focus and the value is too short.

Must be at least 3 characters.

'use client'; import { useState } from 'react'; import { FloatingLabel } from '@/components/ui/floating-label-input'; import { Field, FieldDescription, FieldError } from '@/components/ui/field'; export function FieldValidationDemo() { const [value, setValue] = useState(''); const [touched, setTouched] = useState(false); const isInvalid = touched && value.length < 3; return ( <Field data-invalid={isInvalid || undefined}> <FloatingLabel> <FloatingLabel.Input id='username' value={value} onChange={(e) => setValue(e.target.value)} onBlur={() => setTouched(true)} aria-invalid={isInvalid || undefined} /> <FloatingLabel.Label htmlFor='username'>Username</FloatingLabel.Label> </FloatingLabel> <FieldDescription>Must be at least 3 characters.</FieldDescription> {isInvalid && ( <FieldError>Username must be at least 3 characters.</FieldError> )} </Field> ); }

With FieldSet (Form)

Group multiple floating label inputs inside a FieldSet with FieldGroup for a complete form layout.

Account Information

Fill in your account details below.

We’ll send a confirmation to this address.

Must be at least 8 characters.

import { Field, FieldDescription, FieldGroup, FieldSet, FieldLegend, } from '@/components/ui/field';
<FieldSet> <FieldLegend>Account Information</FieldLegend> <FieldDescription>Fill in your account details below.</FieldDescription> <FieldGroup> <Field> <FloatingLabel> <FloatingLabel.Input id='name' /> <FloatingLabel.Label htmlFor='name'>Full Name</FloatingLabel.Label> </FloatingLabel> </Field> <Field> <FloatingLabel> <FloatingLabel.Input id='email' type='email' /> <FloatingLabel.Label htmlFor='email'>Email</FloatingLabel.Label> </FloatingLabel> <FieldDescription> We'll send a confirmation to this address. </FieldDescription> </Field> <Field> <FloatingLabel> <FloatingLabel.Input id='password' type='password' /> <FloatingLabel.Label htmlFor='password'>Password</FloatingLabel.Label> </FloatingLabel> <FieldDescription>Must be at least 8 characters.</FieldDescription> </Field> </FieldGroup> </FieldSet>

Props

FloatingLabel (root)

PropTypeDefaultDescription
childrenReact.ReactNodeMust contain .Input and .Label.
classNamestringAdditional CSS classes for the root wrapper.

FloatingLabel.Input

PropTypeDefaultDescription
...propsInputHTMLAttributesAll standard input props.
classNamestringAdditional CSS classes.

FloatingLabel.Label

PropTypeDefaultDescription
htmlForstringMatches the input id.
childrenReact.ReactNodeThe label text.
classNamestringAdditional CSS classes.

Theme styles

The Floating Label Input ships in a dedicated variant for each supported shadcn style. Installed through the @prisma namespace, the CLI delivers the one matching the style in your components.json — same API, with the input sizing and label offsets adjusted per style:

radix-vega
radix-nova
radix-maia
radix-lyra
radix-mira
radix-luma
radix-rhea
radix-sera

See Styles & Themes for setup and the full list of supported styles.

Last updated on