Skip to content

Pending Review

Pending Review from User Experience (UX)

Focus Component

Overview

The PWC Focus component provides visual focus indication and styling wrapper for form elements and interactive components. Built as a utility component, it enhances accessibility by providing consistent focus outlines and semantic color variants for different states and contexts.

Core Capabilities

  • Focus Visualization - Consistent focus ring styling with brand colors and accessibility-compliant contrast ratios
  • Semantic Variants - Six color variants (default, critical, invalid, success, tip, warning) for contextual state indication

  • Flexible Layout - Support for flex properties and alignment options to integrate with various layout patterns

  • Blur Border Option - Additional border styling for enhanced visual separation when elements lose focus

  • CSS Modern Features - Uses :has() selector for advanced styling based on child element focus states

  • Accessibility Standards - WCAG-compliant focus indicators that work with keyboard navigation and screen readers

When to use Focus:

  • Form elements requiring enhanced focus visibility beyond browser defaults
  • Interactive components needing contextual color coding for different states
  • Complex form layouts where consistent focus styling improves user experience
  • Accessibility-critical interfaces where clear focus indication is essential for navigation

When not to use Focus:

  • Simple text links or buttons where browser default focus styling is sufficient
  • Non-interactive elements that don't receive keyboard focus
  • Components that already include their own focus management and styling

Basic Implementation

import React from 'react';
import { PwcFocus, PwcInput } from "@progress-i360/pwc-react";

function MyComponent() {
  return (
    <>
      <PwcFocus variant="default">
        <input
          type="text"
          placeholder="Enter your name"
          style={{ border: 'none', outline: 'none', padding: '8px' }}
        />
      </PwcFocus>

      <PwcFocus variant="invalid">
        <input
          type="email"
          placeholder="Invalid email format"
          style={{ border: 'none', outline: 'none', padding: '8px' }}
        />
      </PwcFocus>

      <PwcFocus variant="success" flex>
        <PwcInput
          type="text"
          placeholder="Valid input"
          name="validInput"
        />
      </PwcFocus>
    </>
  );
}
import '@progress-i360/progress-web-components/focus';
import '@progress-i360/progress-web-components/input';

function FocusStates() {
  return (
    <>
      <pwc-focus variant="success" flex>
        <pwc-input
          type="text"
          name="validated-input"
          value="Valid input"
        ></pwc-input>
      </pwc-focus>

      <pwc-focus variant="warning" blur-border>
        <select style={{ border: 'none', outline: 'none', padding: '8px' }}>
          <option value="">Choose option</option>
          <option value="high">High priority</option>
          <option value="low">Low priority</option>
        </select>
      </pwc-focus>
    </>
  );
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/body";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/focus";
import "@progress-i360/progress-web-components/heading";

@Component({
  selector: 'focus-demo',
  template: `
    <pwc-flex direction="column" gap="m" padding="m">
      <pwc-heading content="Focus State Demonstration" size="l"></pwc-heading>
      <pwc-flex direction="column" gap="s">
        <pwc-body content="Click on the inputs below to see focus styling:"></pwc-body>
        <pwc-focus variant="default">
          <input type="text" placeholder="Default focus style" (focus)="setFocusType('default')" (blur)="clearFocus()">
        </pwc-focus>
        <pwc-focus [variant]="currentFocusVariant">
          <input type="email" placeholder="Validation focus (try invalid email)" 
                 [value]="emailValue" 
                 (input)="updateEmail($event)" 
                 (focus)="setFocusType('validation')" 
                 (blur)="validateEmail()">
        </pwc-focus>
        <pwc-focus variant="success" *ngIf="showSuccess">
          <input type="text" placeholder="Success state" readonly value="Valid input!">
        </pwc-focus>
      </pwc-flex>
      <pwc-flex gap="s">
        <pwc-button label="Trigger Success" variant="success" (pwc-click)="showSuccessState()"></pwc-button>
        <pwc-button label="Trigger Warning" variant="warning" (pwc-click)="showWarningState()"></pwc-button>
        <pwc-button label="Trigger Error" variant="critical" (pwc-click)="showErrorState()"></pwc-button>
      </pwc-flex>
      <pwc-body [content]="'Current focus: ' + (currentFocus || 'None') + ', Validations: ' + validationCount" color="subtle" size="xs"></pwc-body>
    </pwc-flex>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class FocusDemo {
  currentFocus = '';
  currentFocusVariant = 'default';
  emailValue = '';
  showSuccess = false;
  validationCount = 0;

  setFocusType(type: string) {
    this.currentFocus = type;
  }

  clearFocus() {
    this.currentFocus = '';
  }

  updateEmail(event: any) {
    this.emailValue = event.target.value;
  }

  validateEmail() {
    const isValid = this.emailValue.includes('@') && this.emailValue.includes('.');
    this.currentFocusVariant = isValid ? 'success' : 'invalid';
    this.validationCount++;
  }

  showSuccessState() {
    this.currentFocusVariant = 'success';
    this.showSuccess = true;
    this.validationCount++;
  }

  showWarningState() {
    this.currentFocusVariant = 'warning';
    this.validationCount++;
  }

  showErrorState() {
    this.currentFocusVariant = 'invalid';
    this.validationCount++;
  }
}
import '@progress-i360/progress-web-components/focus';

const focusWrapper = document.createElement('pwc-focus');
focusWrapper.setAttribute('variant', 'invalid');

const input = document.createElement('input');
input.type = 'email';
input.placeholder = 'Enter email address';

focusWrapper.appendChild(input);
document.body.appendChild(focusWrapper);

Usage Patterns

  • Form Validation - Use semantic variants (invalid, success, warning) to provide visual feedback for field validation states
  • Interactive Elements - Wrap buttons, inputs, and custom controls with focus styling for consistent keyboard navigation experience
  • State Communication - Apply contextual colors (critical, tip) to communicate urgency, importance, or informational context
  • Layout Integration - Use flex and alignment properties to integrate focused elements seamlessly with form layouts

Best Practices

Content Strategy Guidelines

  • Semantic Color Usage - Choose focus variants that match the semantic meaning of the content and validation state
  • Consistent Application - Apply focus styling consistently across similar interactive elements in the same interface
  • Clear Visual Hierarchy - Use focus variants to support, not compete with, other visual hierarchy elements
  • Accessibility Priority - Ensure focus indicators meet WCAG contrast requirements and are visible to all users

Performance Optimization

  • CSS Modern Features - Leverage :has() selector for efficient styling without JavaScript event handlers
  • Minimal DOM Impact - Use focus wrapper only when enhanced styling is needed beyond browser defaults
  • State-based Rendering - Conditionally apply focus variants based on actual validation or interaction states
  • Layout Efficiency - Use flex and alignment properties to reduce layout recalculations

Integration Architecture

  • Form System Integration - Coordinate focus variants with form validation states and error handling
  • Design Token Usage - Rely on design system color tokens for consistent focus styling across applications
  • Accessibility Standards - Ensure focus management works with screen readers and keyboard navigation patterns
  • Component Composition - Combine with other form components while maintaining focus behavior

Common Use Cases

Form Validation

  • Input field error states with red focus rings for validation failures
  • Success confirmation with green focus styling for completed valid fields
  • Warning states with orange focus for fields requiring attention but not blocking submission

Interactive Controls

  • Button focus enhancement for primary actions and critical operations
  • Custom control focus styling for complex widgets like date pickers and dropdown menus
  • Navigation element focus for keyboard accessibility in menus and tab interfaces

Status Indication

  • Critical alerts with red focus styling for urgent attention requirements
  • Informational tips with purple focus for helpful guidance and contextual information
  • Progress indicators with semantic focus colors to show completion states

Troubleshooting

Common Issues

Actions Not Triggering

Symptoms: Focus styles don't appear when elements receive keyboard focus

Solutions:

  • Verify child elements can receive focus (tabindex, focusable elements)

  • Check that :has() selector is supported in target browsers

  • Ensure focus styles aren't overridden by other CSS rules with higher specificity

Actions Not Visible

Symptoms: Focus component doesn't render or appears with default styling

Solutions:

  • Confirm renderSlot function returns valid Lit template result

  • Check CSS imports and focus styles are properly loaded

  • Verify variant names match expected FocusVariant types

Layout Issues

Symptoms: Focus wrapper disrupts intended layout or element positioning

Solutions:

  • Use alignSelf property to control focus wrapper alignment within flex containers

  • Apply flex property when focus wrapper should expand to fill available space

  • Check parent container styling doesn't conflict with focus wrapper display properties

Icon Problems

Symptoms: Focus colors don't match design system or appear incorrect

Solutions:

  • Verify design token CSS variables are loaded and available

  • Check color variant mapping matches intended semantic meaning

  • Ensure focus ring contrast meets accessibility requirements for background colors

Implementation Support

  • Accessibility Compliance - Focus indicator implementation strategies meeting WCAG guidelines and screen reader compatibility
  • Browser Compatibility - Fallback strategies for browsers that don't support modern CSS features like :has() selector
  • Design System Integration - Guidance for consistent focus styling patterns across complex application interfaces

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.