Pending Review
Pending Review from User Experience (UX)
Tag Component
Overview
The PWC Tag component provides a compact and visually distinctive way to categorize, label, and communicate status information throughout the application. Built on Lit web components, it features semantic color variants with integrated icons to convey meaning and context effectively in various interface scenarios.
Core Capabilities
- Semantic Variants - Eight meaningful color and icon combinations for different status types and contexts
- Integrated Icons - Automatic icon selection based on variant with option to disable for text-only display
- Flexible Styling - Standard and corner variants with gradient backgrounds and consistent typography
- Status Communication - Clear visual indicators for danger, success, warning, info, and other states
- Content Integration - Seamless integration with PWC Body and Icon components for consistent styling
- Layout Support - Full flex layout properties for precise positioning within parent containers
When to use Tag:
- Status Indicators - Display system states, process status, and operational conditions with clear visual meaning
- Content Classification - Categorize content, features, or data with descriptive labels and semantic colors
- Alert Communication - Provide contextual information and warnings without overwhelming the main interface
- Progress Tracking - Show completion states, maintenance windows, and operational statuses
When not to use Tag:
- Interactive Elements - Use button components for clickable actions instead of tags for navigation or operations
- Primary Content - Don't use tags as the main content delivery method or for essential information display
- Decorative Purpose - Avoid using tags purely for visual decoration without meaningful semantic content
Basic Implementation
import React, { useState, useCallback } from 'react';
import { PwcTag, PwcButton } from '@progress-i360/pwc-react';
function SystemStatus() {
const [services, setServices] = useState([
{ name: 'API Server', status: 'success' },
{ name: 'Database', status: 'warning' },
{ name: 'Cache', status: 'danger' }
]);
const [showIcons, setShowIcons] = useState(true);
// React 18: useCallback for optimization
const cycleStatus = useCallback((index) => {
const statusCycle = ['success', 'warning', 'danger', 'maintenance'];
setServices(prev => prev.map((service, i) => {
if (i === index) {
const currentIndex = statusCycle.indexOf(service.status);
return { ...service, status: statusCycle[(currentIndex + 1) % statusCycle.length] };
}
return service;
}));
}, []);
const toggleIcons = useCallback(() => {
setShowIcons(prev => !prev);
}, []);
return (
<div style={{ padding: '20px' }}>
<div style={{ marginBottom: '16px' }}>
{services.map((service, index) => (
<div key={service.name} style={{ marginBottom: '8px' }}>
<PwcTag
label={service.name}
variant={service.status}
noIcon={!showIcons}
onPwcClick={() => cycleStatus(index)}
style={{ cursor: 'pointer', marginRight: '8px' }}
/>
</div>
))}
</div>
<PwcButton
label={showIcons ? 'Hide Icons' : 'Show Icons'}
variant="outline"
onPwcClick={toggleIcons}
/>
</div>
);
}
import { useCallback, useMemo, useOptimistic, useState, startTransition } from 'react';
import '@progress-i360/progress-web-components/tag';
import '@progress-i360/progress-web-components/button';
type Task = {
id: number;
title: string;
status: 'info' | 'warning' | 'success' | 'danger';
};
function TaskTracker() {
const [tasks, setTasks] = useState<Task[]>([
{ id: 1, title: 'Deploy API', status: 'warning' },
{ id: 2, title: 'Update Docs', status: 'success' }
]);
const statusFlow = useMemo(() => ({
info: 'warning',
warning: 'success',
success: 'danger',
danger: 'info'
}) satisfies Record<Task['status'], Task['status']>, []);
// React 19+: Optimistic task status updates
const [optimisticTasks, updateTaskStatus] = useOptimistic(
tasks,
(state, payload: { taskId: number; newStatus: Task['status'] }) => state.map(task =>
task.id === payload.taskId ? { ...task, status: payload.newStatus } : task
)
);
const handleStatusClick = useCallback((taskId: number, currentStatus: Task['status']) => {
const newStatus = statusFlow[currentStatus];
updateTaskStatus({ taskId, newStatus });
startTransition(() => {
setTasks(prev => prev.map(task =>
task.id === taskId ? { ...task, status: newStatus } : task
));
});
}, [setTasks, statusFlow, updateTaskStatus]);
const addTask = useCallback(() => {
const newTask: Task = {
id: Date.now(),
title: `Task ${optimisticTasks.length + 1}`,
status: 'info'
};
startTransition(() => {
setTasks(prev => [...prev, newTask]);
});
}, [optimisticTasks.length, setTasks]);
return (
<div style={{ padding: '20px' }}>
{optimisticTasks.map(task => (
<div key={task.id} style={{ marginBottom: '8px' }}>
<pwc-tag
label={task.title}
variant={task.status}
onPwcClick={() => handleStatusClick(task.id, task.status)}
style={{ cursor: 'pointer' }}
></pwc-tag>
</div>
))}
<pwc-button
label="Add Task"
variant="primary"
onPwcClick={addTask}
style={{ marginTop: '8px' }}
></pwc-button>
</div>
);
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/tag";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/body";
import "@progress-i360/progress-web-components/heading";
@Component({
selector: 'tag-demo',
template: `
<pwc-flex direction="column" gap="m" padding="m">
<pwc-heading content="Status Tags Demo" size="l"></pwc-heading>
<pwc-flex gap="s" wrap="wrap" align-items="center">
<pwc-tag [label]="tagLabel" [variant]="currentVariant" [noIcon]="hideIcon"></pwc-tag>
<pwc-tag label="Success" variant="success"></pwc-tag>
<pwc-tag label="Warning" variant="warning"></pwc-tag>
<pwc-tag label="Maintenance" variant="maintenance"></pwc-tag>
</pwc-flex>
<pwc-flex gap="s" wrap="wrap">
<pwc-button label="Change Variant" variant="primary" (pwc-click)="changeVariant()"></pwc-button>
<pwc-button label="Toggle Icon" variant="outline" (pwc-click)="toggleIcon()"></pwc-button>
<pwc-button label="Update Label" variant="outline" (pwc-click)="updateLabel()"></pwc-button>
</pwc-flex>
<pwc-body [content]="'Current: ' + currentVariant + ', Icon: ' + (hideIcon ? 'Hidden' : 'Visible')" color="subtle" size="xs"></pwc-body>
</pwc-flex>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class TagDemo {
tagLabel = 'Active Status';
currentVariant = 'info';
hideIcon = false;
labelCount = 0;
variants = ['success', 'warning', 'danger', 'info', 'maintenance', 'tip', 'inactive', 'unknown'];
changeVariant() {
const currentIndex = this.variants.indexOf(this.currentVariant);
this.currentVariant = this.variants[(currentIndex + 1) % this.variants.length];
}
toggleIcon() {
this.hideIcon = !this.hideIcon;
}
updateLabel() {
this.labelCount++;
this.tagLabel = `Status #${this.labelCount}`;
}
}
import '@progress-i360/progress-web-components/tag';
const successTag = document.createElement('pwc-tag');
successTag.setAttribute('label', 'Completed');
successTag.setAttribute('variant', 'success');
const infoTag = document.createElement('pwc-tag');
infoTag.setAttribute('label', 'Information');
infoTag.setAttribute('variant', 'info');
infoTag.setAttribute('corner', 'true');
document.body.appendChild(successTag);
document.body.appendChild(infoTag);
Usage Patterns
- Status Display - Use semantic variants (danger, success, warning, info) to communicate system and process states clearly
- Content Labeling - Apply descriptive tags to categorize features, content types, and operational classifications
- Visual Hierarchy - Leverage color coding and icons to create scannable information architecture
- Corner Styling - Implement corner variant for tags attached to interface elements like cards or panels
Best Practices
Content Strategy Guidelines
- Clear Messaging - Write concise, descriptive labels that immediately convey meaning and context
- Semantic Consistency - Use tag variants consistently throughout the application for similar meanings
- Appropriate Length - Keep tag labels brief while maintaining clarity and avoiding abbreviations when possible
- Contextual Relevance - Ensure tags provide value and meaning within their specific interface context
Performance Optimization
- Efficient Rendering - Lightweight component structure that minimizes DOM impact and reflow operations
- Icon Optimization - Automatic icon selection reduces the need for manual icon management and configuration
- CSS Performance - Gradient backgrounds and styling optimized for smooth rendering across devices
- Memory Management - Minimal component footprint with efficient cleanup and state management
Integration Architecture
- Component Composition - Seamless integration with PWC Body and Icon components for consistent styling
- Design System Alignment - Full compatibility with PWC design tokens for colors, typography, and spacing
- Layout Flexibility - Support for flex layout properties enables precise positioning in complex layouts
- Theme Compatibility - Consistent appearance and contrast across light and dark theme variations
Common Use Cases
Data Table Headers
- Column Status - Display status tags in table headers to indicate data quality, processing states, or operational conditions
- Filter Indicators - Show active filter states and categories with appropriately colored tag variants
- Data Quality Tags - Communicate data validation states, completeness, and reliability metrics
Search Result Sections
- Result Categories - Tag search results with type, status, or relevance indicators for better information organization
- Status Indicators - Show result freshness, availability, or processing states with semantic color coding
- Feature Tags - Highlight special features, premium content, or access levels within search results
Dashboard Widget Headers
- Widget Status - Display operational status, data freshness, and system health indicators in widget headers
- Alert States - Show maintenance windows, system alerts, and operational notifications with appropriate urgency
- Performance Indicators - Communicate system performance, uptime, and operational metrics with visual clarity
Troubleshooting
Common Issues
Tag Not Displaying
Problem: Tag doesn't appear or shows without proper styling
Solution:
- Verify variant property is set correctly and CSS custom properties are loaded properly
Icon Not Showing
Problem: Tag displays without the expected semantic icon
Solution:
- Check that noIcon property is not set to true and variant mapping includes valid icon reference
Color Issues
Problem: Tag background or text colors don't match expected variant appearance
Solution:
- Ensure design tokens are loaded and variant property uses valid TagVariant enum values
Layout Problems
Problem: Tags don't align properly or cause layout disruption in parent containers
Solution:
- Check flex layout properties and ensure proper container styling for tag placement
Implementation Support
For detailed implementation guidance:
- Variant System - Eight semantic variants with automatic icon and color coordination
- Layout Integration - Full flex layout support for precise positioning and responsive design
- Component Composition - Seamless integration with PWC typography and icon component systems
Resources
Storybook Documentation
For comprehensive API documentation, interactive examples, and testing tools: 📖 View Complete API Documentation in Storybook →