aura-glass
Version:
A comprehensive glassmorphism design system for React applications with 142+ production-ready components
130 lines (127 loc) • 5.87 kB
JavaScript
'use client';
import { jsx, jsxs } from 'react/jsx-runtime';
import React, { forwardRef, useState } from 'react';
import { cn } from '../../lib/utilsComprehensive.js';
import { GlassPopover } from '../modal/GlassPopover.js';
import { GlassAvatar } from '../data-display/GlassAvatar.js';
import { ChevronRight } from 'lucide-react';
import { useA11yId } from '../../utils/a11y.js';
import { useReducedMotion } from '../../hooks/useReducedMotion.js';
const HeaderUserMenu = /*#__PURE__*/forwardRef(({
user,
items,
respectMotionPreference = true,
className
}, ref) => {
// Accessibility and motion preferences
const menuId = useA11yId("user-menu");
const prefersReducedMotion = useReducedMotion();
const shouldReduceMotion = respectMotionPreference && prefersReducedMotion;
const [open, setOpen] = useState(false);
const statusColor = user.status === "online" ? "bg-green-500" : user.status === "away" ? "bg-yellow-500" : user.status === "busy" ? "bg-red-500" : "bg-gray-500";
return jsx(GlassPopover, {
open: open,
onOpenChange: setOpen,
trigger: "click",
placement: "bottom-end",
appearance: "glass",
contentClassName: "w-80 glass-p-1 ring-1 ring-white/10 shadow-[0_20px_60px_rgba(2,8,23,0.55)] rounded-2xl",
content: jsxs("div", {
className: 'w-80',
children: [jsx("div", {
className: 'glass-px-4 pt-4',
children: jsxs("div", {
className: 'glass-flex glass-items-center glass-gap-3 glass-px-3 glass-py-3 glass-gradient-primary glass-gradient-primary via-white/3 glass-gradient-primary glass-border glass-border-white/12 glass-shadow-[inset_0_1px_0_rgba(255,255,255,0.08)]',
style: {
borderRadius: 18
},
children: [jsx(GlassAvatar, {
size: "md",
src: user.avatar,
fallbackText: user.name,
showStatus: !!user.status,
status: user.status
}), jsxs("div", {
className: 'min-glass-w-0',
children: [jsx("div", {
className: 'font-semibold text-primary truncate',
children: user.name
}), user.email && jsx("div", {
className: 'glass-text-xs text-primary/80 truncate',
children: user.email
}), user.status && jsxs("div", {
className: "glass-flex glass-items-center glass-gap-1 glass-mt-1",
children: [jsx("span", {
className: cn("inline-block w-2 h-2 glass-radius-full", statusColor)
}), jsx("span", {
className: 'glass-text-xs text-primary/70 capitalize',
children: user.status
})]
})]
})]
})
}), jsx("div", {
className: "glass-p-2",
children: items.map((item, idx) => jsxs(React.Fragment, {
children: [item?.separator && idx > 0 && jsx("div", {
className: "glass-my-2 glass-border-t glass-border-white/10"
}), item?.href ? jsxs("a", {
href: item?.href,
className: cn("group w-full flex items-center justify-between glass-gap-3 rounded-[14px] glass-px-3 glass-py-2.5 transition-colors", "glass-text-primary/90 hover:glass-text-primary hover:bg-white/10", "glass-focus glass-touch-target glass-contrast-guard"),
onClick: e => setOpen(false),
children: [jsxs("span", {
className: 'glass-inline-flex glass-items-center glass-gap-3 truncate',
children: [item?.icon && jsx("span", {
className: 'text-primary/80',
children: item?.icon
}), jsx("span", {
className: 'truncate',
children: item?.label
})]
}), jsx(ChevronRight, {
className: 'w-4 h-4 text-primary/40 group-hover:text-primary/70'
})]
}) : jsxs("button", {
type: "button",
onClick: e => {
item?.onClick?.();
setOpen(false);
},
className: cn("w-full flex items-center justify-between glass-gap-3 rounded-[14px] glass-px-3 glass-py-2.5 transition-colors", "glass-focus glass-touch-target glass-contrast-guard", item?.variant === "danger" ? "text-red-300 hover:bg-red-500/10" : "glass-text-primary/90 hover:glass-text-primary hover:bg-white/10"),
children: [jsxs("span", {
className: 'glass-inline-flex glass-items-center glass-gap-3 truncate',
children: [item?.icon && jsx("span", {
className: cn(item?.variant === "danger" ? "text-red-400" : "glass-text-primary/80"),
children: item?.icon
}), jsx("span", {
className: 'truncate',
children: item?.label
})]
}), item?.variant !== "danger" && jsx(ChevronRight, {
className: 'w-4 h-4 text-primary/40 group-hover:text-primary/70'
})]
})]
}, item?.id))
})]
}),
children: jsx("button", {
ref: ref,
type: "button",
className: cn("flex items-center glass-gap-2 glass-px-1.5 glass-py-1 glass-radius-full", "bg-transparent text-foreground hover:bg-white/10 focus:outline-none focus:ring-2 focus:ring-white/30", "glass-focus glass-touch-target glass-contrast-guard", !shouldReduceMotion && "transition-all duration-200 hover:scale-105", className),
"aria-label": user.name,
"aria-haspopup": "menu",
"aria-expanded": open,
id: menuId,
children: jsx(GlassAvatar, {
size: "sm",
src: user.avatar,
fallbackText: user.name,
showStatus: !!user.status,
status: user.status
})
})
});
});
HeaderUserMenu.displayName = "HeaderUserMenu";
export { HeaderUserMenu };
//# sourceMappingURL=HeaderUserMenu.js.map