niceui

Spotlight Card New

Cards lit by a soft light that follows the pointer, with a matching border highlight.

ReactTailwind CSSTypeScriptEffectsMIT · Free
Live preview

Installation

01

Install with the shadcn CLI. The NiceUI theme comes along the first time.

$ npx shadcn@latest add https://niceui.dev/r/effects-spotlight-card.json
02

Or copy the source below. Dependencies: lucide-react.

Source

components/niceui/effects/SpotlightCard.tsx
import { useRef, type PointerEvent, type ReactNode } from 'react';
import { Bolt, Lock, Sparkles, Workflow } from 'lucide-react';
import { cn } from '@/lib/cn';

export type SpotlightCardProps = { children: ReactNode; className?: string; color?: string };

/** A card lit by a soft light that follows the pointer, with a matching border highlight. */
export function SpotlightCard({ children, className, color = '56,189,248' }: SpotlightCardProps) {
  const ref = useRef<HTMLDivElement>(null);
  const move = (e: PointerEvent<HTMLDivElement>) => {
    const el = ref.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    el.style.setProperty('--x', `${e.clientX - r.left}px`);
    el.style.setProperty('--y', `${e.clientY - r.top}px`);
  };
  return (
    <div
      ref={ref}
      onPointerMove={move}
      className={cn('group relative overflow-hidden rounded-2xl bg-ink-900 p-px', className)}
      style={{ background: `radial-gradient(260px circle at var(--x,50%) var(--y,0%), rgba(${color},.55), rgba(255,255,255,.06) 60%)` }}
    >
      <div className="relative h-full rounded-[15px] bg-ink-900 p-5">
        <div aria-hidden className="pointer-events-none absolute inset-0 rounded-[15px] opacity-0 transition-opacity duration-300 group-hover:opacity-100" style={{ background: `radial-gradient(320px circle at var(--x,50%) var(--y,0%), rgba(${color},.12), transparent 60%)` }} />
        <div className="relative">{children}</div>
      </div>
    </div>
  );
}

const items = [
  { icon: Sparkles, title: 'AI suggestions', body: 'Context-aware edits as you type.' },
  { icon: Workflow, title: 'Workflows', body: 'Automate the busywork in a few clicks.' },
  { icon: Lock, title: 'SSO and audit logs', body: 'Enterprise controls, built in.' },
  { icon: Bolt, title: 'Edge-fast', body: 'Sub-50ms responses worldwide.' },
];

export function SpotlightCardDemo() {
  return (
    <div className="grid w-full max-w-2xl grid-cols-1 gap-3 sm:grid-cols-2">
      {items.map(({ icon: Icon, title, body }) => (
        <SpotlightCard key={title}>
          <span className="grid h-9 w-9 place-items-center rounded-lg bg-brand-500/10 text-brand-300">
            <Icon className="h-4 w-4" />
          </span>
          <h3 className="mt-4 text-sm font-medium text-ink-50">{title}</h3>
          <p className="mt-1 text-sm text-ink-400">{body}</p>
        </SpotlightCard>
      ))}
    </div>
  );
}