[CAL-811] Avatar icon not redirecting user back to the main page (#6586)
* Remove cursor-pointer, remove old Avatar* files * Fixed styling for checkedSelect + some cleanup Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com> Co-authored-by: Alex van Andel <me@alexvanandel.com>
This commit is contained in:
parent
0bb0883e64
commit
7ce83542e2
|
@ -36,7 +36,7 @@ export const UserAvatars = ({
|
||||||
href?: string;
|
href?: string;
|
||||||
}[]
|
}[]
|
||||||
}
|
}
|
||||||
size="sm"
|
size={users.length <= 1 ? "lg" : "sm"}
|
||||||
truncateAfter={props.truncateAfter}
|
truncateAfter={props.truncateAfter}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
|
||||||
|
|
||||||
import { Maybe } from "@calcom/trpc/server";
|
|
||||||
|
|
||||||
import classNames from "@lib/classNames";
|
|
||||||
import { defaultAvatarSrc } from "@lib/profile";
|
|
||||||
|
|
||||||
export type AvatarProps = {
|
|
||||||
className?: string;
|
|
||||||
size?: number;
|
|
||||||
imageSrc?: Maybe<string>;
|
|
||||||
title?: string;
|
|
||||||
alt: string;
|
|
||||||
gravatarFallbackMd5?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated Use AvatarSSR instead. Once, there is no usage of Avatar, AvatarSSR can be renamed.
|
|
||||||
*/
|
|
||||||
export default function Avatar(props: AvatarProps) {
|
|
||||||
const { imageSrc, gravatarFallbackMd5, size, alt, title } = props;
|
|
||||||
const className = classNames("rounded-full", props.className, size && `h-${size} w-${size}`);
|
|
||||||
const avatar = (
|
|
||||||
<AvatarPrimitive.Root>
|
|
||||||
<AvatarPrimitive.Image
|
|
||||||
src={imageSrc ?? undefined}
|
|
||||||
alt={alt}
|
|
||||||
className={classNames("rounded-full", `h-auto w-${size}`, props.className)}
|
|
||||||
/>
|
|
||||||
<AvatarPrimitive.Fallback delayMs={600}>
|
|
||||||
{gravatarFallbackMd5 && (
|
|
||||||
// eslint-disable-next-line @next/next/no-img-element
|
|
||||||
<img src={defaultAvatarSrc({ md5: gravatarFallbackMd5 })} alt={alt} className={className} />
|
|
||||||
)}
|
|
||||||
</AvatarPrimitive.Fallback>
|
|
||||||
</AvatarPrimitive.Root>
|
|
||||||
);
|
|
||||||
|
|
||||||
return title ? (
|
|
||||||
<Tooltip.Tooltip delayDuration={300}>
|
|
||||||
<Tooltip.TooltipTrigger className="cursor-default">{avatar}</Tooltip.TooltipTrigger>
|
|
||||||
<Tooltip.Content className="rounded-sm bg-black p-2 text-sm text-white">
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
{title}
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Tooltip>
|
|
||||||
) : (
|
|
||||||
<>{avatar}</>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
import Link from "next/link";
|
|
||||||
import React from "react";
|
|
||||||
|
|
||||||
import classNames from "@lib/classNames";
|
|
||||||
|
|
||||||
import { AvatarSSR } from "@components/ui/AvatarSSR";
|
|
||||||
|
|
||||||
export type AvatarGroupProps = {
|
|
||||||
border?: string; // this needs to be the color of the parent container background, i.e.: border-white dark:border-gray-900
|
|
||||||
size: number;
|
|
||||||
truncateAfter?: number;
|
|
||||||
items: {
|
|
||||||
image: string;
|
|
||||||
title?: string;
|
|
||||||
alt?: string;
|
|
||||||
href?: string;
|
|
||||||
}[];
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AvatarGroup = function AvatarGroup(props: AvatarGroupProps) {
|
|
||||||
return (
|
|
||||||
<ul className={classNames(props.className)}>
|
|
||||||
{props.items.slice(0, props.truncateAfter).map((item, idx) => {
|
|
||||||
if (item.image != null) {
|
|
||||||
const avatar = (
|
|
||||||
<AvatarSSR
|
|
||||||
className={props.border}
|
|
||||||
imageSrc={item.image}
|
|
||||||
title={item.title}
|
|
||||||
alt={item.alt || ""}
|
|
||||||
size={props.size}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<li key={idx} className="-ltr:mr-2 inline-block rtl:ml-2">
|
|
||||||
{item.href ? <Link href={item.href}>{avatar}</Link> : avatar}
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default AvatarGroup;
|
|
|
@ -1,62 +0,0 @@
|
||||||
import { User } from "@prisma/client";
|
|
||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
|
||||||
|
|
||||||
import classNames from "@lib/classNames";
|
|
||||||
|
|
||||||
export type AvatarProps = (
|
|
||||||
| {
|
|
||||||
user: Pick<User, "name" | "username" | "avatar"> & { emailMd5?: string };
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
user?: null;
|
|
||||||
imageSrc: string;
|
|
||||||
}
|
|
||||||
) & {
|
|
||||||
className?: string;
|
|
||||||
size?: number;
|
|
||||||
title?: string;
|
|
||||||
href?: string;
|
|
||||||
alt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
// defaultAvatarSrc from profile.tsx can't be used as it imports crypto
|
|
||||||
function defaultAvatarSrc(md5: string) {
|
|
||||||
return `https://www.gravatar.com/avatar/${md5}?s=160&d=mp&r=PG`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An SSR Supported version of Avatar component.
|
|
||||||
export function AvatarSSR(props: AvatarProps) {
|
|
||||||
const { size, title } = props;
|
|
||||||
|
|
||||||
let imgSrc = "";
|
|
||||||
let alt: string = props.alt;
|
|
||||||
|
|
||||||
if (props.user) {
|
|
||||||
const user = props.user;
|
|
||||||
const nameOrUsername = user.name || user.username || "";
|
|
||||||
alt = alt || nameOrUsername;
|
|
||||||
|
|
||||||
if (user.avatar) {
|
|
||||||
imgSrc = user.avatar;
|
|
||||||
} else if (user.emailMd5) {
|
|
||||||
imgSrc = defaultAvatarSrc(user.emailMd5);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
imgSrc = props.imageSrc;
|
|
||||||
}
|
|
||||||
|
|
||||||
const className = classNames("rounded-full", props.className, size && `h-${size} w-${size}`);
|
|
||||||
|
|
||||||
const avatar = imgSrc ? <img alt={alt} className={className} src={imgSrc} /> : null;
|
|
||||||
return title ? (
|
|
||||||
<Tooltip.Tooltip delayDuration={300}>
|
|
||||||
<Tooltip.TooltipTrigger asChild>{avatar}</Tooltip.TooltipTrigger>
|
|
||||||
<Tooltip.Content className="rounded-sm bg-black p-2 text-sm text-white">
|
|
||||||
<Tooltip.Arrow />
|
|
||||||
{title}
|
|
||||||
</Tooltip.Content>
|
|
||||||
</Tooltip.Tooltip>
|
|
||||||
) : (
|
|
||||||
<>{avatar}</>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -2,9 +2,8 @@ import React from "react";
|
||||||
import { Props } from "react-select";
|
import { Props } from "react-select";
|
||||||
|
|
||||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||||
import { Icon } from "@calcom/ui";
|
import { Icon, Avatar } from "@calcom/ui";
|
||||||
|
|
||||||
import Avatar from "@components/ui/Avatar";
|
|
||||||
import Select from "@components/ui/form/Select";
|
import Select from "@components/ui/form/Select";
|
||||||
|
|
||||||
type CheckedSelectOption = {
|
type CheckedSelectOption = {
|
||||||
|
@ -43,7 +42,8 @@ export const CheckedSelect = ({
|
||||||
{value.map((option) => (
|
{value.map((option) => (
|
||||||
<div key={option.value} className="border p-2 font-medium">
|
<div key={option.value} className="border p-2 font-medium">
|
||||||
<Avatar
|
<Avatar
|
||||||
className="inline h-6 w-6 rounded-full ltr:mr-2 rtl:ml-2"
|
className="inline ltr:mr-2 rtl:ml-2"
|
||||||
|
size="sm"
|
||||||
imageSrc={option.avatar}
|
imageSrc={option.avatar}
|
||||||
alt={option.label}
|
alt={option.label}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -26,13 +26,11 @@ import { collectPageParameters, telemetryEventTypes, useTelemetry } from "@calco
|
||||||
import prisma from "@calcom/prisma";
|
import prisma from "@calcom/prisma";
|
||||||
import { baseEventTypeSelect } from "@calcom/prisma/selects";
|
import { baseEventTypeSelect } from "@calcom/prisma/selects";
|
||||||
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
import { EventTypeMetaDataSchema } from "@calcom/prisma/zod-utils";
|
||||||
import { Icon, HeadSeo, AvatarGroup } from "@calcom/ui";
|
import { Icon, HeadSeo, AvatarGroup, Avatar } from "@calcom/ui";
|
||||||
|
|
||||||
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
import { inferSSRProps } from "@lib/types/inferSSRProps";
|
||||||
import { EmbedProps } from "@lib/withEmbedSsr";
|
import { EmbedProps } from "@lib/withEmbedSsr";
|
||||||
|
|
||||||
import { AvatarSSR } from "@components/ui/AvatarSSR";
|
|
||||||
|
|
||||||
import { ssrInit } from "@server/lib/ssr";
|
import { ssrInit } from "@server/lib/ssr";
|
||||||
|
|
||||||
export default function User(props: inferSSRProps<typeof getServerSideProps> & EmbedProps) {
|
export default function User(props: inferSSRProps<typeof getServerSideProps> & EmbedProps) {
|
||||||
|
@ -132,7 +130,7 @@ export default function User(props: inferSSRProps<typeof getServerSideProps> & E
|
||||||
)}>
|
)}>
|
||||||
{isSingleUser && ( // When we deal with a single user, not dynamic group
|
{isSingleUser && ( // When we deal with a single user, not dynamic group
|
||||||
<div className="mb-8 text-center">
|
<div className="mb-8 text-center">
|
||||||
<AvatarSSR user={user} className="mx-auto mb-4 h-24 w-24" alt={nameOrUsername} />
|
<Avatar imageSrc={user.avatar} size="xl" alt={nameOrUsername} />
|
||||||
<h1 className="font-cal mb-1 text-3xl text-gray-900 dark:text-white">
|
<h1 className="font-cal mb-1 text-3xl text-gray-900 dark:text-white">
|
||||||
{nameOrUsername}
|
{nameOrUsername}
|
||||||
{user.verified && (
|
{user.verified && (
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
||||||
import * as Tooltip from "@radix-ui/react-tooltip";
|
import * as Tooltip from "@radix-ui/react-tooltip";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
import classNames from "@calcom/lib/classNames";
|
import classNames from "@calcom/lib/classNames";
|
||||||
import { defaultAvatarSrc } from "@calcom/lib/defaultAvatarImage";
|
import { defaultAvatarSrc } from "@calcom/lib/defaultAvatarImage";
|
||||||
|
@ -9,10 +10,11 @@ import { Maybe } from "@trpc/server";
|
||||||
|
|
||||||
export type AvatarProps = {
|
export type AvatarProps = {
|
||||||
className?: string;
|
className?: string;
|
||||||
size: "xs" | "sm" | "md" | "mdLg" | "lg";
|
size: "xs" | "sm" | "md" | "mdLg" | "lg" | "xl";
|
||||||
imageSrc?: Maybe<string>;
|
imageSrc?: Maybe<string>;
|
||||||
title?: string;
|
title?: string;
|
||||||
alt: string;
|
alt: string;
|
||||||
|
href?: string;
|
||||||
gravatarFallbackMd5?: string;
|
gravatarFallbackMd5?: string;
|
||||||
fallback?: React.ReactNode;
|
fallback?: React.ReactNode;
|
||||||
accepted?: boolean;
|
accepted?: boolean;
|
||||||
|
@ -25,20 +27,24 @@ const sizesPropsBySize = {
|
||||||
md: "w-8 h-8", // 32px
|
md: "w-8 h-8", // 32px
|
||||||
mdLg: "w-10 h-10", //40px
|
mdLg: "w-10 h-10", //40px
|
||||||
lg: "w-16 h-16", // 64px
|
lg: "w-16 h-16", // 64px
|
||||||
|
xl: "w-24 h-24", // 96px
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export function Avatar(props: AvatarProps) {
|
export function Avatar(props: AvatarProps) {
|
||||||
const { imageSrc, gravatarFallbackMd5, size, alt, title } = props;
|
const { imageSrc, gravatarFallbackMd5, size, alt, title, href } = props;
|
||||||
const sizeClassname = sizesPropsBySize[size];
|
const rootClass = classNames("aspect-square rounded-full", sizesPropsBySize[size]);
|
||||||
const rootClass = classNames("rounded-full aspect-square ", sizeClassname);
|
let avatar = (
|
||||||
const avatar = (
|
|
||||||
<AvatarPrimitive.Root
|
<AvatarPrimitive.Root
|
||||||
className={classNames(
|
className={classNames(
|
||||||
sizeClassname,
|
"dark:bg-darkgray-300 item-center relative inline-flex aspect-square justify-center overflow-hidden rounded-full",
|
||||||
"dark:bg-darkgray-300 item-center relative inline-flex aspect-square justify-center overflow-hidden rounded-full"
|
props.className
|
||||||
)}>
|
)}>
|
||||||
<>
|
<>
|
||||||
<AvatarPrimitive.Image src={imageSrc ?? undefined} alt={alt} className={rootClass} />
|
<AvatarPrimitive.Image
|
||||||
|
src={imageSrc ?? undefined}
|
||||||
|
alt={alt}
|
||||||
|
className={classNames("aspect-square rounded-full", sizesPropsBySize[size])}
|
||||||
|
/>
|
||||||
<AvatarPrimitive.Fallback delayMs={600} asChild={props.asChild}>
|
<AvatarPrimitive.Fallback delayMs={600} asChild={props.asChild}>
|
||||||
<>
|
<>
|
||||||
{props.fallback && !gravatarFallbackMd5 && props.fallback}
|
{props.fallback && !gravatarFallbackMd5 && props.fallback}
|
||||||
|
@ -62,6 +68,10 @@ export function Avatar(props: AvatarProps) {
|
||||||
</AvatarPrimitive.Root>
|
</AvatarPrimitive.Root>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (href) {
|
||||||
|
avatar = <Link href={href}>{avatar}</Link>;
|
||||||
|
}
|
||||||
|
|
||||||
return title ? (
|
return title ? (
|
||||||
<Tooltip.Provider>
|
<Tooltip.Provider>
|
||||||
<Tooltip.Tooltip delayDuration={300}>
|
<Tooltip.Tooltip delayDuration={300}>
|
||||||
|
|
|
@ -8,6 +8,7 @@ export type AvatarGroupProps = {
|
||||||
image: string;
|
image: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
alt?: string;
|
alt?: string;
|
||||||
|
href?: string;
|
||||||
}[];
|
}[];
|
||||||
className?: string;
|
className?: string;
|
||||||
accepted?: boolean;
|
accepted?: boolean;
|
||||||
|
@ -51,6 +52,7 @@ export const AvatarGroup = function AvatarGroup(props: AvatarGroupProps) {
|
||||||
alt={item.alt || ""}
|
alt={item.alt || ""}
|
||||||
accepted={props.accepted}
|
accepted={props.accepted}
|
||||||
size={props.size}
|
size={props.size}
|
||||||
|
href={item.href}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user