Files
zeekayandHanzo Dev c37dbf30a6 Merge origin/main into converge/ui-8046
`TeamMemberCard` was rewritten on both sides — de-Radix here, and upstream
stopped fabricating social URLs from a person's name. Both survive: the card
keeps the `hz-*` vocabulary and `cn` from `@hanzo/ui`, and takes upstream's
`linkedin`/`x` props, rendering each icon only when a real handle is passed.
The slugified `linkedin.com/in/<name>` and `x.com/<name>` links are gone, which
was the point of that commit; no member data carries a handle yet, so the human
cards now show GitHub alone — upstream's intent, not a styling regression.

Upstream's version still carried a required `gradient` prop feeding
`bg-gradient-to-br`. It stays dropped: this brand is monochrome, and the prop
had no caller left.

Dockerfile: the export is flat because `next.config.mjs` says so — the file was
renamed from `.ts` on this branch, and the comment named the old one.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-04 18:28:26 -07:00

158 lines
4.3 KiB
TypeScript

"use client";
import { LucideIcon } from "lucide-react";
import { motion } from "framer-motion";
import { Github, Linkedin, Twitter, MessageSquare, Rocket } from "lucide-react";
import { cn } from '@hanzo/ui'
interface TeamMemberCardProps {
name: string;
role: string;
description: string;
icon: LucideIcon;
image?: string;
link?: string;
emoji?: string;
botId?: string;
// Real handles only — never derive a social URL from a person's name.
linkedin?: string;
x?: string;
}
export default function TeamMemberCard({ name, role, description, icon: Icon, image, link, emoji, botId, linkedin, x }: TeamMemberCardProps) {
const isHuman = !!image;
return (
<motion.div
whileHover={{ y: -5 }}
className={cn(
"hz-rel hz-r-xl hz-bordered hz-p-6 hz-glass hz-clip",
"hz-bg-surface"
)}
>
<div className="hz-abs hz-inset hz-invisible hz-transition hz-z-behind" />
<div className="hz-mb-4 hz-rel hz-z-raised">
{image ? (
<div className={cn(
"hz-sq-8 hz-r-full hz-clip hz-ring hz-mb-4",
"hz-bg-surface"
)}>
<img
src={image}
alt={name}
className="hz-w-full hz-h-full hz-object-cover"
/>
</div>
) : emoji ? (
<div className="hz-mb-4 hz-t-5xl hz-leading-none">
{emoji}
</div>
) : (
<div className="hz-inline hz-p-3 hz-r-lg hz-mb-4 hz-bg-surface">
<Icon className="hz-sq-4 hz-fg" />
</div>
)}
<h3 className={cn(
"hz-t-xl hz-w-semibold hz-mb-2 hz-transition",
"hz-fg"
)}>
{name}
</h3>
<p className={cn(
"hz-w-medium hz-mb-3 hz-t-sm",
"hz-fg"
)}>
{role}
</p>
<p className={cn(
"hz-mb-4 hz-t-sm",
"hz-fg"
)}>
{description}
</p>
</div>
{isHuman ? (
<div className="hz-row hz-ai-center hz-gap-3 hz-rel hz-z-raised">
{linkedin && (
<a
href={linkedin}
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
>
<Linkedin className="hz-sq-2" />
</a>
)}
{x && (
<a
href={x}
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
>
<Twitter className="hz-sq-2" />
</a>
)}
<a
href="https://github.com/hanzoai"
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
>
<Github className="hz-sq-2" />
</a>
</div>
) : (
<div className="hz-row hz-ai-center hz-gap-3 hz-rel hz-z-raised">
<a
href={botId ? `https://app.hanzo.bot/${botId}` : "https://app.hanzo.bot"}
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
title="Launch"
>
<Rocket className="hz-sq-2" />
</a>
<a
href="https://hanzo.chat"
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
title="Chat"
>
<MessageSquare className="hz-sq-2" />
</a>
<a
href="https://github.com/hanzoai/bot"
target="_blank"
rel="noopener noreferrer"
className={cn(
"hz-p-2 hz-r-lg hz-bordered hz-transition",
"hz-fg hz-hoverable"
)}
title="GitHub"
>
<Github className="hz-sq-2" />
</a>
</div>
)}
</motion.div>
);
}