Skip to content

Pending Review

Pending Review from User Experience (UX)

Button Group Component

Overview

The PWC Button Group component provides a single-selection interface using connected buttons for mutually exclusive options. Built with Lit web components, it integrates seamlessly with form validation and offers visual feedback for selected states.

Core Capabilities

  • Single Selection - Exclusive selection pattern where only one option can be active at a time

  • Visual Connectivity - Connected button styling with shared borders and rounded corners on ends

  • Form Integration - Native form field behavior with validation, required state, and loading skeleton support

  • Accessibility Focus - Full keyboard navigation with proper ARIA attributes and screen reader compatibility

  • Option Management - Flexible option configuration with labels, values, and individual disabled states

  • State Indication - Clear visual feedback with checkmark icons and background highlighting for selected options

When to use Button Group:

  • Single-choice selections where all options should be visible simultaneously

  • Filter controls and view mode toggles with 2-5 related options

  • Category selection and content type switching interfaces

  • Form inputs requiring exclusive choice from a predefined set

When not to use Button Group:

  • Multiple selection scenarios where users need to choose several options

  • Long lists of options that would create excessive horizontal space requirements

  • Navigation between different pages or sections where other navigation patterns are more appropriate

Basic Implementation

import React from 'react';
import { PwcButtonGroup } from "@progress-i360/pwc-react";

function MyComponent() {
  const viewOptions = [
    { label: 'List', value: 'list' },
    { label: 'Grid', value: 'grid' },
    { label: 'Card', value: 'card' }
  ];

  return (
      <PwcButtonGroup
        label="View Mode"
        name="viewMode"
        options={viewOptions}
        required
      />
  );
}
import { useEffect, useMemo, useRef, useState } from 'react';
import '@progress-i360/progress-web-components/button-group';

type GroupOption = { label: string; value: string };

function PrioritySelector() {
  const options = useMemo<GroupOption[]>(() => [
    { label: 'Low', value: 'low' },
    { label: 'Medium', value: 'medium' },
    { label: 'High', value: 'high' }
  ], []);

  const groupRef = useRef<(HTMLElement & { options?: GroupOption[]; value?: string }) | null>(null);
  const [selected, setSelected] = useState('medium');

  useEffect(() => {
    if (groupRef.current) {
      groupRef.current.options = options;
    }
  }, [options]);

  useEffect(() => {
    const element = groupRef.current;
    if (!element) {
      return;
    }

    const handleChange = (event: Event) => {
      const { detail } = event as CustomEvent<string>;
      setSelected(detail);
    };

    element.addEventListener('pwc-change', handleChange as EventListener);
    return () => {
      element.removeEventListener('pwc-change', handleChange as EventListener);
    };
  }, []);

  useEffect(() => {
    if (groupRef.current) {
      groupRef.current.value = selected;
    }
  }, [selected]);

  return (
    <div style={{ maxWidth: '320px' }}>
      <pwc-button-group
        ref={groupRef}
        label="Priority Level"
        name="priority"
        hint="Select task priority"
        required="true"
      ></pwc-button-group>
    </div>
  );
}
import { Component, CUSTOM_ELEMENTS_SCHEMA } from "@angular/core";
import "@progress-i360/progress-web-components/button-group";
import "@progress-i360/progress-web-components/button";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/heading";
import "@progress-i360/progress-web-components/body";

@Component({
  selector: 'button-group-demo',
  template: `
    <pwc-flex direction="column" gap="m" padding="m">
      <pwc-heading content="View Selection Demo" size="l"></pwc-heading>
      <pwc-button-group 
        label="Display Mode" 
        [options]="viewOptions" 
        [value]="selectedView"
        (pwc-change)="handleViewChange($event)">
      </pwc-button-group>
      <pwc-button-group 
        label="Priority Filter" 
        [options]="priorityOptions" 
        [value]="selectedPriority"
        [required]="true"
        (pwc-change)="handlePriorityChange($event)">
      </pwc-button-group>
      <pwc-flex gap="s">
        <pwc-button label="Add Option" variant="outline" (pwc-click)="addOption()"></pwc-button>
        <pwc-button label="Reset Selection" variant="clear" (pwc-click)="resetSelections()"></pwc-button>
      </pwc-flex>
      <pwc-body [content]="'View: ' + selectedView + ', Priority: ' + (selectedPriority || 'None')" color="subtle" size="xs"></pwc-body>
    </pwc-flex>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class ButtonGroupDemo {
  selectedView = 'grid';
  selectedPriority = '';

  viewOptions = [
    { label: 'List', value: 'list' },
    { label: 'Grid', value: 'grid' },
    { label: 'Card', value: 'card' }
  ];

  priorityOptions = [
    { label: 'High', value: 'high' },
    { label: 'Medium', value: 'medium' },
    { label: 'Low', value: 'low' }
  ];

  handleViewChange(e: Event) {
    const ce = (e as CustomEvent);
    this.selectedView = ce.detail;
  }

  handlePriorityChange(e: Event) {
    const ce = (e as CustomEvent);
    this.selectedPriority = ce.detail;
  }

  addOption() {
    const newOption = { label: 'Table', value: 'table' };
    if (!this.viewOptions.find(opt => opt.value === 'table')) {
      this.viewOptions = [...this.viewOptions, newOption];
    }
  }

  resetSelections() {
    this.selectedView = 'list';
    this.selectedPriority = '';
  }
}
import '@progress-i360/progress-web-components/button-group';

const buttonGroup = document.createElement('pwc-button-group');
buttonGroup.setAttribute('label', 'View Mode');
buttonGroup.options = [
  { label: 'List', value: 'list' },
  { label: 'Grid', value: 'grid' },
  { label: 'Card', value: 'card' }
];

buttonGroup.addEventListener('pwc-change', (event) => {
  console.log('Selected value:', event.detail);
});

document.body.appendChild(buttonGroup);

Usage Patterns

  • View Controls - Toggle between different data visualization modes like list, grid, or card layouts

  • Filter Categories - Single-selection filters for status, type, or priority categories with immediate visual feedback

  • Form Choices - Exclusive selection inputs for preferences, settings, or configuration options in forms

  • Content Switches - Switch between related content types or display modes within the same interface context

Best Practices

Content Strategy Guidelines

  • Clear Labels - Use concise, descriptive labels that clearly differentiate between options

  • Logical Grouping - Organize options in a logical order such as priority levels or chronological sequence

  • Consistent Terminology - Maintain consistent naming conventions across similar button groups

  • Appropriate Scope - Limit to 2-5 options to prevent interface clutter and maintain usability

Performance Optimization

  • Option Caching - Cache option arrays to prevent unnecessary re-renders on component updates

  • Event Debouncing - Implement debouncing for rapid selection changes to reduce processing overhead

  • Conditional Rendering - Only render button groups when options are available and relevant

  • State Management - Use efficient state management patterns to handle selection changes

Integration Architecture

  • Form Context - Leverage form integration for validation, loading states, and submission handling

  • Accessibility Standards - Ensure proper keyboard navigation and screen reader announcements

  • Design Tokens - Use consistent spacing, colors, and typography from the design system

  • Component Composition - Combine with labels, hints, and validation messages for complete form fields

Common Use Cases

Data Filtering

  • Status filters for active, inactive, or pending items in data tables

  • Category filters for content types, departments, or classification systems

  • Time period selections for reports, analytics, and historical data views

Interface Controls

  • View mode toggles for switching between different data presentation formats

  • Theme or appearance selections for user interface customization

  • Language or locale selection for internationalization support

Form Selections

  • Priority level selection for tasks, tickets, or project items

  • Preference settings for notifications, privacy, or display options

  • Configuration choices for features, modules, or application behavior

Troubleshooting

Common Issues

Actions Not Triggering

Symptoms: Button group selections don't fire change events or update values

Solutions:

  • Verify pwc-change event listeners are properly attached

  • Check if button group is disabled or in loading state

  • Ensure options array is properly formatted with value and label properties

Actions Not Visible

Symptoms: Button group doesn't render or appears empty

Solutions:

  • Confirm options array is populated with valid option objects

  • Check CSS display properties and container overflow settings

  • Verify component is imported and registered correctly in the application

Layout Issues

Symptoms: Buttons appear disconnected or with incorrect spacing

Solutions:

  • Check parent container width and flex properties affecting button sizing

  • Ensure proper CSS border-radius and margin styles are not overridden

  • Verify button group is not wrapped in containers with conflicting styling

Icon Problems

Symptoms: Selected state checkmark icons don't appear or display incorrectly

Solutions:

  • Confirm icon system is properly loaded and available

  • Check color token values for disabled and normal icon states

  • Verify selected state styling is properly applied with background colors

Implementation Support

  • Form Integration - Pattern guidance for validation, error handling, and submission workflows

  • Accessibility Compliance - WCAG implementation strategies and screen reader optimization

  • Design System Integration - Token usage, theming, and consistent styling across applications

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.