Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | 11x 11x 609x 609x 609x 609x 609x 609x | import { Stack } from "@mui/material";
import { addSizeToImage } from "@components/UploadAvatar/UploadAvatar";
import GiveTruncateText from "@shared/Text/GiveTruncateText";
import GiveAvatar from "@shared/Avatar/GiveAvatar";
/**
* The two pairings the designs use. `md` is the table row (Settings → Team, the
* event Host tab); `sm` is the Assign Host modal's 54px row, whose 24px avatar
* comes with a wider gutter (frame 8181-61190). Paired rather than exposed as
* two props because the two values move together in the mockups.
*/
const SIZES = {
md: { avatar: "32px", gap: "8px" },
sm: { avatar: "24px", gap: "12px" },
} as const;
type GiveMemberNameCellProps = {
imageURL?: string;
firstName: string;
lastName?: string;
email: string;
size?: keyof typeof SIZES;
/**
* Lead with the email when the member has no name on file, and drop the
* second line rather than repeating it. Off by default: a table row wants the
* blank name line so the email stays in its own column position, while a
* standalone row (the Assign Host modal) wants the collapse.
*/
fallbackToEmail?: boolean;
};
/**
* One member's identity: avatar, name, email.
*
* Shared by the Team table, the event Host tab and the Assign Host modal — the
* three drew the same person from three copies of this markup before, which is
* how they drift.
*/
export const GiveMemberNameCell = ({
imageURL,
firstName,
lastName,
email,
size = "md",
fallbackToEmail = false,
}: GiveMemberNameCellProps) => {
const image = imageURL ? addSizeToImage(imageURL, "small") : undefined;
const { avatar, gap } = SIZES[size];
const name = [firstName, lastName].filter(Boolean).join(" ").trim();
const leadWithEmail = fallbackToEmail && !name;
// The default keeps the literal two-slot template rather than the joined
// name: a member with no name on file renders a whitespace-only line, and
// that line is what holds a table row at its full height.
const nameLine = fallbackToEmail ? name : `${firstName} ${lastName ?? ""}`;
return (
<Stack direction="row" alignItems="center" gap={gap} flex={1} minWidth={0}>
<GiveAvatar size={avatar} imageUrl={image} shape="rounded" />
{/* minWidth:0 is what lets the two texts truncate instead of pushing a
sibling control off the row's right edge. */}
<Stack minWidth={0} flex={1}>
<GiveTruncateText lineClamp={1} variant="bodyS">
{leadWithEmail ? email : nameLine}
</GiveTruncateText>
{!leadWithEmail && (
<GiveTruncateText
sx={{ wordBreak: "break-all" }}
color="secondary"
variant="bodyXS"
lineClamp={1}
>
{email}
</GiveTruncateText>
)}
</Stack>
</Stack>
);
};
|