Campo de vidrio esmerilado
Campo translúcido con desenfoque del fondo, borde de luz e icono; sube su brillo al enfocar. Glassmorfismo.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { useId, useState, type CSSProperties } from "react";
/** Campo de vidrio esmerilado con icono, sobre cualquier fondo de color. Glassmorfismo. React + TypeScript, sin dependencias. */
export type CampoVidrioProps = {
label?: string;
placeholder?: string;
type?: string;
value?: string;
defaultValue?: string;
onChange?: (value: string) => void;
disabled?: boolean;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gccvd-root { box-sizing: border-box; display: block; width: 100%; max-width: 340px; font: 500 15px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; color: var(--gccvd-fg, #fff); }
.gccvd-root *, .gccvd-root *::before, .gccvd-root *::after { box-sizing: border-box; }
.gccvd-root input { font: inherit; }
@media (prefers-reduced-motion: reduce) { .gccvd-root *, .gccvd-root *::before, .gccvd-root *::after { animation: none !important; transition-duration: .01ms !important; } }
.gccvd-label { display: block; margin: 0 0 8px 4px; font-size: 13px; font-weight: 600; letter-spacing: .02em; opacity: .9; }
.gccvd-box { position: relative; display: flex; align-items: center; gap: 12px; height: 54px; padding: 0 18px; border-radius: 16px; background: rgba(255, 255, 255, .14); -webkit-backdrop-filter: blur(18px) saturate(1.5); backdrop-filter: blur(18px) saturate(1.5); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .3), inset 0 1px 0 rgba(255, 255, 255, .5), 0 10px 24px -12px rgba(10, 10, 60, .5); transition: background .25s, box-shadow .25s; }
.gccvd-box:hover { background: rgba(255, 255, 255, .2); }
.gccvd-box:focus-within { background: rgba(255, 255, 255, .24); box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, .85), inset 0 1px 0 rgba(255, 255, 255, .6), 0 0 0 5px rgba(255, 255, 255, .16), 0 10px 24px -12px rgba(10, 10, 60, .5); }
.gccvd-input { flex: 1; min-width: 0; height: 100%; border: 0; background: transparent; color: inherit; outline: 0; }
.gccvd-input::placeholder { color: rgba(255, 255, 255, .72); }
.gccvd-input::selection { background: rgba(255, 255, 255, .35); }
.gccvd-icon { flex-shrink: 0; opacity: .85; }
.gccvd-box[data-disabled="true"] { opacity: .5; }`;
export function CampoVidrio({ label = "Correo", placeholder = "tu@correo.com", type = "email", value, defaultValue = "", onChange, disabled, className = "", style }: CampoVidrioProps) {
const id = useId();
const [inner, setInner] = useState(defaultValue);
return (
<div className={`gccvd-root ${className}`} style={style}>
<style>{CSS}</style>
<label className="gccvd-label" htmlFor={id}>
{label}
</label>
<div className="gccvd-box" data-disabled={disabled ? "true" : undefined}>
<svg className="gccvd-icon" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
<rect x="3" y="5" width="18" height="14" rx="3" />
<path d="m4 7 8 6 8-6" />
</svg>
<input
id={id}
className="gccvd-input"
type={type}
placeholder={placeholder}
value={value ?? inner}
disabled={disabled}
onChange={(event) => {
setInner(event.target.value);
onChange?.(event.target.value);
}}
/>
</div>
</div>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/campo-vidrioEjemplo de uso de Campo de vidrio esmerilado
Después de copiar campo-vidrio.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { CampoVidrio } from "./campo-vidrio";
export default function Ejemplo() {
return <CampoVidrio label="Ejemplo" />;
}Propiedades de CampoVidrio
CampoVidrio acepta 9 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
label? | string | Opcional. |
placeholder? | string | Opcional. |
type? | string | Opcional. |
value? | string | Opcional. |
defaultValue? | string | Opcional. |
onChange? | (value: string) => void | Opcional. |
disabled? | boolean | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Personaliza Campo de vidrio esmerilado con variables CSS
Define estas variables en el contenedor o en tu hoja de estilos para cambiar los colores sin tocar el componente. Si no las defines, se usa el valor por defecto.
| Variable | Valor por defecto |
|---|---|
--gccvd-fg | #fff |
Accesibilidad y rendimiento
El archivo tiene 63 líneas (3 KB) y no necesita @keyframes. Esto es lo que hace Campo de vidrio esmerilado por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Expone su estado a tecnologías de apoyo con atributos aria-*.
- Usa backdrop-filter para el efecto de vidrio; en navegadores sin soporte el panel se ve sin desenfoque.
- Es un componente de cliente de Next.js: incluye la directiva "use client".