Skip to main content

Content & marketing

Glow Card code

Copy the implementation or inspect every file that belongs to this component unit.

resources/views/components/ui/glow-card.blade.php

@props([
    'icon' => null,
    'iconWeight' => 'duotone',
    'title' => null,
    'href' => null,
    'meta' => null,
])

@php
    /*
    | Spotlight card with a soft radial glow that tracks the cursor and a hairline
    | border that lights up on hover — the treatment used across Cloudflare,
    | Vercel and Linear marketing pages. Renders as an <a> when `href` is set.
    |
    | icon:  optional Phosphor icon shown in a rounded tile
    | meta:  optional small text shown top-right (e.g. a category)
    |
    | Usage:
    |   <x-ui.glow-card icon="plug" title="Webhooks" href="#">
    |       Stream events to any endpoint in real time.
    |   </x-ui.glow-card>
    */
    $tag = $href ? 'a' : 'div';
@endphp

<{{ $tag }}
    @if ($href) href="{{ $href }}" @endif
    x-data="{ rx: '50%', ry: '50%' }"
    @mousemove="rx = ($event.offsetX / $el.offsetWidth * 100) + '%'; ry = ($event.offsetY / $el.offsetHeight * 100) + '%'"
    style="--glow-x: 50%; --glow-y: 50%"
    :style="`--glow-x: ${rx}; --glow-y: ${ry}`"
    {{ $attributes->merge(['class' => 'group/glow relative block overflow-hidden rounded-2xl border border-gray-200 bg-white p-6 transition-colors duration-300 hover:border-brand-300 dark:border-gray-800 dark:bg-gray-900 dark:hover:border-brand-700']) }}
>
    {{-- Cursor-following glow --}}
    <div
        class="pointer-events-none absolute inset-0 -z-0 opacity-0 transition-opacity duration-300 group-hover/glow:opacity-100"
        style="background: radial-gradient(360px circle at var(--glow-x) var(--glow-y), var(--color-brand-500), transparent 40%); mask-image: radial-gradient(360px circle at var(--glow-x) var(--glow-y), black, transparent 40%);"
        aria-hidden="true"
    ></div>
    {{-- Inner fill so only a thin glowing edge shows --}}
    <div class="pointer-events-none absolute inset-px -z-0 rounded-[15px] bg-white dark:bg-gray-900" aria-hidden="true"></div>

    <div class="relative z-10">
        <div class="flex items-start justify-between gap-3">
            @if ($icon)
                <span class="flex h-11 w-11 items-center justify-center rounded-xl bg-brand-50 text-brand-600 ring-1 ring-brand-100 transition group-hover/glow:bg-brand-100 dark:bg-brand-950/60 dark:text-brand-400 dark:ring-brand-900/60">
                    <x-ui.icon :name="$icon" :weight="$iconWeight" size="xl" />
                </span>
            @endif

            @if ($meta)
                <span class="text-xs font-medium uppercase tracking-wider text-gray-400 dark:text-gray-500">{{ $meta }}</span>
            @endif

            @if ($href)
                <x-ui.icon name="arrow-up-right" weight="bold" size="base" class="ml-auto text-gray-300 transition group-hover/glow:translate-x-0.5 group-hover/glow:-translate-y-0.5 group-hover/glow:text-brand-500 dark:text-gray-600" />
            @endif
        </div>

        @if ($title)
            <h3 class="mt-4 text-base font-semibold tracking-tight text-gray-900 dark:text-white">{{ $title }}</h3>
        @endif

        <div class="mt-1.5 text-sm leading-relaxed text-gray-600 dark:text-gray-400">
            {{ $slot }}
        </div>
    </div>
</{{ $tag }}>