Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename component to AvatarStack #43

Merged
merged 1 commit into from
Jul 12, 2023
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
2 changes: 1 addition & 1 deletion src/components/Avatar/Avatar.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ img.avatar {
}

.stacked-avatars .avatar:not(:last-child) {
/* injected in the document from StackedAvatars.tsx */
/* injected in the document from AvatarStack.tsx */
clip-path: url("#cpdAvatarClip");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@ limitations under the License.
import React from "react";
import { Meta, StoryFn } from "@storybook/react";

import { StackedAvatars as StackedAvatarsComponent } from "./StackedAvatars";
import { AvatarStack as AvatarStackComponent } from "./AvatarStack";
import { Avatar } from "./Avatar";

export default {
title: "StackedAvatar",
component: StackedAvatarsComponent,
component: AvatarStackComponent,
argTypes: {},
args: {
size: "64px",
},
} as Meta<typeof StackedAvatarsComponent>;
} as Meta<typeof AvatarStackComponent>;

const Template: StoryFn<typeof StackedAvatarsComponent> = (args) => (
<StackedAvatarsComponent {...args}>
const Template: StoryFn<typeof AvatarStackComponent> = (args) => (
<AvatarStackComponent {...args}>
<Avatar
name="Alice"
id="@alice:example.org"
Expand All @@ -43,8 +43,8 @@ const Template: StoryFn<typeof StackedAvatarsComponent> = (args) => (
size="200px"
src="/images/__test__/kitten2.jpg"
/>
</StackedAvatarsComponent>
</AvatarStackComponent>
);

export const StackedAvatars = Template.bind({});
StackedAvatars.args = {};
export const AvatarStack = Template.bind({});
AvatarStack.args = {};
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ limitations under the License.
import { render } from "@testing-library/react";
import React from "react";

import { StackedAvatars } from "./StackedAvatars";
import { AvatarStack } from "./AvatarStack";

const originalImage = global.Image;

describe("StackedAvatars", () => {
describe("AvatarStack", () => {
beforeEach(() => {
global.Image = class extends originalImage {
constructor() {
Expand All @@ -44,18 +44,18 @@ describe("StackedAvatars", () => {

it("renders", () => {
const { asFragment } = render(
<StackedAvatars avatars={avatars} size="32px" />
<AvatarStack avatars={avatars} size="32px" />
);
expect(asFragment()).toMatchSnapshot();
});

it("adds the mask to the body", () => {
render(<StackedAvatars avatars={avatars} size="32px" />);
render(<AvatarStack avatars={avatars} size="32px" />);

// We can't run better assertions as `SVG` loading is mocked out in jest
expect(document.querySelectorAll("svg")).toHaveLength(1);

render(<StackedAvatars avatars={avatars} size="32px" />);
render(<AvatarStack avatars={avatars} size="32px" />);

// We only one instance of the mask, ever!
expect(document.querySelectorAll("svg")).toHaveLength(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ import styles from "./Avatar.module.css";

import AvatarClipPath from "./avatar-clip.mask.svg";

type StackedAvatarsProps = {
type AvatarStackProps = {
className?: string;
};

const AVATAR_MASK_ID = "cpdAvatarClipSvg";
let stackedAvatarsUsageCount = 0;
let AvatarStackUsageCount = 0;

/**
* Renders a stack of avatars and clips the content appropriately.
*
* The `type` of avatars should always be set to `round`
* And all the avatars should have the same size.
*/
export const StackedAvatars = ({
export const AvatarStack = ({
children,
className,
}: React.PropsWithChildren<StackedAvatarsProps>): React.JSX.Element => {
}: React.PropsWithChildren<AvatarStackProps>): React.JSX.Element => {
/**
* The `clip-path` property in CSS supports a `path()` function, however
* that has to use pixel values.
Expand All @@ -48,20 +48,20 @@ export const StackedAvatars = ({
* But this is only supported in Firefox
* This leaves us with no choice but rendering SVG inline in the HTML document
* And making sure there is always only a single instance regardless of the
* amount of `StackedAvatars` instance in the document.
* amount of `AvatarStack` instance in the document.
*/
useEffect(() => {
if (stackedAvatarsUsageCount === 0) {
if (AvatarStackUsageCount === 0) {
const svgMask = renderToStaticMarkup(
<AvatarClipPath id={AVATAR_MASK_ID} />
);
document.body.insertAdjacentHTML("beforeend", svgMask);
}
stackedAvatarsUsageCount++;
AvatarStackUsageCount++;
return () => {
stackedAvatarsUsageCount--;
if (stackedAvatarsUsageCount <= 0) {
// Cleanup the mask if there are no instances of `StackedAvatars` left
AvatarStackUsageCount--;
if (AvatarStackUsageCount <= 0) {
// Cleanup the mask if there are no instances of `AvatarStack` left
// on the page
document.getElementById(AVATAR_MASK_ID)?.remove();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`StackedAvatars renders 1`] = `
exports[`AvatarStack renders 1`] = `
<DocumentFragment>
<div
class="stacked-avatars"
Expand Down