Pending Review
Pending Review from User Experience (UX)
Icon Component
Overview
The PWC Icon component provides a flexible and consistent way to display SVG icons throughout the application. Built on Lit web components, it supports both Carbon Design System icons and custom brand icons with comprehensive styling options, interactive capabilities, and animation support.
Core Capabilities
- Multiple Icon Libraries - Support for Carbon Design System icons and custom brand icons
- Comprehensive Color System - 14 semantic color variants including danger, success, warning, and info states
- Flexible Sizing - Six size options from extra small (xs) to extra large (xxl) with responsive scaling
- Interactive Elements - Clickable icons with hover states and custom event handling
- Animation Support - Built-in spin animation for loading indicators and dynamic states
- Brand Integration - Specialized brand icon support with custom dimensions and positioning
When to use Icon:
- Visual Communication - Enhance user interface clarity with universally recognized symbols
- Interactive Elements - Create clickable icon buttons for actions and navigation
- Status Indicators - Display system states, notifications, and feedback with semantic colors
- Loading States - Show progress and processing with animated spinning icons
When not to use Icon:
- Complex Illustrations - Use dedicated image components for detailed graphics or photographs
- Text Replacement - Avoid using icons as the sole means of conveying critical information
- Decorative Purpose Only - Don't add icons that don't enhance functionality or understanding
Basic Implementation
import React, { useState, useCallback } from 'react';
import { PwcIcon, PwcFlex, PwcButton } from '@progress-i360/pwc-react';
function StatusIcons() {
const [currentStatus, setCurrentStatus] = useState('idle');
const [isLoading, setIsLoading] = useState(false);
// React 18: useCallback for optimization
const statusConfig = useCallback(() => {
const configs = {
idle: { icon: 'circle', color: 'subtle' },
success: { icon: 'checkmark', color: 'success' },
error: { icon: 'warning-filled', color: 'danger' },
info: { icon: 'information', color: 'info' }
};
return configs[currentStatus] || configs.idle;
}, [currentStatus]);
const cycleStatus = useCallback(() => {
const statuses = ['idle', 'success', 'error', 'info'];
const currentIndex = statuses.indexOf(currentStatus);
setCurrentStatus(statuses[(currentIndex + 1) % statuses.length]);
}, [currentStatus]);
const toggleLoading = useCallback(() => {
setIsLoading(prev => !prev);
}, []);
const config = statusConfig();
return (
<PwcFlex gap="m" alignItems="center">
<PwcIcon
iconKey={config.icon}
color={config.color}
size="l"
clickable
onPwcClick={cycleStatus}
/>
<PwcIcon
iconKey="loading"
spin={isLoading}
color="info"
size="m"
/>
<PwcButton
label={`Toggle Loading`}
variant="outline"
onPwcClick={toggleLoading}
/>
</PwcFlex>
);
}
import { useCallback, useMemo, useOptimistic, useState, startTransition } from 'react';
import '@progress-i360/progress-web-components/icon';
import '@progress-i360/progress-web-components/flex';
import '@progress-i360/progress-web-components/button';
type NotificationType = 'info' | 'warning' | 'success';
type Notification = {
id: number;
type: NotificationType;
read: boolean;
};
function NotificationCenter() {
const [notifications, setNotifications] = useState<Notification[]>([
{ id: 1, type: 'info', read: false },
{ id: 2, type: 'warning', read: false },
{ id: 3, type: 'success', read: true }
]);
// React 19+: Optimistic updates for instant feedback
const [optimisticNotifications, markAsRead] = useOptimistic(
notifications,
(state, notificationId: number) =>
state.map(notification =>
notification.id === notificationId ? { ...notification, read: true } : notification
)
);
const getIconConfig = useCallback((type: NotificationType, read: boolean) => {
const configs: Record<NotificationType, { icon: string; color: string }> = {
info: { icon: 'information', color: read ? 'subtle' : 'info' },
warning: { icon: 'warning-filled', color: read ? 'subtle' : 'warning' },
success: { icon: 'checkmark', color: read ? 'subtle' : 'success' }
};
return configs[type];
}, []);
const handleNotificationClick = useCallback(
(id: number) => {
markAsRead(id);
startTransition(() => {
setNotifications(prev =>
prev.map(notification =>
notification.id === id ? { ...notification, read: true } : notification
)
);
});
},
[markAsRead, setNotifications]
);
const addNotification = useCallback(() => {
const types: NotificationType[] = ['info', 'warning', 'success'];
const newNotification: Notification = {
id: Date.now(),
type: types[Math.floor(Math.random() * types.length)],
read: false
};
startTransition(() => {
setNotifications(prev => [...prev, newNotification]);
});
}, [setNotifications]);
const renderedIcons = useMemo(
() =>
optimisticNotifications.map(notification => {
const config = getIconConfig(notification.type, notification.read);
return (
<pwc-icon
key={notification.id}
icon-key={config.icon}
color={config.color}
size="l"
clickable="true"
onPwcClick={() => handleNotificationClick(notification.id)}
></pwc-icon>
);
}),
[getIconConfig, handleNotificationClick, optimisticNotifications]
);
return (
<pwc-flex direction="column" gap="s">
<pwc-flex gap="s" align-items="center" wrap="wrap">
{renderedIcons}
</pwc-flex>
<pwc-button
label="Add Notification"
variant="primary"
onPwcClick={addNotification}
></pwc-button>
</pwc-flex>
);
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/icon";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/heading";
import "@progress-i360/progress-web-components/body";
@Component({
selector: 'icon-demo',
template: `
<pwc-flex direction="column" gap="m" padding="m">
<pwc-heading content="Interactive Icon Demo" size="l"></pwc-heading>
<pwc-flex align-items="center" gap="m" wrap="wrap">
<pwc-icon [iconKey]="currentIcon" [size]="iconSize" [color]="iconColor" [clickable]="true" (pwc-click)="handleIconClick()"></pwc-icon>
<pwc-icon iconKey="loading" [spin]="isLoading" color="info"></pwc-icon>
</pwc-flex>
<pwc-flex gap="s" wrap="wrap">
<pwc-button label="Change Icon" variant="outline" (pwc-click)="changeIcon()"></pwc-button>
<pwc-button label="Toggle Size" variant="outline" (pwc-click)="toggleSize()"></pwc-button>
<pwc-button label="Toggle Loading" variant="primary" (pwc-click)="toggleLoading()"></pwc-button>
</pwc-flex>
<pwc-body [content]="'Current: ' + currentIcon + ' (' + iconSize + ', ' + iconColor + ')'" color="subtle" size="xs"></pwc-body>
</pwc-flex>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class IconDemo {
currentIcon = 'settings';
iconSize = 'm';
iconColor = 'normal';
isLoading = false;
clickCount = 0;
icons = ['settings', 'user', 'notification', 'search', 'home'];
sizes = ['s', 'm', 'l', 'xl'];
colors = ['normal', 'success', 'danger', 'warning', 'info'];
handleIconClick() {
this.clickCount++;
this.iconColor = this.colors[this.clickCount % this.colors.length];
}
changeIcon() {
const currentIndex = this.icons.indexOf(this.currentIcon);
this.currentIcon = this.icons[(currentIndex + 1) % this.icons.length];
}
toggleSize() {
const currentIndex = this.sizes.indexOf(this.iconSize);
this.iconSize = this.sizes[(currentIndex + 1) % this.sizes.length];
}
toggleLoading() {
this.isLoading = !this.isLoading;
}
}
import '@progress-i360/progress-web-components/icon';
const infoIcon = document.createElement('pwc-icon');
infoIcon.setAttribute('icon-key', 'information');
infoIcon.setAttribute('color', 'info');
infoIcon.setAttribute('size', 'l');
infoIcon.setAttribute('clickable', 'true');
const loader = document.createElement('pwc-icon');
loader.setAttribute('icon-key', 'loading');
loader.setAttribute('spin', 'true');
loader.setAttribute('color', 'subtle');
document.body.appendChild(infoIcon);
document.body.appendChild(loader);
Usage Patterns
- Status Communication - Use semantic colors (danger, success, warning, info) to convey system states and feedback
- Interactive Navigation - Implement clickable icons with appropriate hover states for menu items and action buttons
- Loading Indicators - Apply spin animation to loading icons for visual feedback during data processing
- Brand Identity - Leverage brand icon type for company logos and proprietary symbol integration
Best Practices
Content Strategy Guidelines
- Semantic Meaning - Choose icons that have clear, universally understood meanings within your user context
- Consistent Usage - Use the same icon consistently for the same action or concept throughout the application
- Color Semantics - Apply color variants that align with their semantic meaning (danger for errors, success for completion)
- Accessibility Labels - Always provide meaningful titles and ARIA labels for screen reader compatibility
Performance Optimization
- Icon Caching - Leverage SVG mask loading system for efficient icon rendering and browser caching
- Size Optimization - Choose appropriate icon sizes to minimize DOM impact while maintaining visual clarity
- Animation Control - Use spin animation sparingly to avoid overwhelming users or impacting performance
- Event Management - Implement efficient click event handling with proper event delegation patterns
Integration Architecture
- Component Composition - Seamlessly integrate with other PWC components through consistent styling tokens
- Design System Alignment - Utilize Carbon Design System icons for standardized visual language
- Flexible Positioning - Support flex layout properties for precise positioning within parent containers
- Dynamic State Management - Enable runtime icon changes through reactive property updates
Common Use Cases
Data Table Headers
- Sort Indicators - Use directional icons to show column sort states with appropriate color coding
- Filter Controls - Implement clickable filter icons with hover states for data manipulation
- Action Buttons - Display edit, delete, and view icons with semantic colors for row-level operations
Search Result Sections
- Result Type Icons - Categorize search results with type-specific icons (document, user, folder)
- Status Indicators - Show result relevance or processing states with color-coded status icons
- Quick Actions - Provide clickable shortcut icons for common result actions like share or bookmark
Dashboard Widget Headers
- Widget Type Icons - Identify widget functionality with clear, recognizable category icons
- Status Monitoring - Display real-time status with color-coded icons for system health monitoring
- Configuration Access - Use settings icons as entry points for widget customization and configuration
Troubleshooting
Common Issues
Icons Not Displaying
Problem: Icon appears as empty space or placeholder
Solution:
- Verify iconKey matches available icon names and check SVG file path resolution
Color Not Applied
Problem: Icon displays in default color instead of specified variant
Solution:
- Ensure color property uses valid IconColor enum values and CSS custom properties are loaded
Click Events Not Working
Problem: Clickable icons don't respond to user interaction
Solution:
- Set clickable property to true and verify event handler is properly bound to pwc-click event
Animation Performance Issues
Problem: Spin animation causes visual lag or performance degradation
Solution:
- Limit concurrent spinning icons and consider using CSS will-change property for optimization
Implementation Support
For detailed implementation guidance:
- Carbon Integration - Seamlessly works with Carbon Design System icon library for consistent visual language
- Brand Customization - Supports custom brand icons with specialized dimensions and positioning controls
- Event System - Provides standardized click event handling through PWC component event architecture
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.