mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-08-07 21:56:33 -05:00
54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
import clsx from "clsx";
|
|
import type * as React from "react";
|
|
import { Link } from "react-router";
|
|
import type { Tables } from "~/db/tables";
|
|
import { userPage } from "~/utils/urls";
|
|
import { Avatar } from "./Avatar";
|
|
import styles from "./UserLink.module.css";
|
|
|
|
type UserLinkUser = Pick<
|
|
Tables["User"],
|
|
"username" | "discordId" | "discordAvatar"
|
|
> & {
|
|
customUrl?: Tables["User"]["customUrl"];
|
|
customAvatarUrl?: string | null;
|
|
};
|
|
|
|
type UnlinkedPlayer = { name: string | null } & {
|
|
[K in keyof UserLinkUser]: UserLinkUser[K] | null;
|
|
};
|
|
|
|
/** Link to a user's page showing their avatar and username. Accepts also result players without an account, rendering just their name. */
|
|
export function UserLink({
|
|
user,
|
|
size = "xxs",
|
|
direction = "horizontal",
|
|
className,
|
|
children,
|
|
}: {
|
|
user: UserLinkUser | UnlinkedPlayer;
|
|
size?: React.ComponentProps<typeof Avatar>["size"];
|
|
direction?: "horizontal" | "vertical";
|
|
className?: string;
|
|
/** Replaces the plain username text (avatar is always rendered) */
|
|
children?: React.ReactNode;
|
|
}) {
|
|
if (user.username === null) {
|
|
return <>{(user as UnlinkedPlayer).name}</>;
|
|
}
|
|
|
|
const linkedUser = user as UserLinkUser;
|
|
|
|
return (
|
|
<Link
|
|
to={userPage(linkedUser)}
|
|
className={clsx(styles.userLink, className, {
|
|
[styles.vertical]: direction === "vertical",
|
|
})}
|
|
>
|
|
<Avatar user={linkedUser} size={size} />
|
|
{children ?? linkedUser.username}
|
|
</Link>
|
|
);
|
|
}
|