Ir al contenido
Evaluar mi proyecto
Componentes · FormulariosDisponible

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.

campo-vidrio.tsx63 líneas
Descargar
"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.

terminal.sh1 líneas
npx shadcn@latest add https://www.gassierconsulting.com/r/campo-vidrio

Ejemplo 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.

ejemplo.tsx5 líneas
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.

PropiedadTipoDescripción
label?stringOpcional.
placeholder?stringOpcional.
type?stringOpcional.
value?stringOpcional.
defaultValue?stringOpcional.
onChange?(value: string) => voidOpcional.
disabled?booleanOpcional.
className?stringOpcional.
style?CSSPropertiesOpcional.

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.

VariableValor 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".
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React 18 y 19 · Next.js (componente de cliente)