BadgeContainer on user page initial
@@ -8,6 +8,8 @@ interface SocialLinkProps {
|
||||
type: "youtube" | "twitter" | "twitch";
|
||||
identifier: string;
|
||||
}
|
||||
|
||||
// xxx: move to route file
|
||||
export function SocialLink({
|
||||
type,
|
||||
identifier,
|
||||
|
||||
@@ -5,6 +5,9 @@ import { Avatar } from "~/components/Avatar";
|
||||
import { SocialLink } from "~/components/u/SocialLink";
|
||||
import styles from "~/styles/u.css";
|
||||
import type { UserPageLoaderData } from "../u.$identifier";
|
||||
import * as React from "react";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import clsx from "clsx";
|
||||
|
||||
export const links: LinksFunction = () => {
|
||||
return [{ rel: "stylesheet", href: styles }];
|
||||
@@ -46,7 +49,66 @@ export default function UserInfoPage() {
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
<BadgeContainer badges={data.badges} />
|
||||
{data.bio ? <article className="u__bio">{data.bio}</article> : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function BadgeContainer(props: { badges: UserPageLoaderData["badges"] }) {
|
||||
const [badges, setBadges] = React.useState(props.badges);
|
||||
const [bigBadge, ...smallBadges] = badges;
|
||||
if (!bigBadge) return null;
|
||||
|
||||
const setBadgeFirst = (badge: Unpacked<UserPageLoaderData["badges"]>) => {
|
||||
setBadges(
|
||||
badges.map((b, i) => {
|
||||
if (i === 0) return badge;
|
||||
if (b.code === badge.code) return badges[0]!;
|
||||
|
||||
return b;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={clsx("u__badges", {
|
||||
"justify-center": smallBadges.length === 0,
|
||||
})}
|
||||
>
|
||||
<img
|
||||
key={bigBadge.code}
|
||||
src={`/gif/badges/${bigBadge.code}.gif`}
|
||||
alt={bigBadge.displayName}
|
||||
title={bigBadge.displayName}
|
||||
width="125"
|
||||
height="125"
|
||||
/>
|
||||
{smallBadges.length > 0 ? (
|
||||
<div className="u__small-badges">
|
||||
{smallBadges.map((badge) => (
|
||||
<img
|
||||
key={badge.code}
|
||||
src={`/gif/badges/${badge.code}.gif`}
|
||||
alt={badge.displayName}
|
||||
title={badge.displayName}
|
||||
onClick={() => setBadgeFirst(badge)}
|
||||
width="48"
|
||||
height="48"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="u__badge-explanation">
|
||||
{badgeExplanationText(bigBadge)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function badgeExplanationText(badge: Unpacked<UserPageLoaderData["badges"]>) {
|
||||
return `Awarded for winning ${badge.displayName}`;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
--bg-lighter-transparent: hsla(237.3deg 42.3% 35.6% / 50%);
|
||||
--bg-darker-very-transparent: hsla(237.3deg 42.3% 26.6% / 50%);
|
||||
--bg-darker-transparent: hsla(237.3deg 42.3% 26.6% / 90%);
|
||||
--bg-badge: #000;
|
||||
--border: hsl(237.3deg 42.3% 45.6%);
|
||||
--button-text: rgb(0 0 0 / 85%);
|
||||
--button-text-transparent: rgb(0 0 0 / 65%);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.u__container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--s-8);
|
||||
gap: var(--s-6);
|
||||
}
|
||||
|
||||
.u__avatar-container {
|
||||
@@ -88,3 +88,27 @@
|
||||
.u__bio {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.u__badges {
|
||||
display: flex;
|
||||
max-width: 24rem;
|
||||
padding: var(--s-2);
|
||||
background-color: var(--bg-badge);
|
||||
border-radius: var(--rounded);
|
||||
margin-inline: auto;
|
||||
}
|
||||
|
||||
.u__small-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
gap: var(--s-1);
|
||||
}
|
||||
|
||||
.u__badge-explanation {
|
||||
color: var(--text-lighter);
|
||||
font-size: var(--fonts-xs);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
BIN
public/gif/badges/lutiblue.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutigreen.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutilimegreen.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutiorange.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutipink.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutipurple.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutired.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutitan.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutitan2.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |
BIN
public/gif/badges/lutiyellow.gif
Normal file
|
After Width: | Height: | Size: 121 KiB |