|
| 1 | +@php $iconVariant = $iconVariant ??= $attributes->pluck('icon:variant'); @endphp |
| 2 | + |
| 3 | +@props([ |
| 4 | + 'iconVariant' => 'solid', |
| 5 | + 'initials' => null, |
| 6 | + 'tooltip' => null, |
| 7 | + 'circle' => null, |
| 8 | + 'color' => null, |
| 9 | + 'badge' => null, |
| 10 | + 'name' => null, |
| 11 | + 'icon' => null, |
| 12 | + 'size' => 'md', |
| 13 | + 'src' => null, |
| 14 | + 'href' => null, |
| 15 | + 'alt' => null, |
| 16 | + 'as' => 'div', |
| 17 | +]) |
| 18 | + |
| 19 | +@php |
| 20 | +if ($name && ! $initials) { |
| 21 | + $parts = explode(' ', preg_replace('/[^a-zA-Z\s]/', '', $name)); |
| 22 | +
|
| 23 | + if ($attributes->pluck('initials:single')) { |
| 24 | + $initials = strtoupper($parts[0][0]); |
| 25 | + } else { |
| 26 | + if (count($parts) > 1) { |
| 27 | + $initials = strtoupper($parts[0][0] . $parts[1][0]); |
| 28 | + } else { |
| 29 | + $initials = strtoupper($parts[0][0]) . strtolower($parts[0][1]); |
| 30 | + } |
| 31 | + } |
| 32 | +} |
| 33 | +
|
| 34 | +if ($name && $tooltip === true) { |
| 35 | + $tooltip = $name; |
| 36 | +} |
| 37 | +
|
| 38 | +$hasTextContent = $icon ?? $initials ?? $slot->isNotEmpty(); |
| 39 | +
|
| 40 | +// Be careful not to change the order of these colors. |
| 41 | +// They're used in the hash function below and changing them would change actual user avatar colors that they might have grown to identify with. |
| 42 | +$colors = ['red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose']; |
| 43 | +
|
| 44 | +if ($hasTextContent && $color === 'auto') { |
| 45 | + $colorSeed = $attributes->pluck('color:seed') ?? $name ?? $icon ?? $initials ?? $slot; |
| 46 | + $hash = crc32((string) $colorSeed); |
| 47 | + $color = $colors[$hash % count($colors)]; |
| 48 | +} |
| 49 | +
|
| 50 | +$classes = Flux::classes() |
| 51 | + ->add(match($size) { |
| 52 | + 'xl' => '[:where(&)]:size-16 [:where(&)]:text-base', |
| 53 | + 'lg' => '[:where(&)]:size-12 [:where(&)]:text-base', |
| 54 | + default => '[:where(&)]:size-10 [:where(&)]:text-sm', |
| 55 | + 'sm' => '[:where(&)]:size-8 [:where(&)]:text-sm', |
| 56 | + 'xs' => '[:where(&)]:size-6 [:where(&)]:text-xs', |
| 57 | + }) |
| 58 | + ->add($circle ? '[--avatar-radius:calc(infinity*1px)]' : match($size) { |
| 59 | + 'xl' => '[--avatar-radius:var(--radius-xl)]', |
| 60 | + 'lg' => '[--avatar-radius:var(--radius-lg)]', |
| 61 | + default => '[--avatar-radius:var(--radius-lg)]', |
| 62 | + 'sm' => '[--avatar-radius:var(--radius-md)]', |
| 63 | + 'xs' => '[--avatar-radius:var(--radius-sm)]', |
| 64 | + }) |
| 65 | + ->add('relative isolate flex items-center justify-center') |
| 66 | + ->add('[:where(&)]:font-medium') |
| 67 | + ->add('rounded-[var(--avatar-radius)]') |
| 68 | + ->add($hasTextContent ? '[:where(&)]:bg-zinc-200 [:where(&)]:dark:bg-zinc-600 [:where(&)]:text-zinc-800 [:where(&)]:dark:text-white' : '') |
| 69 | + ->add(match($color) { |
| 70 | + 'red' => 'bg-red-200 text-red-800', |
| 71 | + 'orange' => 'bg-orange-200 text-orange-800', |
| 72 | + 'amber' => 'bg-amber-200 text-amber-800', |
| 73 | + 'yellow' => 'bg-yellow-200 text-yellow-800', |
| 74 | + 'lime' => 'bg-lime-200 text-lime-800', |
| 75 | + 'green' => 'bg-green-200 text-green-800', |
| 76 | + 'emerald' => 'bg-emerald-200 text-emerald-800', |
| 77 | + 'teal' => 'bg-teal-200 text-teal-800', |
| 78 | + 'cyan' => 'bg-cyan-200 text-cyan-800', |
| 79 | + 'sky' => 'bg-sky-200 text-sky-800', |
| 80 | + 'blue' => 'bg-blue-200 text-blue-800', |
| 81 | + 'indigo' => 'bg-indigo-200 text-indigo-800', |
| 82 | + 'violet' => 'bg-violet-200 text-violet-800', |
| 83 | + 'purple' => 'bg-purple-200 text-purple-800', |
| 84 | + 'fuchsia' => 'bg-fuchsia-200 text-fuchsia-800', |
| 85 | + 'pink' => 'bg-pink-200 text-pink-800', |
| 86 | + 'rose' => 'bg-rose-200 text-rose-800', |
| 87 | + default => '', |
| 88 | + }) |
| 89 | + ->add(true ? [ |
| 90 | + 'after:absolute after:inset-0 after:inset-ring-[1px] after:inset-ring-black/7 dark:after:inset-ring-white/10', |
| 91 | + $circle ? 'after:rounded-full' : match($size) { |
| 92 | + 'xl' => 'after:rounded-xl', |
| 93 | + 'lg' => 'after:rounded-lg', |
| 94 | + default => 'after:rounded-lg', |
| 95 | + 'sm' => 'after:rounded-md', |
| 96 | + 'xs' => 'after:rounded-sm', |
| 97 | + }, |
| 98 | + ] : []); |
| 99 | +
|
| 100 | +$iconClasses = Flux::classes() |
| 101 | + ->add('opacity-75') |
| 102 | + ->add(match($size) { |
| 103 | + 'lg' => 'size-8', |
| 104 | + default => 'size-6', |
| 105 | + 'sm' => 'size-5', |
| 106 | + 'xs' => 'size-4', |
| 107 | + }); |
| 108 | +
|
| 109 | +$badgeColor = $attributes->pluck('badge:color') ?: (is_object($badge) ? $badge?->attributes?->pluck('color') : null); |
| 110 | +$badgeCircle = $attributes->pluck('badge:circle') ?: (is_object($badge) ? $badge?->attributes?->pluck('circle') : null); |
| 111 | +$badgePosition = $attributes->pluck('badge:position') ?: (is_object($badge) ? $badge?->attributes?->pluck('position') : null); |
| 112 | +$badgeVariant = $attributes->pluck('badge:variant') ?: (is_object($badge) ? $badge?->attributes?->pluck('variant') : null); |
| 113 | +
|
| 114 | +$badgeClasses = Flux::classes() |
| 115 | + ->add('absolute min-h-3 min-w-3 ring-[2px] ring-white dark:ring-zinc-900 z-10') |
| 116 | + ->add('flex items-center justify-center tabular-nums overflow-hidden') |
| 117 | + ->add('text-[.625rem] text-zinc-800 dark:text-white font-medium') |
| 118 | + ->add($badgeCircle ? 'rounded-full' : 'rounded-[3px]') |
| 119 | + ->add($badgeVariant === 'outline' ? [ |
| 120 | + 'after:absolute after:inset-[3px] after:bg-white dark:after:bg-zinc-900', |
| 121 | + $badgeCircle ? 'after:rounded-full' : 'after:rounded-[1px]', |
| 122 | + ] : []) |
| 123 | + ->add(match($badgePosition) { |
| 124 | + 'top left' => 'top-0 left-0', |
| 125 | + 'top right' => 'top-0 right-0', |
| 126 | + 'bottom left' => 'bottom-0 left-0', |
| 127 | + 'bottom right' => 'bottom-0 right-0', |
| 128 | + default => 'bottom-0 right-0', |
| 129 | + }) |
| 130 | + ->add(match($badgeColor) { |
| 131 | + 'red' => 'bg-red-500 dark:bg-red-400', |
| 132 | + 'orange' => 'bg-orange-500 dark:bg-orange-400', |
| 133 | + 'amber' => 'bg-amber-500 dark:bg-amber-400', |
| 134 | + 'yellow' => 'bg-yellow-500 dark:bg-yellow-400', |
| 135 | + 'lime' => 'bg-lime-500 dark:bg-lime-400', |
| 136 | + 'green' => 'bg-green-500 dark:bg-green-400', |
| 137 | + 'emerald' => 'bg-emerald-500 dark:bg-emerald-400', |
| 138 | + 'teal' => 'bg-teal-500 dark:bg-teal-400', |
| 139 | + 'cyan' => 'bg-cyan-500 dark:bg-cyan-400', |
| 140 | + 'sky' => 'bg-sky-500 dark:bg-sky-400', |
| 141 | + 'blue' => 'bg-blue-500 dark:bg-blue-400', |
| 142 | + 'indigo' => 'bg-indigo-500 dark:bg-indigo-400', |
| 143 | + 'violet' => 'bg-violet-500 dark:bg-violet-400', |
| 144 | + 'purple' => 'bg-purple-500 dark:bg-purple-400', |
| 145 | + 'fuchsia' => 'bg-fuchsia-500 dark:bg-fuchsia-400', |
| 146 | + 'pink' => 'bg-pink-500 dark:bg-pink-400', |
| 147 | + 'rose' => 'bg-rose-500 dark:bg-rose-400', |
| 148 | + 'zinc' => 'bg-zinc-400 dark:bg-zinc-300', |
| 149 | + 'gray' => 'bg-zinc-400 dark:bg-zinc-300', |
| 150 | + default => 'bg-white dark:bg-zinc-900', |
| 151 | + }) |
| 152 | + ; |
| 153 | +
|
| 154 | +$label = $alt ?? $name; |
| 155 | +@endphp |
| 156 | + |
| 157 | +<flux:with-tooltip :$tooltip :$attributes> |
| 158 | + <flux:button-or-link :attributes="$attributes->class($classes)->merge($circle ? ['data-circle' => 'true'] : [])" :$as :$href data-flux-avatar data-slot="avatar" data-size="{{ $size }}"> |
| 159 | + <?php if ($src): ?> |
| 160 | + <img src="{{ $src }}" alt="{{ $alt ?? $name }}" class="rounded-[var(--avatar-radius)]"> |
| 161 | + <?php elseif ($icon): ?> |
| 162 | + <flux:icon :name="$icon" :variant="$iconVariant" :class="$iconClasses" /> |
| 163 | + <?php elseif ($hasTextContent): ?> |
| 164 | + <span class="select-none">{{ $initials ?? $slot }}</span> |
| 165 | + <?php endif; ?> |
| 166 | + |
| 167 | + <?php if ($badge instanceof \Illuminate\View\ComponentSlot): ?> |
| 168 | + <div {{ $badge->attributes->class($badgeClasses) }} aria-hidden="true">{{ $badge }}</div> |
| 169 | + <?php elseif ($badge): ?> |
| 170 | + <div class="{{ $badgeClasses }}" aria-hidden="true">{{ is_string($badge) ? $badge : '' }}</div> |
| 171 | + <?php endif; ?> |
| 172 | + </flux:button-or-link> |
| 173 | +</flux:with-tooltip> |
0 commit comments