Falnix UI

Gradient Input

A premium text input with a mouse-following gradient border effect. Features performance-optimized mouse tracking and seamless touch support.

FormsInteractiveAccessible

Component Preview

States & Variants

Error State

This field is required.

Disabled State

Custom Gradient Color

style={{ "--input-border-gradient": "#3b82f6" }}

Override the CSS variable --input-border-gradient on the parent or the component itself to change the glow color.

Installation

npm install clsx tailwind-merge

Copy the source code below into components/ui/glow-input.tsx:

1"use client";
2
3import * as React from "react";
4import { cn } from "@/lib/utils";
5
6export interface GlowInputProps
7 extends React.InputHTMLAttributes<HTMLInputElement> {
8 id?: string;
9 error?: boolean;
10}
11
12const GlowInput = React.forwardRef<HTMLInputElement, GlowInputProps>(
13 ({ className, type, id, error, onFocus, onBlur, ...props }, ref) => {
14 const [focused, setFocused] = React.useState(false);
15 const containerRef = React.useRef<HTMLDivElement>(null);
16
17 React.useEffect(() => {
18 const container = containerRef.current;
19 if (!container) return;
20
21 const handleMouseMove = (e: MouseEvent) => {
22 const rect = container.getBoundingClientRect();
23 const x = e.clientX - rect.left;
24 const y = e.clientY - rect.top;
25 container.style.setProperty("--mouse-x", `${x}px`);
26 container.style.setProperty("--mouse-y", `${y}px`);
27 };
28
29 container.addEventListener("mousemove", handleMouseMove);
30 return () => {
31 container.removeEventListener("mousemove", handleMouseMove);
32 };
33 }, []);
34
35 const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
36 setFocused(true);
37 onFocus?.(e);
38 };
39
40 const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
41 setFocused(false);
42 onBlur?.(e);
43 };
44
45 return (
46 <div
47 ref={containerRef}
48 className={cn(
49 "group relative rounded-xl p-[1px] transition-all duration-300",
50 "bg-neutral-800", // Default border color
51 error ? "bg-red-500/50" : focused ? "bg-neutral-600" : "hover:bg-neutral-700"
52 )}
53 style={
54 {
55 "--mouse-x": "0px",
56 "--mouse-y": "0px",
57 background: error
58 ? undefined
59 : `radial-gradient(600px circle at var(--mouse-x) var(--mouse-y), rgba(255, 255, 255, 0.4), transparent 40%),
60 radial-gradient(400px circle at var(--mouse-x) var(--mouse-y), var(--input-border-gradient, #a78bfa), transparent 40%)`
61 } as React.CSSProperties
62 }
63 >
64 {/* Inner Background Mask to create the border effect */}
65 <div className="relative rounded-[10px] bg-neutral-950 h-full w-full">
66 <input
67 ref={ref}
68 type={type}
69 id={id}
70 className={cn(
71 "w-full bg-transparent px-4 py-3 text-sm text-white placeholder:text-neutral-500",
72 "focus:outline-none",
73 "disabled:cursor-not-allowed disabled:opacity-50",
74 "h-11", // Explicit height for better touch targets
75 className
76 )}
77 onFocus={handleFocus}
78 onBlur={handleBlur}
79 {...props}
80 />
81 </div>
82 </div>
83 );
84 }
85);
86GlowInput.displayName = "GlowInput";
87
88export { GlowInput };