Skip to content

Pending Review

Pending Review from User Experience (UX)

Copyright Component

Overview

The PWC Copyright is a specialized typography component in the Progress Web Components design system. It provides consistent copyright notice display with automatic year calculation and standardized legal text formatting across React and Angular applications.

Core Capabilities

  • Automatic Year Range - Generates copyright year ranges from start year to current year
  • Localization Support - Integrated with Lit localize for multi-language copyright notices
  • Progress Branding - Standard Progress Software Corporation copyright text formatting
  • Body Text Integration - Built on PWC Body component with disabled color and XS size
  • Semi-Bold Typography - Emphasized weight for legal notice visibility
  • Dynamic Updates - Automatically updates current year without manual intervention

When to use Copyright:

  • Display legal copyright notices in application footers and legal pages
  • Show Progress Software Corporation attribution in branded applications
  • Present standardized copyright information with proper year formatting
  • Include required legal notices in compliance and licensing contexts

When not to use Copyright:

  • Custom copyright text requiring different formatting (use Body component)
  • Non-Progress copyright notices requiring different legal text
  • General informational or disclaimer text (use appropriate text components)

Basic Implementation

import React, { useState, useCallback, useMemo } from 'react';
import { PwcCopyright, PwcFlex, PwcButton, PwcBody } from '@progress-i360/pwc-react';

function AppFooter() {
  const [appMode, setAppMode] = useState('production');
  const [showVersionInfo, setShowVersionInfo] = useState(false);

  // React 18: Manual memoization for copyright configuration
  const copyrightConfig = useMemo(() => {
    const configs = {
      production: { startYear: 2020, env: 'Production Environment' },
      staging: { startYear: 2022, env: 'Staging Environment' },
      development: { startYear: 2023, env: 'Development Environment' }
    };
    return configs[appMode] || configs.production;
  }, [appMode]);

  // React 18: useCallback for performance optimization
  const cycleEnvironment = useCallback(() => {
    const modes = ['production', 'staging', 'development'];
    const currentIndex = modes.indexOf(appMode);
    setAppMode(modes[(currentIndex + 1) % modes.length]);
  }, [appMode]);

  const toggleVersionInfo = useCallback(() => {
    setShowVersionInfo(prev => !prev);
  }, []);

  return (
      <PwcFlex direction="column" gap="s" alignItems="center">
        <PwcCopyright startYear={copyrightConfig.startYear} />

        {showVersionInfo && (
          <PwcBody 
            content={`${copyrightConfig.env} • Version 2.1.0`}
            size="xs" 
            color="subtle"
          />
        )}

        <PwcFlex gap="s">
          <PwcButton
            label="Change Environment"
            variant="outline"
            onPwcClick={cycleEnvironment}
          />
          <PwcButton
            label={`${showVersionInfo ? 'Hide' : 'Show'} Version`}
            variant="outline"
            onPwcClick={toggleVersionInfo}
          />
        </PwcFlex>

        <PwcBody 
          content={`Current: ${appMode}`}
          size="xs" 
          color="subtler"
        />
      </PwcFlex>
  );
}
import { useCallback, useState, useDeferredValue, useOptimistic, startTransition } from 'react';
import '@progress-i360/progress-web-components/copyright';
import '@progress-i360/progress-web-components/flex';
import '@progress-i360/progress-web-components/button';
import '@progress-i360/progress-web-components/body';

type Application = {
  id: number;
  name: string;
  startYear: number;
  active: boolean;
};

function DynamicCopyrightFooter() {
  const [applications, setApplications] = useState<Application[]>([
    { id: 1, name: 'Progress® OpenEdge®', startYear: 1984, active: true },
    { id: 2, name: 'Progress® DataDirect®', startYear: 1993, active: false },
    { id: 3, name: 'Progress® Chef®', startYear: 2008, active: false }
  ]);

  // React 19+: Defer expensive application list rendering
  const deferredApplications = useDeferredValue(applications);

  // React 19+: Optimistic updates for instant feedback
  const [optimisticApps, setOptimisticApp] = useOptimistic(
    deferredApplications,
    (state, updatedApp) =>
      state.map(app => (app.id === updatedApp.id ? { ...app, ...updatedApp } : app))
  );

  const activeApp = optimisticApps.find(app => app.active) || optimisticApps[0];

  const switchApplication = useCallback(
    async (targetApp: Application) => {
      // React 19+: Optimistic update for instant UI feedback
      setOptimisticApp({ id: targetApp.id, active: true });

      // React 19+: Use startTransition for non-urgent updates
      startTransition(() => {
        setApplications(prev =>
          prev.map(app => ({
            ...app,
            active: app.id === targetApp.id
          }))
        );
      });

      // Simulate loading application context
      await new Promise(resolve => setTimeout(resolve, 500));
    },
    [setOptimisticApp, setApplications]
  );

  const addNewApplication = useCallback(() => {
    const newApp = {
      id: Date.now(),
      name: 'Progress® New Product',
      startYear: new Date().getFullYear(),
      active: false
    };

    startTransition(() => {
      setApplications(prev => [...prev, newApp]);
    });
  }, [setApplications]);

  return (
    <pwc-flex direction="column" gap="m" align-items="center">
      <pwc-copyright start-year={String(activeApp.startYear)}></pwc-copyright>

      <pwc-body
        content={`Active Application: ${activeApp.name}`}
        size="xs"
        weight="semi-bold"
        color="blue-base"
      ></pwc-body>

      <pwc-flex direction="column" gap="s">
        <pwc-flex gap="xs" wrap="wrap" justify-content="center">
          {optimisticApps.map(app => (
            <pwc-button
              key={app.id}
              label={app.name.replace('Progress® ', '')}
              variant={app.active ? 'primary' : 'outline'}
              onPwcClick={() => switchApplication(app)}
            ></pwc-button>
          ))}
        </pwc-flex>

        <pwc-button
          label="Add New Product"
          variant="outline"
          onPwcClick={addNewApplication}
        ></pwc-button>
      </pwc-flex>

      <pwc-body
        content={`Managing ${optimisticApps.length} Progress products`}
        size="xs"
        color="subtle"
      ></pwc-body>
    </pwc-flex>
  );
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/copyright";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/heading";

@Component({
  selector: 'copyright-demo',
  template: `
    <pwc-flex direction="column" gap="m" padding="m">
      <pwc-heading content="Copyright Examples" size="l"></pwc-heading>
      <pwc-copyright [startYear]="startYear"></pwc-copyright>
      <pwc-flex gap="s">
        <pwc-button label="Change Year" variant="outline" (pwc-click)="changeStartYear()"></pwc-button>
        <pwc-button label="Current Year Only" variant="outline" (pwc-click)="currentYearOnly()"></pwc-button>
      </pwc-flex>
      <pwc-body [content]="'Start Year: ' + (startYear || 'Not Set')" color="subtle" size="xs"></pwc-body>
    </pwc-flex>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class CopyrightDemo {
  startYear = 2020;

  changeStartYear() {
    const years = [2018, 2019, 2020, 2021, 2022];
    const currentIndex = years.indexOf(this.startYear);
    this.startYear = years[(currentIndex + 1) % years.length];
  }

  currentYearOnly() {
    this.startYear = undefined;
  }
}
import '@progress-i360/progress-web-components/copyright';

const copyright = document.createElement('pwc-copyright');
copyright.setAttribute('start-year', '2020');

const currentCopyright = document.createElement('pwc-copyright');

const footer = document.querySelector('footer');
footer?.appendChild(copyright);
footer?.appendChild(currentCopyright);

Usage Patterns

Copyright components adapt to different legal and branding scenarios:

  • Year Range Display - Automatic calculation from start year to current year (e.g., "2020-2025")
  • Current Year Only - Display current year when no start year is specified
  • Standard Branding - Consistent Progress Software Corporation legal text formatting
  • Footer Integration - Seamless integration with application footer layouts

Best Practices

Content Strategy Guidelines

  • Accurate Start Years - Set start year to reflect actual project or product inception date
  • Consistent Placement - Position copyright notices in standard footer locations
  • Legal Compliance - Ensure copyright notices meet legal requirements for target jurisdictions
  • Brand Consistency - Use standard Progress Software Corporation copyright formatting

Performance Optimization

  • Static Rendering - Component renders efficiently with minimal DOM updates
  • Localization Efficiency - Leverage Lit localize for optimal multi-language support
  • Memory Management - Lightweight implementation with minimal resource usage
  • Year Caching - Efficient year calculation and display without repeated processing

Integration Architecture

  • Body Component Integration - Built on PWC Body component for consistent typography
  • Theme Compatibility - Works seamlessly with light and dark theme variations
  • Footer Layout Support - Integrates well with various footer layout patterns
  • Responsive Behavior - Maintains proper display across all screen sizes and devices

Common Use Cases

Data Table Headers

  • Table Footer Information - Copyright notices in data export footers and print layouts
  • Report Attribution - Legal attribution in generated reports and data summaries
  • Documentation Headers - Copyright information in table-based documentation layouts

Search Result Sections

  • Search Footer Information - Copyright notices in search result page footers
  • Content Attribution - Legal information for search result content and data sources
  • Export Metadata - Copyright notices in exported search results and data files

Dashboard Widget Headers

  • Dashboard Footer Areas - Copyright information in dashboard footer sections
  • Widget Legal Information - Attribution information for proprietary dashboard data
  • Application Branding - Consistent Progress branding across dashboard interfaces

Troubleshooting

Common Issues

Start Year Not Working

Problem: Start year property doesn't generate correct year range

Solution:

  • Verify startYear property is set as number type and component is properly initialized

Text Not Displaying

Problem: Copyright text doesn't appear or shows empty content

Solution:

  • Check localization setup and ensure Lit localize is properly configured

Layout Issues

Problem: Copyright notice doesn't align properly in footer

Solution:

  • Apply appropriate CSS styles and check parent container layout properties

Localization Problems

Problem: Copyright text doesn't translate or shows incorrect language

Solution:

  • Verify localization configuration and ensure proper locale setup

Implementation Support

For detailed implementation guidance:

  • Localization Integration - Works with Lit localize for multi-language support
  • Body Component Dependency - Leverages PWC Body component for consistent styling
  • Progress Branding - Maintains standard Progress Software Corporation legal formatting

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.