---
title: Liquid Glass Input
description: A 3D liquid crystal text input component with top curved glare highlights, bottom prism refraction, 6 color variants (glass, aurora, emerald, cyan, primary, dark), 3 sizes, left/right icon support, validation status indicators, and password visibility toggle.
---
## Installation
CLI
Manual
```bash
npx lightswind@latest add liquid-glass-input
```
Copy and paste the following code into your project.
```tsx
"use client";
import React, { useState, useId } from "react";
import { cn } from "@/components/lib/utils";
import { Eye, EyeOff, AlertCircle, CheckCircle2 } from "lucide-react";
/* ─── Types ─────────────────────────────────────────────────────── */
export type LiquidGlassInputVariant =
| "glass"
| "aurora"
| "emerald"
| "cyan"
| "primary"
| "dark";
export type LiquidGlassInputSize = "sm" | "md" | "lg";
export type LiquidGlassInputStatus = "default" | "success" | "error";
export interface LiquidGlassInputProps
extends Omit, "size"> {
/** Visual variant */
variant?: LiquidGlassInputVariant;
/** Input height */
size?: LiquidGlassInputSize;
/** Validation state */
status?: LiquidGlassInputStatus;
/** Label above the input */
label?: string;
/** Helper / error text below */
hint?: string;
/** Icon on the left side */
leftIcon?: React.ReactNode;
/** Icon on the right side (overridden by password toggle / status icons) */
rightIcon?: React.ReactNode;
/** Extra classes for the outer wrapper */
wrapperClassName?: string;
}
/* ─── Variant Config ─────────────────────────────────────────────── */
interface InputVariantConfig {
wrapper: string;
focusRing: string;
glareGradient: string;
labelColor: string;
textColor: string;
placeholderClass: string;
}
const VARIANT_CONFIG: Record = {
glass: {
wrapper: cn(
"bg-gradient-to-b from-white/55 via-white/28 to-white/12 dark:from-white/22 dark:via-white/10 dark:to-white/5",
"border border-white/85 dark:border-white/25",
"shadow-[0_10px_28px_-4px_rgba(15,23,42,0.20),inset_0_2.5px_1.5px_rgba(255,255,255,0.95),0_0_0_1px_rgba(255,255,255,0.80)]",
"dark:shadow-[0_12px_32px_-4px_rgba(0,0,0,0.65),inset_0_2px_1.5px_rgba(255,255,255,0.30),0_0_0_1px_rgba(255,255,255,0.15)]"
),
focusRing: "ring-2 ring-white/70 dark:ring-white/30",
glareGradient:
"linear-gradient(180deg, rgba(255,255,255,0.90) 0%, rgba(255,255,255,0.40) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-slate-700 dark:text-slate-300",
textColor: "text-slate-900 dark:text-white",
placeholderClass: "placeholder-slate-400 dark:placeholder-slate-500",
},
aurora: {
wrapper: cn(
"bg-gradient-to-b from-violet-300/40 via-fuchsia-400/25 to-violet-500/30 dark:from-violet-400/30 dark:via-fuchsia-500/18 dark:to-violet-600/25",
"border border-violet-300/70 dark:border-violet-400/35",
"shadow-[0_10px_28px_-4px_rgba(139,92,246,0.25),inset_0_2.5px_1.5px_rgba(240,220,255,0.90),0_0_0_1px_rgba(200,180,255,0.70)]",
"dark:shadow-[0_12px_32px_-4px_rgba(139,92,246,0.40),inset_0_2px_1.5px_rgba(240,220,255,0.35),0_0_0_1px_rgba(200,180,255,0.25)]"
),
focusRing: "ring-2 ring-violet-400/60",
glareGradient:
"linear-gradient(180deg, rgba(255,245,255,0.88) 0%, rgba(240,220,255,0.38) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-violet-700 dark:text-violet-300",
textColor: "text-violet-900 dark:text-violet-100",
placeholderClass: "placeholder-violet-400/70 dark:placeholder-violet-400/50",
},
emerald: {
wrapper: cn(
"bg-gradient-to-b from-emerald-300/40 via-emerald-400/25 to-teal-500/30 dark:from-emerald-400/30 dark:via-emerald-500/18 dark:to-teal-600/25",
"border border-emerald-300/70 dark:border-emerald-400/35",
"shadow-[0_10px_28px_-4px_rgba(16,185,129,0.25),inset_0_2.5px_1.5px_rgba(220,255,235,0.90),0_0_0_1px_rgba(160,255,200,0.65)]",
"dark:shadow-[0_12px_32px_-4px_rgba(16,185,129,0.40),inset_0_2px_1.5px_rgba(220,255,235,0.35),0_0_0_1px_rgba(160,255,200,0.25)]"
),
focusRing: "ring-2 ring-emerald-400/60",
glareGradient:
"linear-gradient(180deg, rgba(235,255,245,0.88) 0%, rgba(180,255,220,0.38) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-emerald-700 dark:text-emerald-300",
textColor: "text-emerald-900 dark:text-emerald-100",
placeholderClass: "placeholder-emerald-400/70 dark:placeholder-emerald-400/50",
},
cyan: {
wrapper: cn(
"bg-gradient-to-b from-sky-300/40 via-blue-400/25 to-indigo-400/30 dark:from-sky-400/30 dark:via-blue-500/18 dark:to-indigo-500/25",
"border border-sky-300/70 dark:border-sky-400/35",
"shadow-[0_10px_28px_-4px_rgba(14,165,233,0.25),inset_0_2.5px_1.5px_rgba(220,240,255,0.90),0_0_0_1px_rgba(180,220,255,0.65)]",
"dark:shadow-[0_12px_32px_-4px_rgba(14,165,233,0.40),inset_0_2px_1.5px_rgba(220,240,255,0.35),0_0_0_1px_rgba(180,220,255,0.25)]"
),
focusRing: "ring-2 ring-sky-400/60",
glareGradient:
"linear-gradient(180deg, rgba(225,242,255,0.88) 0%, rgba(180,220,255,0.38) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-sky-700 dark:text-sky-300",
textColor: "text-sky-900 dark:text-sky-100",
placeholderClass: "placeholder-sky-400/70 dark:placeholder-sky-400/50",
},
primary: {
wrapper: cn(
"bg-gradient-to-b from-rose-300/40 via-red-400/25 to-rose-500/30 dark:from-rose-400/30 dark:via-red-500/18 dark:to-rose-600/25",
"border border-rose-300/70 dark:border-rose-400/35",
"shadow-[0_10px_28px_-4px_rgba(244,63,94,0.25),inset_0_2.5px_1.5px_rgba(255,220,220,0.90),0_0_0_1px_rgba(255,180,180,0.65)]",
"dark:shadow-[0_12px_32px_-4px_rgba(244,63,94,0.40),inset_0_2px_1.5px_rgba(255,220,220,0.35),0_0_0_1px_rgba(255,180,180,0.25)]"
),
focusRing: "ring-2 ring-rose-400/60",
glareGradient:
"linear-gradient(180deg, rgba(255,238,240,0.88) 0%, rgba(255,200,200,0.38) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-rose-700 dark:text-rose-300",
textColor: "text-rose-900 dark:text-rose-100",
placeholderClass: "placeholder-rose-400/70 dark:placeholder-rose-400/50",
},
dark: {
wrapper: cn(
"bg-gradient-to-b from-slate-700/60 via-slate-800/45 to-zinc-900/55 dark:from-slate-600/55 dark:via-slate-700/40 dark:to-slate-800/50",
"border border-white/18 dark:border-white/15",
"shadow-[0_10px_28px_-4px_rgba(0,0,0,0.45),inset_0_2.5px_1.5px_rgba(255,255,255,0.18),0_0_0_1px_rgba(255,255,255,0.12)]",
"dark:shadow-[0_12px_32px_-4px_rgba(0,0,0,0.65),inset_0_2px_1.5px_rgba(255,255,255,0.15),0_0_0_1px_rgba(255,255,255,0.10)]"
),
focusRing: "ring-2 ring-white/25",
glareGradient:
"linear-gradient(180deg, rgba(255,255,255,0.22) 0%, rgba(255,255,255,0.08) 45%, rgba(255,255,255,0) 100%)",
labelColor: "text-slate-300",
textColor: "text-white",
placeholderClass: "placeholder-slate-400",
},
};
/* ─── Status Config ──────────────────────────────────────────────── */
const STATUS_RING: Record = {
default: "",
success: "ring-2 ring-emerald-400/60",
error: "ring-2 ring-rose-400/65",
};
const STATUS_HINT: Record = {
default: "text-slate-500 dark:text-slate-400",
success: "text-emerald-600 dark:text-emerald-400",
error: "text-rose-600 dark:text-rose-400",
};
/* ─── Size Config ────────────────────────────────────────────────── */
const SIZE_CONFIG: Record<
LiquidGlassInputSize,
{ height: string; px: string; text: string; iconSize: string; radius: string }
> = {
sm: { height: "h-9", px: "px-3.5", text: "text-xs", iconSize: "w-3.5 h-3.5", radius: "rounded-xl" },
md: { height: "h-11", px: "px-4", text: "text-sm", iconSize: "w-4 h-4", radius: "rounded-2xl" },
lg: { height: "h-13", px: "px-5", text: "text-base", iconSize: "w-5 h-5", radius: "rounded-2xl" },
};
/* ─── Component ─────────────────────────────────────────────────── */
export const LiquidGlassInputField = React.forwardRef<
HTMLInputElement,
LiquidGlassInputProps
>(
(
{
variant = "glass",
size = "md",
status = "default",
label,
hint,
leftIcon,
rightIcon,
type = "text",
className,
wrapperClassName,
id,
disabled,
...props
},
ref
) => {
const autoId = useId();
const inputId = id ?? autoId;
const [showPassword, setShowPassword] = useState(false);
const isPassword = type === "password";
const resolvedType = isPassword ? (showPassword ? "text" : "password") : type;
const cfg = VARIANT_CONFIG[variant];
const sz = SIZE_CONFIG[size];
// Status icon shown right side (overrides rightIcon if set)
const statusIcon =
status === "success" ? (
) : status === "error" ? (
) : null;
const rightSlot = isPassword ? (
) : statusIcon ? (
statusIcon
) : rightIcon ? (
{rightIcon}
) : null;
return (
{/* Label */}
{label && (
)}
{/* Input wrapper */}
{/* Top specular glare */}
{/* Bottom prism refraction */}
{/* Left icon */}
{leftIcon && (
{leftIcon}
)}
{/* Native */}
{/* Right slot */}
{rightSlot && (
{rightSlot}
)}
{/* Hint / error / success text */}
{hint && (
{hint}
)}
);
}
);
LiquidGlassInputField.displayName = "LiquidGlassInputField";
export default LiquidGlassInputField;
```
## Usage
```tsx
import LiquidGlassInputField from "@/components/lightswind/liquid-glass-input"
```
```tsx
import { useState } from "react";
import LiquidGlassInputField from "@/components/lightswind/liquid-glass-input";
import { Mail, Lock } from "lucide-react";
export function Demo() {
const [email, setEmail] = useState("");
return (
setEmail(e.target.value)}
placeholder="alex@company.com"
leftIcon={}
variant="aurora"
size="md"
/>
}
variant="emerald"
size="md"
/>
);
}
```