feat: Replace user avatar with Facehash faces (#86)
## Summary - Replaced the default initials-based avatar fallback with [Facehash](https://facehash.dev/) — deterministic, unique avatar faces generated from the user's name - Same name always produces the same face, no API calls needed - Fully rounded with `rounded-full` styling ## Preview  Each user gets a unique, consistent face based on their name — no more generic initials. ## Changes - Installed `facehash` package - Updated `resources/js/components/user-info.tsx` to use `<Facehash>` instead of `<Avatar>` with initials fallback ## Test plan - [x] Verify avatar renders correctly in the sidebar footer (desktop) - [x] Verify avatar renders correctly in the mobile header - [x] Verify avatar renders correctly in the user dropdown menu - [x] Confirm the same user always gets the same face - [x] Check dark mode appearance
This commit is contained in:
parent
cc666a3111
commit
6aa9da3df3
3
bun.lock
3
bun.lock
|
|
@ -36,6 +36,7 @@
|
|||
"date-fns": "^4.1.0",
|
||||
"dexie": "^4.2.1",
|
||||
"dexie-react-hooks": "^4.2.0",
|
||||
"facehash": "^0.0.5",
|
||||
"globals": "^15.14.0",
|
||||
"input-otp": "^1.4.2",
|
||||
"json-logic-js": "^2.0.5",
|
||||
|
|
@ -1029,6 +1030,8 @@
|
|||
|
||||
"exsolve": ["exsolve@1.0.8", "", {}, "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA=="],
|
||||
|
||||
"facehash": ["facehash@0.0.5", "", { "peerDependencies": { "@types/react": "", "next": ">=15", "react": ">=18 <20", "react-dom": ">=18 <20" }, "optionalPeers": ["@types/react", "next"] }, "sha512-txM9veJ9IPNWsimpHD+Qqr5aFcSdgJPBY2oTRzRgIfSPcLxwZQY4++7vv9fHjco25ErUxC9pdq9tPB9NK1UhTQ=="],
|
||||
|
||||
"fast-content-type-parse": ["fast-content-type-parse@3.0.0", "", {}, "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg=="],
|
||||
|
||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@
|
|||
"date-fns": "^4.1.0",
|
||||
"dexie": "^4.2.1",
|
||||
"dexie-react-hooks": "^4.2.0",
|
||||
"facehash": "^0.0.5",
|
||||
"globals": "^15.14.0",
|
||||
"input-otp": "^1.4.2",
|
||||
"json-logic-js": "^2.0.5",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,32 @@
|
|||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { useInitials } from '@/hooks/use-initials';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { type User } from '@/types';
|
||||
import { Facehash } from 'facehash';
|
||||
import { Avatar } from './ui/avatar';
|
||||
|
||||
export const tailwindColorClasses = [
|
||||
'bg-slate-200 dark:bg-slate-800',
|
||||
'bg-gray-200 dark:bg-gray-800',
|
||||
'bg-zinc-200 dark:bg-zinc-800',
|
||||
'bg-neutral-200 dark:bg-neutral-800',
|
||||
'bg-stone-200 dark:bg-stone-800',
|
||||
'bg-red-200 dark:bg-red-800',
|
||||
'bg-orange-200 dark:bg-orange-800',
|
||||
'bg-amber-200 dark:bg-amber-800',
|
||||
'bg-yellow-200 dark:bg-yellow-800',
|
||||
'bg-lime-200 dark:bg-lime-800',
|
||||
'bg-green-200 dark:bg-green-800',
|
||||
'bg-emerald-200 dark:bg-emerald-800',
|
||||
'bg-teal-200 dark:bg-teal-800',
|
||||
'bg-cyan-200 dark:bg-cyan-800',
|
||||
'bg-sky-200 dark:bg-sky-800',
|
||||
'bg-blue-200 dark:bg-blue-800',
|
||||
'bg-indigo-200 dark:bg-indigo-800',
|
||||
'bg-violet-200 dark:bg-violet-800',
|
||||
'bg-purple-200 dark:bg-purple-800',
|
||||
'bg-fuchsia-200 dark:bg-fuchsia-800',
|
||||
'bg-pink-200 dark:bg-pink-800',
|
||||
'bg-rose-200 dark:bg-rose-800',
|
||||
];
|
||||
|
||||
export function UserInfo({
|
||||
user,
|
||||
|
|
@ -12,16 +37,18 @@ export function UserInfo({
|
|||
showEmail?: boolean;
|
||||
hideNameOnMobile?: boolean;
|
||||
}) {
|
||||
const getInitials = useInitials();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Avatar className="h-8 w-8 overflow-hidden rounded-full">
|
||||
<AvatarImage src={user.avatar} alt={user.name} />
|
||||
<AvatarFallback className="rounded-lg bg-neutral-200 text-black dark:bg-neutral-700 dark:text-white">
|
||||
{getInitials(user.name)}
|
||||
</AvatarFallback>
|
||||
<Avatar>
|
||||
<Facehash
|
||||
name={user.name}
|
||||
size={32}
|
||||
colorClasses={tailwindColorClasses}
|
||||
intensity3d="dramatic"
|
||||
className="rounded-full"
|
||||
/>
|
||||
</Avatar>
|
||||
|
||||
<div
|
||||
className={cn([
|
||||
'grid flex-1 text-left text-sm leading-tight',
|
||||
|
|
|
|||
Loading…
Reference in New Issue