Skip to content

Commit

Permalink
update AvatarGroup API using context
Browse files Browse the repository at this point in the history
  • Loading branch information
somethiiing committed Jan 11, 2024
1 parent 4230052 commit 9525e3e
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 131 deletions.
23 changes: 10 additions & 13 deletions packages/syntax-core/src/Avatar/Avatar.module.css
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
:root {
--syntax-avatar-border-width: 1px;
}

.avatar {
box-sizing: border-box;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
border-radius: 50%;
border: var(--syntax-avatar-border-width) solid #fff;
border: 2px solid #fff;
}

.sm {
width: calc(24px - var(--syntax-avatar-border-width) * 2);
height: calc(24px - var(--syntax-avatar-border-width) * 2);
width: 24px;
height: 24px;
}

.md {
width: calc(40px - var(--syntax-avatar-border-width) * 2);
height: calc(40px - var(--syntax-avatar-border-width) * 2);
width: 40px;
height: 40px;
}

.lg {
width: calc(72px - var(--syntax-avatar-border-width) * 2);
height: calc(72px - var(--syntax-avatar-border-width) * 2);
width: 72px;
height: 72px;
}

.xl {
width: calc(128px - var(--syntax-avatar-border-width) * 2);
height: calc(128px - var(--syntax-avatar-border-width) * 2);
width: 128px;
height: 129px;
}
77 changes: 67 additions & 10 deletions packages/syntax-core/src/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { type ReactElement } from "react";
import classNames from "classnames";
import styles from "./Avatar.module.css";
import Box from "../Box/Box";
import { useAvatarGroup } from "../AvatarGroup/AvatarGroup";

const sizeToIconStyles = {
sm: { bottom: 8, marginInlineEnd: 0, height: 4, width: 4 },
Expand All @@ -9,15 +11,14 @@ const sizeToIconStyles = {
xl: { bottom: 12, marginInlineEnd: 12, height: 16, width: 16 },
} as const;

/**
* [Avatar](https://cambly-syntax.vercel.app/?path=/docs/components-avatar--docs) is a circular image that represents a user.
*/
const Avatar = ({
accessibilityLabel,
icon,
size = "md",
src,
}: {
const sizeToMargin = {
sm: -16,
md: -28,
lg: -48,
xl: -88,
} as const;

type AvatarProps = {
/**
* Alt text to use for the image.
* This should describe the image to people using screen readers.
Expand All @@ -42,7 +43,14 @@ const Avatar = ({
* URL of the image to display as the avatar.
*/
src: string;
}): JSX.Element => {
};

function AvatarInternal({
accessibilityLabel,
icon,
size = "md",
src,
}: AvatarProps): ReactElement {
return (
<div className={styles[size]}>
<img
Expand All @@ -68,6 +76,55 @@ const Avatar = ({
)}
</div>
);
}

/**
* [Avatar](https://cambly-syntax.vercel.app/?path=/docs/components-avatar--docs) is a circular image that represents a user.
*/
const Avatar = ({
accessibilityLabel,
icon,
size = "md",
src,
}: AvatarProps): JSX.Element => {
const avatarGroupContext = useAvatarGroup();

if (avatarGroupContext !== null) {
return (
<Box
position="relative"
dangerouslySetInlineStyle={{
__style: {
marginInlineEnd: sizeToMargin[avatarGroupContext.size],
},
}}
>
<Box
display="flex"
alignItems="center"
justifyContent="center"
backgroundColor="white"
rounding="full"
>
<AvatarInternal
accessibilityLabel={accessibilityLabel}
icon={icon}
size={avatarGroupContext.size}
src={src}
/>
</Box>
</Box>
);
}

return (
<AvatarInternal
accessibilityLabel={accessibilityLabel}
icon={icon}
size={size}
src={src}
/>
);
};

export default Avatar;
147 changes: 67 additions & 80 deletions packages/syntax-core/src/AvatarGroup/AvatarGroup.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type StoryObj, type Meta } from "@storybook/react";
import AvatarGroup from "./AvatarGroup";
import Avatar from "../Avatar/Avatar";
import image from "../../../../apps/storybook/assets/images/jane.webp";
import defaultAvatar from "../../../../apps/storybook/assets/images/defaultAvatar.svg";
import type Avatar from "../Avatar/Avatar";
import Box from "../Box/Box";
import { type ComponentProps } from "react";

Expand All @@ -29,29 +29,11 @@ export default {
tags: ["autodocs"],
} as Meta<typeof AvatarGroup>;

const filledAvatars = [
{
src: image,
accessibilityLabel: "Jane",
key: "Jane",
icon: (
<div
style={{
height: "100%",
width: "100%",
backgroundColor: "green",
borderRadius: "50%",
}}
/>
),
},
];

const defaultAvatars = Array(2)
.fill(undefined)
.map((_, idx) => ({
src: defaultAvatar,
accessibilityLabel: "defaultAccessibilityLAbel",
accessibilityLabel: "defaultAccessibilityLabel",
key: `defaultAvatar${idx}`,
}));

Expand All @@ -64,31 +46,29 @@ export const Default: StoryObj<
render: (args) => {
const { size, orientation } = args;
return (
<Box width={200} margin={4}>
<AvatarGroup orientation={orientation}>
{filledAvatars.map(
({ src, accessibilityLabel, key, icon }, index) => (
<AvatarGroup.Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
icon={icon}
orientation={orientation}
size={size}
zIndex={filledAvatars.length + defaultAvatars.length - index}
/>
),
)}
{defaultAvatars.map(({ src, accessibilityLabel, key }, index) => (
<AvatarGroup.Avatar
<Box backgroundColor="gray100">
<AvatarGroup size={size} orientation={orientation}>
{defaultAvatars.map(({ src, accessibilityLabel, key }) => (
<Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
orientation={orientation}
size={size}
zIndex={defaultAvatars.length - index}
/>
))}
<Avatar
src={image}
accessibilityLabel="Jane"
icon={
<div
style={{
height: "100%",
width: "100%",
backgroundColor: "green",
borderRadius: "50%",
}}
/>
}
/>
</AvatarGroup>
</Box>
);
Expand All @@ -104,31 +84,29 @@ export const Standard: StoryObj<
render: (args) => {
const { size, orientation } = args;
return (
<Box width={200} margin={4}>
<AvatarGroup orientation={orientation}>
{filledAvatars.map(
({ src, accessibilityLabel, key, icon }, index) => (
<AvatarGroup.Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
icon={icon}
orientation={orientation}
size={size}
zIndex={filledAvatars.length + defaultAvatars.length - index}
/>
),
)}
{defaultAvatars.map(({ src, accessibilityLabel, key }, index) => (
<AvatarGroup.Avatar
<Box backgroundColor="gray100">
<AvatarGroup size={size} orientation={orientation}>
{defaultAvatars.map(({ src, accessibilityLabel, key }) => (
<Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
orientation={orientation}
size={size}
zIndex={defaultAvatars.length - index}
/>
))}
<Avatar
src={image}
accessibilityLabel="Jane"
icon={
<div
style={{
height: "100%",
width: "100%",
backgroundColor: "green",
borderRadius: "50%",
}}
/>
}
/>
</AvatarGroup>
</Box>
);
Expand All @@ -144,33 +122,42 @@ export const Reverse: StoryObj<
render: (args) => {
const { size, orientation } = args;
return (
<Box width={200} margin={4}>
<AvatarGroup orientation={orientation}>
{filledAvatars.map(
({ src, accessibilityLabel, key, icon }, index) => (
<AvatarGroup.Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
icon={icon}
orientation={orientation}
size={size}
zIndex={filledAvatars.length + defaultAvatars.length - index}
/>
),
)}
{defaultAvatars.map(({ src, accessibilityLabel, key }, index) => (
<AvatarGroup.Avatar
<Box backgroundColor="gray100">
<AvatarGroup size={size} orientation={orientation}>
{defaultAvatars.map(({ src, accessibilityLabel, key }) => (
<Avatar
src={src}
accessibilityLabel={accessibilityLabel}
key={key}
orientation={orientation}
size={size}
zIndex={defaultAvatars.length - index}
/>
))}
<Avatar
src={image}
accessibilityLabel="Jane"
icon={
<div
style={{
height: "100%",
width: "100%",
backgroundColor: "green",
borderRadius: "50%",
}}
/>
}
/>
</AvatarGroup>
</Box>
);
},
};

export const Test: StoryObj = {
args: { size: "xl", orientation: "reverse" },
render: () => (
<>
<Avatar src={image} accessibilityLabel="Jane" key="Jane" />
<Avatar src={image} accessibilityLabel="Jane" key="Jane" />
<Avatar src={image} accessibilityLabel="Jane" key="Jane" />
</>
),
};
Loading

0 comments on commit 9525e3e

Please sign in to comment.