mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Add a reusable decorateAdminAvatar(avatarEl, id) that applies BOTH the gold ring (box-shadow, not clipped by the avatar's overflow) and the corner star (hung off a non-clipped .admin-avatar-wrap it ensures around the avatar). Idempotent; works on attached or freshly-built detached avatars. Wired onto: - profile modal "Acting as" identity pill - account-switcher saved-profile avatars - video card creator avatars - video player creator avatar - DM conversation list + message bubbles (upgraded from star-only to ring+star) adminBadge.js: split the star decision from its DOM (setAdminStar) so the ring and star share one isAdminActor check; added ADMIN_RING_CLASS / ADMIN_WRAP_CLASS. tests: decorateAdminAvatar (wrap/ring/star, idempotency, non-admin, detached). Co-Authored-By: Claude Opus 4.8 <[email protected]>
67 lines
1.7 KiB
JavaScript
67 lines
1.7 KiB
JavaScript
import { decorateAdminAvatar, isAdminActor } from "../adminBadge.js";
|
|
|
|
const DEFAULT_AVATAR_ALT = "Avatar";
|
|
|
|
function getInitials(label = "") {
|
|
if (typeof label !== "string") {
|
|
return "";
|
|
}
|
|
const words = label.trim().split(/\s+/).filter(Boolean);
|
|
if (!words.length) {
|
|
return "";
|
|
}
|
|
const initials = words.slice(0, 2).map((word) => word[0].toUpperCase());
|
|
return initials.join("");
|
|
}
|
|
|
|
export function Avatar({
|
|
document: doc,
|
|
src = "",
|
|
alt = DEFAULT_AVATAR_ALT,
|
|
size = "md",
|
|
initials = "",
|
|
status = "",
|
|
adminId = "",
|
|
} = {}) {
|
|
if (!doc) {
|
|
throw new Error("Avatar requires a document reference.");
|
|
}
|
|
|
|
const avatar = doc.createElement("div");
|
|
// Explicit mapping ensures Tailwind scanner detects these classes
|
|
const sizeClass = {
|
|
sm: "dm-avatar--sm",
|
|
md: "dm-avatar--md",
|
|
}[size] || `dm-avatar--${size}`;
|
|
|
|
avatar.className = `dm-avatar ${sizeClass}`;
|
|
if (status) {
|
|
avatar.dataset.status = status;
|
|
}
|
|
|
|
const resolvedInitials = initials || getInitials(alt);
|
|
|
|
if (src) {
|
|
const img = doc.createElement("img");
|
|
img.className = "dm-avatar__image";
|
|
img.alt = alt || DEFAULT_AVATAR_ALT;
|
|
img.loading = "lazy";
|
|
img.decoding = "async";
|
|
img.src = src;
|
|
avatar.appendChild(img);
|
|
} else {
|
|
const fallback = doc.createElement("span");
|
|
fallback.className = "dm-avatar__fallback";
|
|
fallback.textContent = resolvedInitials || "?";
|
|
avatar.appendChild(fallback);
|
|
}
|
|
|
|
// Only admin avatars get decorated (ring + wrapped corner star); non-admin
|
|
// avatars are returned exactly as before to keep existing layouts untouched.
|
|
if (adminId && isAdminActor(adminId)) {
|
|
return decorateAdminAvatar(avatar, adminId, { doc });
|
|
}
|
|
|
|
return avatar;
|
|
}
|