Skip to main content

Layout primitives

Card Stack code

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

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

@props([
    'title',
    'meta' => null,
    'count' => null,
    'href' => null,
])

@php
    /*
    | Paper-stack card: two offset sheets peek out behind the top card and
    | fan apart on hover, so a group of things looks like a physical pile.
    | Use for collections — drafts, batches, imports, saved reports.
    |
    | count: number of items in the pile, shown as a chip
    |
    | Usage:
    |   <x-ui.card-stack title="Release drafts" meta="Edited 2h ago" :count="4" href="/drafts">
    |       Unpublished changelog entries awaiting review.
    |   </x-ui.card-stack>
    */
    $tag = $href ? 'a' : 'div';
@endphp

<{{ $tag }}
    @if ($href) href="{{ $href }}" @endif
    {{ $attributes->merge(['class' => 'group/stack relative block min-w-0']) }}
>
    {{-- Sheets underneath --}}
    <span class="absolute inset-x-2 -bottom-2 h-10 rotate-1 rounded-xl border border-gray-200 bg-gray-50 transition-transform duration-300 motion-safe:group-hover/stack:translate-y-1 motion-safe:group-hover/stack:rotate-2 dark:border-gray-800 dark:bg-gray-950" aria-hidden="true"></span>
    <span class="absolute inset-x-1 -bottom-1 h-10 -rotate-1 rounded-xl border border-gray-200 bg-gray-100 transition-transform duration-300 motion-safe:group-hover/stack:translate-y-0.5 motion-safe:group-hover/stack:-rotate-2 dark:border-gray-800 dark:bg-gray-900" aria-hidden="true"></span>

    {{-- Top card --}}
    <span class="relative block rounded-xl border border-gray-200 bg-white p-5 transition-shadow duration-300 group-hover/stack:shadow-md dark:border-gray-800 dark:bg-gray-900">
        <span class="flex items-start justify-between gap-3">
            <span class="min-w-0">
                <span class="block truncate text-sm font-semibold tracking-tight text-gray-900 dark:text-white">{{ $title }}</span>
                @if ($meta)
                    <span class="mt-0.5 block text-xs text-gray-500 dark:text-gray-400">{{ $meta }}</span>
                @endif
            </span>
            @if ($count !== null)
                <span class="inline-flex shrink-0 items-center rounded-full bg-gray-100 px-2 py-0.5 font-mono text-[11px] font-semibold tabular-nums text-gray-600 dark:bg-gray-800 dark:text-gray-300">×{{ $count }}</span>
            @endif
        </span>

        @if ($slot->isNotEmpty())
            <span class="mt-2 block text-sm leading-relaxed text-gray-600 dark:text-gray-400">{{ $slot }}</span>
        @endif
    </span>
</{{ $tag }}>