Pending Review
Pending Review from User Experience (UX)
Avatar Component
Overview
The PWC Avatar is a circular typography component in the Progress Web Components design system. It provides consistent display of user initials and profile representation across React and Angular applications.
Core Capabilities
- Initial Display - Shows user initials in a circular container with consistent typography
- Typography Integration - Built on PWC Body component with inverse color theming
- Responsive Design - Fixed 2rem size that scales appropriately across screen sizes
- Accessibility Support - Screen reader friendly with semantic markup structure
- Theme Integration - Uses design system tokens for consistent visual appearance
- Lightweight Implementation - Minimal footprint with efficient rendering performance
When to use Avatar:
- Display user initials in profile sections and navigation areas
- Represent users in comment threads, activity feeds, and collaboration interfaces
- Provide visual identity in data tables showing user associations
- Create consistent user representation across application interfaces
When not to use Avatar:
- Complex profile images or photos (use dedicated image components)
- Brand logos or company representations (use logo components)
- Large profile displays requiring additional user information
Basic Implementation
import React, { useState, useCallback } from 'react';
import { PwcAvatar, PwcFlex, PwcButton, PwcHeading } from '@progress-i360/pwc-react';
function UserProfile() {
const [users] = useState([
{ id: 1, name: 'John Doe', email: 'john@company.com' },
{ id: 2, name: 'Alice Smith', email: 'alice@company.com' },
{ id: 3, name: 'Bob Wilson', email: 'bob@company.com' }
]);
const [currentIndex, setCurrentIndex] = useState(0);
const generateInitials = useCallback((name: string) => {
return name.split(' ')
.map(part => part.charAt(0).toUpperCase())
.slice(0, 2)
.join('');
}, []);
const handleNextUser = useCallback(() => {
setCurrentIndex((prev) => (prev + 1) % users.length);
}, [users.length]);
const currentUser = users[currentIndex];
return (
<PwcFlex gap="m" alignItems="center">
<PwcAvatar initials={generateInitials(currentUser.name)} />
<PwcFlex direction="column" gap="xs">
<PwcHeading content={currentUser.name} size="s" />
<PwcButton
label="Next User"
variant="outline"
onPwcClick={handleNextUser}
/>
</PwcFlex>
</PwcFlex>
);
}
import { useCallback, useDeferredValue, useOptimistic, useState } from 'react';
import '@progress-i360/progress-web-components/avatar';
import '@progress-i360/progress-web-components/flex';
import '@progress-i360/progress-web-components/button';
import '@progress-i360/progress-web-components/body';
function TeamAvatarList() {
const [teamMembers, setTeamMembers] = useState([
{ id: 1, name: 'Alice Johnson', status: 'online' },
{ id: 2, name: 'Bob Smith', status: 'away' },
{ id: 3, name: 'Carol Davis', status: 'offline' }
]);
const deferredMembers = useDeferredValue(teamMembers);
const [optimisticMembers, addOptimisticMember] = useOptimistic(
deferredMembers,
(state, newMember) => [...state, newMember]
);
const generateInitials = (name: string) => {
return name
.split(' ')
.map((part) => part.charAt(0).toUpperCase())
.slice(0, 2)
.join('');
};
const addTeamMember = useCallback(async () => {
const newMember = {
id: Date.now(),
name: 'New Member',
status: 'online'
};
addOptimisticMember(newMember);
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000));
setTeamMembers((prev) => [...prev, newMember]);
}, [addOptimisticMember]);
return (
<pwc-flex direction="column" gap="l">
<pwc-flex gap="s" align-items="center" wrap="wrap">
{optimisticMembers.map((member) => (
<pwc-flex key={member.id} direction="column" align-items="center" gap="xs">
<pwc-avatar initials={generateInitials(member.name)}></pwc-avatar>
<pwc-body content={member.status} size="xs"></pwc-body>
</pwc-flex>
))}
</pwc-flex>
<pwc-button
label="Add Team Member"
variant="primary"
onPwcClick={addTeamMember}
></pwc-button>
</pwc-flex>
);
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/avatar";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/heading";
@Component({
selector: 'avatar-demo',
template: `
<pwc-flex gap="m" align-items="center">
<pwc-avatar [initials]="userInitials"></pwc-avatar>
<pwc-flex direction="column" gap="s">
<pwc-heading [content]="userName" size="m"></pwc-heading>
<pwc-button label="Change User" variant="outline" (pwc-click)="changeUser()"></pwc-button>
</pwc-flex>
</pwc-flex>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AvatarDemo {
userName = 'John Smith';
userInitials = 'JS';
users = [
{ name: 'Alice Johnson', initials: 'AJ' },
{ name: 'Bob Wilson', initials: 'BW' },
{ name: 'Carol Davis', initials: 'CD' }
];
currentIndex = 0;
changeUser() {
this.currentIndex = (this.currentIndex + 1) % this.users.length;
const user = this.users[this.currentIndex];
this.userName = user.name;
this.userInitials = user.initials;
}
}
const avatar = document.createElement('pwc-avatar');
avatar.setAttribute('initials', 'JD');
const container = document.createElement('pwc-flex');
container.setAttribute('gap', 'm');
container.setAttribute('align-items', 'center');
// Dynamic initials generation from full name
function generateInitials(fullName) {
return fullName
.split(' ')
.map(name => name.charAt(0).toUpperCase())
.slice(0, 2)
.join('');
}
// User cycling functionality
const users = [
{ name: 'Alice Johnson', role: 'Designer' },
{ name: 'Bob Wilson', role: 'Developer' },
{ name: 'Carol Davis', role: 'Manager' }
];
let currentIndex = 0;
const cycleButton = document.createElement('pwc-button');
cycleButton.setAttribute('label', 'Next User');
cycleButton.addEventListener('pwc-click', () => {
currentIndex = (currentIndex + 1) % users.length;
const user = users[currentIndex];
avatar.setAttribute('initials', generateInitials(user.name));
});
container.appendChild(avatar);
container.appendChild(cycleButton);
document.body.appendChild(container);
Usage Patterns
Avatar components adapt to different user representation scenarios:
- Static Initials - Display predefined user initials for consistent identification
- Dynamic Generation - Generate initials from full names or user data objects
- Profile Integration - Combine with user names and additional profile information
- List Display - Show multiple avatars in user lists, comment threads, or activity feeds
Best Practices
Content Strategy Guidelines
- Meaningful Initials - Use first and last name initials for clear user identification
- Consistent Formatting - Apply uppercase formatting for professional appearance
- Fallback Handling - Provide default initials when user names are unavailable
- Character Limits - Limit to 2-3 characters maximum for optimal readability
Performance Optimization
- Efficient Rendering - Leverage component reusability for lists of multiple avatars
- Memory Management - Avoid unnecessary re-renders when initials don't change
- Lightweight Markup - Minimal DOM structure for fast loading and rendering
- CSS Optimization - Use design system tokens for consistent styling performance
Integration Architecture
- User Data Binding - Connect initials to user management systems and data sources
- Responsive Behavior - Ensure consistent appearance across different screen sizes
- Theme Compatibility - Maintain proper contrast ratios in light and dark themes
- Accessibility Standards - Include proper ARIA labels for screen reader support
Common Use Cases
Data Table Headers
- User Assignment Columns - Show assigned users in project management tables
- Author Attribution - Display content creators in document and article listings
- Team Member Display - Represent team members in collaborative workspace tables
Search Result Sections
- User Search Results - Display user avatars in people search and directory interfaces
- Comment Attribution - Show comment authors in search results and activity feeds
- Contact Listings - Represent contacts in address book and communication interfaces
Dashboard Widget Headers
- Activity Feeds - Show user avatars in recent activity and notification widgets
- Team Overviews - Display team member avatars in project dashboard widgets
- User Status - Represent online users and availability in collaboration dashboards
Troubleshooting
Common Issues
Initials Not Displaying
Problem: Avatar appears empty or shows no initials
Solution:
- Verify initials property is set correctly and contains valid string characters
Initials Not Visible
Problem: Initials text appears but isn't readable or visible
Solution:
- Check contrast ratios and ensure inverse color theming is working properly
Layout Issues
Problem: Avatar doesn't align properly with adjacent content
Solution:
- Use CSS flexbox or grid properties to align avatar with surrounding elements
Icon Problems
Problem: Avatar doesn't render consistently across different browsers
Solution:
- Verify web component polyfills are loaded and CSS variables are supported
Implementation Support
For detailed implementation guidance:
- Typography Integration - Works with PWC Body component for consistent text styling
- Design System Tokens - Uses standard color and sizing tokens for theme consistency
- Framework Compatibility - Tested across React, Angular, and vanilla JavaScript implementations
Resources
Storybook Documentation
For comprehensive API documentation, interactive examples, and testing tools: 📖 View Complete API Documentation in Storybook →
This guide provides high-level implementation guidance. For detailed API specifications and interactive examples, visit our Storybook documentation.