Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 26 additions & 4 deletions apps/dashboard/src/@/components/blocks/Img.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @next/next/no-img-element */
"use client";
import { useState } from "react";
import { useRef, useState } from "react";
import { useIsomorphicLayoutEffect } from "../../lib/useIsomorphicLayoutEffect";
import { cn } from "../../lib/utils";

type imgElementProps = React.DetailedHTMLProps<
Expand All @@ -25,19 +26,39 @@ export function Img(props: imgElementProps) {
const { className, fallback, skeleton, ...restProps } = props;
const defaultSkeleton = <div className="animate-pulse bg-accent" />;
const defaultFallback = <div className="bg-muted" />;
const imgRef = useRef<HTMLImageElement>(null);

useIsomorphicLayoutEffect(() => {
const imgEl = imgRef.current;
if (!imgEl) {
return;
}
if (imgEl.complete) {
setStatus("loaded");
} else {
function handleLoad() {
setStatus("loaded");
}
imgEl.addEventListener("load", handleLoad);
return () => {
imgEl.removeEventListener("load", handleLoad);
};
}
}, []);

return (
<div className="relative">
<img
{...restProps}
onLoad={() => {
setStatus("loaded");
}}
// avoid setting empty src string to prevent request to the entire page
src={restProps.src || undefined}
ref={imgRef}
onError={() => {
setStatus("fallback");
}}
style={{
opacity: status === "loaded" ? 1 : 0,
...restProps.style,
}}
alt={restProps.alt || ""}
className={cn(
Expand All @@ -48,6 +69,7 @@ export function Img(props: imgElementProps) {

{status !== "loaded" && (
<div
style={restProps.style}
className={cn(
"fade-in-0 absolute inset-0 overflow-hidden transition-opacity duration-300 [&>*]:h-full [&>*]:w-full",
className,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const PublisherHeader: React.FC<PublisherHeaderProps> = ({
>
<PublisherAvatar
alt="Publisher avatar"
boxSize={14}
className="size-14"
address={ensQuery.data?.ensName || wallet}
/>
</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const ContractPublisher: React.FC<ContractPublisherProps> = async ({
>
<PublisherAvatar
isPending={false}
boxSize={5}
className="size-5"
address={addressOrEns || ""}
/>

Expand Down
5 changes: 2 additions & 3 deletions apps/dashboard/src/components/hackathon/Judges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const Judges = ({ TRACKING_CATEGORY }: JudgesProps) => {
];

return (
<div className="relative flex flex-col gap-8">
<div className="container relative flex max-w-[1200px] flex-col gap-8">
<Heading size="title.2xl">Judges</Heading>
<SimpleGrid
columns={{ base: 1, lg: 4 }}
Expand All @@ -46,10 +46,9 @@ export const Judges = ({ TRACKING_CATEGORY }: JudgesProps) => {
{judges.map((judge) => (
<Flex key={judge.name} flexDir="column" gap={2} alignItems="center">
<MaskedAvatar
boxSize={40}
src={judge.image}
alt={judge.name}
className="rounded-full"
className="size-52"
/>
<Heading size="title.sm" mt={4} textAlign="center">
{judge.name}
Expand Down
5 changes: 2 additions & 3 deletions apps/dashboard/src/components/hackathon/JudgesEarn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const JudgesEarn = () => {
];

return (
<div className="relative flex flex-col gap-8">
<div className="container relative flex max-w-[1200px] flex-col gap-8">
<Heading size="title.2xl">Judges</Heading>
<SimpleGrid
columns={{ base: 1, lg: 4 }}
Expand All @@ -38,10 +38,9 @@ export const JudgesEarn = () => {
{judges.map((judge) => (
<Flex key={judge.name} flexDir="column" gap={2} alignItems="center">
<MaskedAvatar
boxSize={40}
src={judge.image}
alt={judge.name}
className="rounded-full"
className="size-52"
/>
<Heading size="title.sm" mt={4} textAlign="center">
{judge.name}
Expand Down
4 changes: 2 additions & 2 deletions apps/dashboard/src/pages/community/ambassadors.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ const Ambassadors: ThirdwebNextPage = () => {
<MaskedAvatar
src={ambassador.profileImage}
alt={ambassador.name}
boxSize={20}
className="size-20"
/>
<Heading size="title.sm">{ambassador.name}</Heading>
</Flex>
Expand All @@ -619,7 +619,7 @@ const Ambassadors: ThirdwebNextPage = () => {
>
<Flex flexDir="column" gap={0}>
<Heading as="h2" size="display.md" mb={4} textAlign="center">
Ready to
Ready to{" "}
<Heading
size="display.md"
as="span"
Expand Down
2 changes: 1 addition & 1 deletion apps/dashboard/src/pages/profile/[profileAddress].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const UserPage: ThirdwebNextPage = (props: UserPageProps) => {
<Flex gap={{ base: 4, md: 8 }} align="center" w="full">
<PublisherAvatar
address={ens.data?.ensName || props.profileAddress}
boxSize={30}
className="size-30"
/>
<Flex direction="column" gap={0}>
<Heading
Expand Down
16 changes: 5 additions & 11 deletions apps/dashboard/src/tw-components/masked-avatar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,30 @@
import { SkeletonContainer } from "@/components/ui/skeleton";
import { Img } from "@/components/blocks/Img";
import { cn } from "@/lib/utils";
import hexagon from "./hexagon.png";

export interface MaskedAvatarProps {
src: string;
isPending?: boolean;
alt?: string;
boxSize?: number;
className?: string;
}

export const MaskedAvatar: React.FC<MaskedAvatarProps> = ({
src,
alt,
boxSize = 12,
className,
}) => {
return (
<SkeletonContainer
className={cn(className, `size-${boxSize}`)}
<Img
className={cn("size-12 object-cover", className)}
src={src}
alt={alt}
style={{
WebkitMaskImage: `url("${hexagon.src}")`,
WebkitMaskSize: "cover",
mask: `url("${hexagon.src}")`,
maskSize: "cover",
}}
skeletonData={undefined}
loadedData={src}
render={(v) => (
// eslint-disable-next-line @next/next/no-img-element
<img className="object-cover" src={v} alt={alt || ""} />
)}
/>
);
};
Loading