registry:component
Profile Dropdown
v0.1.0alpha
Avatar button with profile, settings, and sign-out menu. Manages its own Supabase auth state.
Registry Endpoint
Open JSONhttps://registry.aavya.com/r/profile-dropdown.json
npx shadcn@latest add https://registry.aavya.com/r/profile-dropdown.json
Live Preview
Dependencies
avatarbuttondropdown-menu
Usage Snippet
import ProfileDropdown from '@/components/blocks/profile-dropdown.tsx'
export default function Example() {
return (
<div className="p-6">
<ProfileDropdown />
</div>
)
}
Source Preview
'use client'
import type { ReactNode } from 'react'
import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import {
BarChart3Icon,
DownloadIcon,
LogInIcon,
LogOutIcon,
SettingsIcon,
UserIcon,
UsersIcon,
WandSparklesIcon,
} from 'lucide-react'
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import { createClient } from '@/lib/supabase/client'
const supabaseEnabled =
process.env.NEXT_PUBLIC_AUTH_DISABLED !== 'true' &&
Boolean(process.env.NEXT_PUBLIC_SUPABASE_URL) &&
Boolean(process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY)
function hasAdminAccess(user: {
app_metadata?: Record<string, unknown>
user_metadata?: Record<string, unknown>
}): boolean {
const roleCandidates = [
user.app_metadata?.role,
user.user_metadata?.role,
user.app_metadata?.roles,
user.user_metadata?.roles,
]
return roleCandidates.some((candidate) => {
if (typeof candidate === 'string') return candidate.toLowerCase() === 'admin'
if (Array.isArray(candidate)) {
return candidate.some((r) => typeof r === 'string' && r.toLowerCase()