Skip to content

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 →