Copy URL or Code
Paste to your AI coding assistant and customize:
Done. Your AI handles the rest.
Fully customizable. Features a smooth rotating conic gradient with blur glow. Supports light/dark themes out of the box.
/*
================================================================================
AI COMPONENT: RainbowRing
================================================================================
A search/input field with:
- Animated rotating rainbow gradient border
- Horizontal outer glow that follows the border colors
- Light/dark theme support
================================================================================
QUICK REFERENCE FOR AI AGENTS
================================================================================
WHEN USER ASKS TO... MODIFY THIS SECTION
─────────────────────────────────────────────────────────────────────────────
Change colors → Look for "CUSTOMIZE: COLORS" comment
Change border thickness → borderSize prop (default: 2)
Change animation speed → animationDuration prop (default: 5)
Change overall size/padding → Look for "CUSTOMIZE: SIZE" comment
Change shape (pill/rounded/square) → Look for "CUSTOMIZE: SHAPE" comment
Change glow intensity → Look for "CUSTOMIZE: GLOW" comment
Change/remove icons → Look for "CUSTOMIZE: ICONS" comment
Switch theme → theme prop: "light" | "dark"
Handle form submission → onSubmit prop callback
Add custom styling → className prop
================================================================================
SETUP
================================================================================
1. Create file: components/RainbowRing.tsx
2. Copy this entire code block into that file
3. Import: import RainbowRing from "@/components/RainbowRing"
4. Use: <RainbowRing placeholder="Search..." theme="dark" />
================================================================================
PROPS
================================================================================
| Prop | Type | Default |
|-------------------|-----------------------|----------------|
| placeholder | string | "Ask anything" |
| theme | "light" | "dark" | "light" |
| borderSize | number (px) | 2 |
| animationDuration | number (seconds) | 5 |
| className | string | "" |
| onSubmit | (value: string)=>void | undefined |
================================================================================
SOURCE CODE (with customization markers)
================================================================================
*/
"use client";
import React from "react";
interface RainbowRingProps {
placeholder?: string;
theme?: "light" | "dark";
borderSize?: number;
animationDuration?: number;
className?: string;
onSubmit?: (value: string) => void;
}
export function RainbowRing({
placeholder = "Ask anything",
theme = "light",
borderSize = 2,
animationDuration = 5,
className = "",
onSubmit,
}: RainbowRingProps) {
const isDark = theme === "dark";
const [value, setValue] = React.useState("");
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (onSubmit && value.trim()) {
onSubmit(value);
setValue("");
}
};
return (
<div className={`rainbow-wrapper ${className}`}>
{/* Glow layer - horizontal shape with color animation */}
<div className="glow">
<div className="glow-gradient" />
</div>
{/* Main input */}
<form onSubmit={handleSubmit} className="rainbow-ring">
{/* Border gradient */}
<div className="border-layer">
<div className="border-gradient" />
</div>
<div className="inner">
{/* ========== CUSTOMIZE: ICONS (left button) ========== */}
{/* Replace this SVG with any icon. To remove: delete this button */}
<button type="button" className="icon-btn" aria-label="Add">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" y1="5" x2="12" y2="19" />
<line x1="5" y1="12" x2="19" y2="12" />
</svg>
</button>
<input
type="text"
placeholder={placeholder}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
{/* ========== CUSTOMIZE: ICONS (right button) ========== */}
{/* Replace this SVG with any icon. To remove: delete this button */}
<button type="submit" className="icon-btn" aria-label="Submit">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z" />
<path d="M19 10v2a7 7 0 0 1-14 0v-2" />
<line x1="12" y1="19" x2="12" y2="23" />
<line x1="8" y1="23" x2="16" y2="23" />
</svg>
</button>
</div>
</form>
<style jsx>{`
.rainbow-wrapper {
--border-size: ${borderSize}px;
--duration: ${animationDuration}s;
position: relative;
}
/* ============================================================
CUSTOMIZE: GLOW
- inset: -12px = glow spread (more negative = wider glow)
- filter: blur(15px) = glow softness
- opacity: 0.8 = glow intensity (0-1)
To remove glow: delete .glow and .glow-gradient sections
============================================================ */
.glow {
position: absolute;
inset: -12px;
border-radius: 5rem;
z-index: 0;
pointer-events: none;
overflow: visible;
}
.glow-gradient {
position: absolute;
inset: 0;
border-radius: inherit;
/* CUSTOMIZE: COLORS (glow) - match these with border colors */
background: linear-gradient(
90deg,
#4285f4 0%, /* blue */
#ea4335 25%, /* red */
#fbbc05 50%, /* yellow */
#34a853 75%, /* green */
#4285f4 100% /* blue (loop) */
);
background-size: 200% 100%;
filter: blur(15px);
opacity: 0.8;
animation: glow-shift var(--duration) linear infinite;
}
@keyframes glow-shift {
0% {
background-position: 0% 50%;
filter: blur(15px) hue-rotate(0deg);
}
100% {
background-position: 200% 50%;
filter: blur(15px) hue-rotate(360deg);
}
}
/* ============================================================
CUSTOMIZE: SHAPE
- border-radius: 4rem = pill shape (current)
- border-radius: 1rem = rounded rectangle
- border-radius: 0.5rem = slightly rounded
- border-radius: 0 = square
============================================================ */
.rainbow-ring {
border-radius: 4rem;
position: relative;
padding: var(--border-size);
border: var(--border-size) solid ${isDark ? "#333" : "lightgray"};
}
/* BORDER GRADIENT - rotating conic gradient */
.border-layer {
position: absolute;
inset: calc(var(--border-size) * -1);
border-radius: inherit;
overflow: hidden;
mask: linear-gradient(white, white);
-webkit-mask: linear-gradient(white, white);
}
.border-gradient {
position: absolute;
top: 50%;
left: 50%;
width: 200%;
height: 200%;
transform: translate(-50%, -50%);
/* CUSTOMIZE: COLORS (border) - the rotating rainbow gradient */
background: conic-gradient(
from 0deg,
#4285f4 0%, /* blue */
#ea4335 25%, /* red */
#fbbc05 50%, /* yellow */
#34a853 75%, /* green */
#4285f4 100% /* blue (loop) */
);
filter: blur(3px);
animation: spin var(--duration) linear infinite;
}
/* ============================================================
CUSTOMIZE: SIZE
- padding: 1rem 0.5rem = inner spacing
- min-width: 200px = minimum input width
- gap: 0.75rem = space between icons and input
============================================================ */
.inner {
background: ${isDark ? "#1a1c1e" : "white"};
color: ${isDark ? "hsl(210, 8%, 66%)" : "#222"};
padding: 1rem 0.5rem;
position: relative;
z-index: 2;
border-radius: calc(4rem - var(--border-size));
display: grid;
grid-template-columns: auto 1fr auto;
align-items: center;
gap: 0.75rem;
font-family: system-ui, sans-serif;
}
.icon-btn {
color: ${isDark ? "hsl(210, 8%, 66%)" : "#222"};
background: none;
border: none;
padding: 0.25rem;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: opacity 0.2s ease;
}
.icon-btn:hover {
opacity: 0.7;
}
input {
color: ${isDark ? "hsl(210, 8%, 66%)" : "#222"};
background: none;
border: none;
font-size: 1rem;
font-family: system-ui, sans-serif;
font-weight: 300;
width: 100%;
min-width: 200px;
}
input:focus {
outline: none;
}
input:not(:placeholder-shown) {
color: ${isDark ? "white" : "black"};
}
input::placeholder {
color: ${isDark ? "hsl(210, 8%, 50%)" : "#888"};
}
@keyframes spin {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
`}</style>
</div>
);
}
export default RainbowRing;/*
================================================================================
USAGE EXAMPLES
================================================================================
*/
import RainbowRing from "@/components/RainbowRing";
// ============================================================================
// BASIC USAGE - Light theme (default)
// ============================================================================
export default function MyPage() {
return (
<div className="flex items-center justify-center h-screen bg-gray-100">
<RainbowRing placeholder="Ask anything..." />
</div>
);
}
// ============================================================================
// DARK THEME - For dark backgrounds
// ============================================================================
export function DarkModeExample() {
return (
<div className="bg-black min-h-screen flex items-center justify-center p-8">
<RainbowRing theme="dark" placeholder="Search in dark mode..." />
</div>
);
}
// ============================================================================
// CUSTOM SPEED & SIZE - Faster animation, thicker border
// ============================================================================
export function CustomizedRing() {
return (
<RainbowRing
animationDuration={3} // Faster: 3 seconds per cycle
borderSize={4} // Thicker border
placeholder="Quick search..."
/>
);
}
// ============================================================================
// WITH SUBMIT HANDLER - Handle user input
// ============================================================================
export function SearchWithHandler() {
const handleSearch = (value: string) => {
console.log("User searched:", value);
// Add your search logic here
};
return (
<RainbowRing
placeholder="Type and press Enter"
onSubmit={handleSearch}
/>
);
}
// ============================================================================
// CUSTOMIZATION EXAMPLES (modify the component code directly)
// ============================================================================
/*
CHANGE COLORS (edit .border-gradient and .glow-gradient):
Purple theme:
background: conic-gradient(
from 0deg,
#9333ea 0%, // purple
#ec4899 25%, // pink
#f43f5e 50%, // rose
#a855f7 75%, // violet
#9333ea 100%
);
Blue theme:
background: conic-gradient(
from 0deg,
#0ea5e9 0%, // sky
#3b82f6 25%, // blue
#6366f1 50%, // indigo
#8b5cf6 75%, // violet
#0ea5e9 100%
);
CHANGE SHAPE (edit border-radius in .rainbow-ring):
Pill (default): border-radius: 4rem;
Rounded box: border-radius: 1rem;
Sharp corners: border-radius: 0.25rem;
CHANGE GLOW INTENSITY (edit .glow-gradient):
Stronger glow: opacity: 1.0; filter: blur(20px);
Softer glow: opacity: 0.5; filter: blur(10px);
No glow: Remove the .glow div entirely
*/