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
Binary file added src/assets/images/sistent/placeholder/user.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
229 changes: 229 additions & 0 deletions src/sections/Projects/Sistent/components/avatar-group/code.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
import React, { useState } from "react";
import { Avatar, AvatarGroup, SistentThemeProvider } from "@sistent/sistent";
import { SistentLayout } from "../../sistent-layout";
import TabButton from "../../../../../reusecore/Button";
import { CodeBlock } from "../button/code-block";
import { useStyledDarkMode } from "../../../../../theme/app/useStyledDarkMode";

import user1 from "../../../../../assets/images/sistent/placeholder/user.webp";
import user2 from "../../../../../assets/images/sistent/placeholder/user.webp";
import user3 from "../../../../../assets/images/sistent/placeholder/user.webp";
import user4 from "../../../../../assets/images/sistent/placeholder/user.webp";

const TABS = ["Overview", "Guidance", "Code"];

const avatarGroupExamples = [
{
title: "Basic AvatarGroup",
description: "Display a horizontal group of avatars with default overlap.",
element: (
<AvatarGroup>
<Avatar src={user1} alt="User 1" />
<Avatar src={user2} alt="User 2" />
<Avatar src={user3} alt="User 3" />
</AvatarGroup>
),
code: `<AvatarGroup>
<Avatar src="/user1.jpg" alt="User 1" />
<Avatar src="/user2.jpg" alt="User 2" />
<Avatar src="/user3.jpg" alt="User 3" />
</AvatarGroup>`,
id: "basic-group",
},
{
title: "Max Avatars",
description: "Limit the number of visible avatars using the `max` prop.",
element: (
<AvatarGroup max={3}>
<Avatar src={user1} alt="User 1" />
<Avatar src={user2} alt="User 2" />
<Avatar src={user3} alt="User 3" />
<Avatar src={user4} alt="User 4" />
</AvatarGroup>
),
code: `<AvatarGroup max={3}>
<Avatar src="/user1.jpg" />
<Avatar src="/user2.jpg" />
<Avatar src="/user3.jpg" />
<Avatar src="/user4.jpg" />
</AvatarGroup>`,
id: "max-group",
},
{
title: "Custom Spacing",
description: "Control the spacing between avatars.",
element: (
<AvatarGroup spacing="medium">
<Avatar src={user1} />
<Avatar src={user2} />
<Avatar src={user3} />
</AvatarGroup>
),
code: `<AvatarGroup spacing="medium">
<Avatar src="/user1.jpg" />
<Avatar src="/user2.jpg" />
<Avatar src="/user3.jpg" />
</AvatarGroup>`,
id: "spacing-group",
},
{
title: "Shape Variants",
description: "Mix avatar shape variants like square and rounded.",
element: (
<AvatarGroup>
<Avatar variant="rounded" src={user1} />
<Avatar variant="square" src={user2} />
<Avatar src={user3} />
</AvatarGroup>
),
code: `<AvatarGroup>
<Avatar variant="rounded" src="/user1.jpg" />
<Avatar variant="square" src="/user2.jpg" />
<Avatar src="/user3.jpg" />
</AvatarGroup>`,
id: "variant-group",
},
{
title: "Total Avatars",
description:
"You can indicate the total number of avatars using the `total` prop, even if not all are rendered.",
element: (
<AvatarGroup total={7}>
<Avatar src={user1} />
<Avatar src={user2} />
<Avatar src={user3} />
</AvatarGroup>
),
code: `<AvatarGroup total={7}>
<Avatar src="/user1.jpg" />
<Avatar src="/user2.jpg" />
<Avatar src="/user3.jpg" />
</AvatarGroup>`,
id: "total-avatars",
},
{
title: "Custom Surplus Renderer",
description:
"Customize the overflow display using the `renderSurplus` prop for more control over surplus appearance.",
element: (
<AvatarGroup
max={2}
renderSurplus={(surplus) => <span>+{surplus.toString()[0]}k</span>}
total={4251}
>
<Avatar src={user1} />
<Avatar src={user2} />
<Avatar src={user3} />
<Avatar src={user4} />
</AvatarGroup>
),
code: `<AvatarGroup
max={2}
renderSurplus={(surplus) => (
<Avatar sx={{ bgcolor: 'secondary.main' }}>{\`+\${surplus} more\`}</Avatar>
)}
>
<Avatar src="/user1.jpg" />
<Avatar src="/user2.jpg" />
<Avatar src="/user3.jpg" />
<Avatar src="/user4.jpg" />
</AvatarGroup>`,
id: "custom-surplus",
},
];

const AvatarGroupComponent = () => {
const { isDark } = useStyledDarkMode();
const [activeTab, setActiveTab] = useState("Overview");

return (
<SistentLayout title="Avatar Group">
<section className="content">
<a id="Identity">
<h2>Avatar Group</h2>
</a>
<p>
Below are practical implementation examples of the
<code>AvatarGroup</code> component, showcasing different
configurations such as max user limit, spacing, variant styling, and
accessibility-friendly usage. These examples are designed to help you
apply <code>AvatarGroup</code> effectively across team or user-related
interfaces.
</p>

<div className="filterBtns">
{TABS.map((tab) => (
<TabButton
key={tab}
title={tab}
className={activeTab === tab ? "active" : ""}
onClick={() => setActiveTab(tab)}
/>
))}
</div>

<p>
The AvatarGroup component helps visually group multiple avatars in a
compact and meaningful layout, often representing users in a shared
context.
</p>

{activeTab === "Code" && (
<div className="code-examples">
<h3>AvatarGroup Implementation Variants</h3>
<SistentThemeProvider initialMode={isDark ? "dark" : "light"}>
{avatarGroupExamples.map(
({ title, description, element, code, id }) => (
<section key={id}>
<h4>{title}</h4>
<p>{description}</p>
<div className="showcase">
<div className="items">{element}</div>
<CodeBlock name={id} code={code} />
</div>
</section>
),
)}
</SistentThemeProvider>
</div>
)}

{activeTab === "Overview" && (
<div className="overview">
<h3>Usage</h3>
<p>
Use AvatarGroup when you want to display a group of users or
entities visually. It's useful for team indicators,
collaborations, or contributors. You can adjust overlap, limit
display with `max`, or even indicate a total with `total`.
</p>
</div>
)}

{activeTab === "Guidance" && (
<div className="guidance">
<h3>Design Guidance</h3>
<p>
Keep avatar count minimal (ideally &lt; 5) to reduce clutter.
Surplus avatars should indicate remaining count clearly (e.g.
"+3"). Consider consistent shapes, sizes, and padding across your
app.
</p>
<ul>
<li>
Use `max` and `total` for clear grouping when avatars exceed
space.
</li>
<li>
Use `renderSurplus` to match branding or add tooltips/custom UI.
</li>
<li>Maintain consistent alt texts for accessibility.</li>
</ul>
</div>
)}
</section>
</SistentLayout>
);
};

export default AvatarGroupComponent;
123 changes: 123 additions & 0 deletions src/sections/Projects/Sistent/components/avatar-group/guidance.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import React from "react";
import { navigate } from "gatsby";
import { useLocation } from "@reach/router";
import { SistentLayout } from "../../sistent-layout";
import TabButton from "../../../../../reusecore/Button";

const AvatarGroupGuidance = () => {
const location = useLocation();

return (
<SistentLayout title="Avatar Group">
<div className="content">
<a id="Identity">
<h2>Avatar Group</h2>
</a>
<p>
The <strong>AvatarGroup</strong> component displays a compact
collection of avatar elements that represent a group of users or
entities. It’s useful in collaborative spaces, team-based features, or
user listings.
</p>

{/* Tabs */}
<div className="filterBtns">
<TabButton
className={
location.pathname === "/projects/sistent/components/avatar-group"
? "active"
: ""
}
onClick={() =>
navigate("/projects/sistent/components/avatar-group")
}
title="Overview"
/>
<TabButton
className={
location.pathname ===
"/projects/sistent/components/avatar-group/guidance"
? "active"
: ""
}
onClick={() =>
navigate("/projects/sistent/components/avatar-group/guidance")
}
title="Guidance"
/>
<TabButton
className={
location.pathname ===
"/projects/sistent/components/avatar-group/code"
? "active"
: ""
}
onClick={() =>
navigate("/projects/sistent/components/avatar-group/code")
}
title="Code"
/>
</div>

<div className="main-content">
<h3>Design Guidelines and Best Practices</h3>
<p>
When implementing <code>AvatarGroup</code>, it's important to
consider how it enhances collaboration and identity clarity without
overwhelming the interface. Here are key best practices:
</p>

<ul>
<li>
<strong>Use to represent teams or shared ownership:</strong> Ideal
for showing members of a project, contributors, or shared access
groups in apps like dashboards or chat.
</li>
<li>
<strong>Don’t overuse in dense interfaces:</strong> Too many
avatars in a group can clutter the view. Use the <code>max</code>{" "}
prop to collapse overflow into a <code>+N</code> indicator.
</li>
<li>
<strong>Use consistent sizing and spacing:</strong> Align all
avatars to the same size to maintain visual harmony. Use{" "}
<code>spacing</code> options (or <code>sx</code>) for controlled
overlap.
</li>
<li>
<strong>
Provide accessible <code>alt</code> text:
</strong>{" "}
Each avatar should have meaningful alternative text for screen
readers. Avoid empty or redundant <code>alt</code> values.
</li>
<li>
<strong>Avoid interactive behavior within AvatarGroup:</strong>{" "}
The component is for display only. If avatars must be clickable,
wrap each <code>&lt;Avatar&gt;</code> individually in buttons or
links outside the group context.
</li>
<li>
<strong>Keep it compact:</strong> AvatarGroup is not meant for
long lists. For large user sets, link to a full view or show
summary avatars only.
</li>
<li>
<strong>Fallbacks matter:</strong> Always account for broken
images by using initials or icons as fallback content within each{" "}
<code>Avatar</code>.
</li>
</ul>

<p>
These practices ensure that <code>AvatarGroup</code> remains a
helpful, visually tidy, and accessible interface element wherever
user identity grouping is necessary.
</p>
</div>
</div>
</SistentLayout>
);
};

export default AvatarGroupGuidance;
Loading