Skip to content

Pending Review

Pending Review from User Experience (UX)

Button Section Component

Overview

The PWC Button Section component combines a button group selection with dynamic content areas that change based on the selected option. This pattern enables contextual form sections and progressive disclosure interfaces where related controls appear based on user selections.

Core Capabilities

  • Dynamic Content Areas - Content sections that show/hide based on button group selection using named slots

  • Button Group Integration - Built-in button group for option selection with all standard button group features

  • Progressive Disclosure - Reveal relevant form fields and controls only when specific options are selected

  • Form Section Composition - Supports nested form inputs and sections within each selectable content area

  • State Management - Maintains selection state and synchronizes with form context for validation and submission

  • Flexible Layout - Responsive column layout with consistent spacing and alignment for all content sections

When to use Button Section:

  • Multi-step forms where different options require different sets of form fields

  • Configuration interfaces with mutually exclusive settings that need specific controls

  • Progressive disclosure patterns where showing all options at once would overwhelm users

  • Wizard-like interfaces that need to collect different information based on user choices

When not to use Button Section:

  • Simple selections that don't require additional form fields or contextual content

  • Navigation between completely different pages or workflows where routing is more appropriate

  • Cases where all form fields should be visible simultaneously regardless of selections

Basic Implementation

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

function MyComponent() {
  const contactOptions = [
    { label: 'Email', value: 'email' },
    { label: 'Phone', value: 'phone' },
    { label: 'Mail', value: 'mail' }
  ];

  return (
    <PwcButtonSection
      label="Contact Method"
      name="contactMethod"
      options={contactOptions}
    >
      <div slot="email">
        <PwcInput name="emailAddress" label="Email Address" />
      </div>

      <div slot="phone">
        <PwcInput name="phoneNumber" label="Phone Number" />
      </div>

      <div slot="mail">
        <PwcInput name="mailingAddress" label="Mailing Address" />
      </div>
    </PwcButtonSection>
  );
}
import { useEffect, useMemo, useRef, useState } from 'react';
import '@progress-i360/progress-web-components/button-section';
import '@progress-i360/progress-web-components/input';

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

function DeliveryOptions() {
  const sectionRef = useRef<(HTMLElement & { options?: SectionOption[]; value?: string }) | null>(null);
  const options = useMemo<SectionOption[]>(() => [
    { label: 'Standard', value: 'standard' },
    { label: 'Express', value: 'express' },
    { label: 'Pickup', value: 'pickup' }
  ], []);

  const [selection, setSelection] = useState('standard');

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

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

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

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

  useEffect(() => {
    if (sectionRef.current) {
      sectionRef.current.value = selection;
    }
  }, [selection]);

  return (
    <pwc-button-section
      ref={sectionRef}
      label="Delivery Options"
      name="delivery"
      hint="Choose your preferred delivery method"
    >
      <div slot="standard">
        <pwc-input
          name="standard-notes"
          label="Delivery Notes"
          placeholder="Optional instructions"
        ></pwc-input>
      </div>

      <div slot="express">
        <pwc-input
          name="express-time"
          label="Preferred Time"
          placeholder="e.g., Morning, Afternoon"
        ></pwc-input>
      </div>

      <div slot="pickup">
        <pwc-input
          name="pickup-location"
          label="Pickup Location"
          placeholder="Enter store code"
        ></pwc-input>
      </div>
    </pwc-button-section>
  );
}
// component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@progress-i360/progress-web-components/button-section';
import '@progress-i360/progress-web-components/input';
import '@progress-i360/progress-web-components/button';
import '@progress-i360/progress-web-components/flex';
import '@progress-i360/progress-web-components/body';

@Component({
  selector: 'button-section-demo',
  template: `
    <pwc-flex direction="column" gap="m" padding="m">
      <pwc-button-section 
        label="Preferred Contact Method" 
        [options]="contactOptions"
        [value]="selectedMethod"
        (pwc-change)="handleMethodChange($event)">

        <div slot="email">
          <pwc-flex direction="column" gap="s">
            <pwc-body content="Email Configuration" weight="semi-bold"></pwc-body>
            <pwc-body [content]="'Email notifications: ' + (emailNotifications ? 'Enabled' : 'Disabled')"></pwc-body>
            <pwc-button label="Toggle Email Notifications" variant="outline" (pwc-click)="toggleEmailNotifications()"></pwc-button>
          </pwc-flex>
        </div>

        <div slot="sms">
          <pwc-flex direction="column" gap="s">
            <pwc-body content="SMS Configuration" weight="semi-bold"></pwc-body>
            <pwc-body [content]="'SMS frequency: ' + smsFrequency"></pwc-body>
            <pwc-button label="Change Frequency" variant="outline" (pwc-click)="changeSmsFrequency()"></pwc-button>
          </pwc-flex>
        </div>

        <div slot="phone">
          <pwc-flex direction="column" gap="s">
            <pwc-body content="Phone Configuration" weight="semi-bold"></pwc-body>
            <pwc-body [content]="'Best time to call: ' + callTime"></pwc-body>
            <pwc-button label="Update Time" variant="outline" (pwc-click)="updateCallTime()"></pwc-button>
          </pwc-flex>
        </div>
      </pwc-button-section>

      <pwc-body [content]="'Selected method: ' + selectedMethod + ', Changes: ' + changeCount" color="subtle" size="xs"></pwc-body>
    </pwc-flex>
  `,
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class ButtonSectionDemo {
  selectedMethod = 'email';
  emailNotifications = true;
  smsFrequency = 'Daily';
  callTime = 'Morning';
  changeCount = 0;

  contactOptions = [
    { label: 'Email', value: 'email' },
    { label: 'SMS', value: 'sms' },
    { label: 'Phone', value: 'phone' }
  ];

  frequencies = ['Daily', 'Weekly', 'Monthly'];
  times = ['Morning', 'Afternoon', 'Evening'];

  handleMethodChange(e: Event) {
    const ce = (e as CustomEvent);
    this.selectedMethod = ce.detail;
    this.changeCount++;
  }

  toggleEmailNotifications() {
    this.emailNotifications = !this.emailNotifications;
    this.changeCount++;
  }

  changeSmsFrequency() {
    const currentIndex = this.frequencies.indexOf(this.smsFrequency);
    this.smsFrequency = this.frequencies[(currentIndex + 1) % this.frequencies.length];
    this.changeCount++;
  }

  updateCallTime() {
    const currentIndex = this.times.indexOf(this.callTime);
    this.callTime = this.times[(currentIndex + 1) % this.times.length];
    this.changeCount++;
  }
}
import '@progress-i360/progress-web-components/button-section';

const buttonSection = document.createElement('pwc-button-section');
buttonSection.setAttribute('label', 'Contact Method');
buttonSection.options = [
  { label: 'Email', value: 'email' },
  { label: 'Phone', value: 'phone' }
];

const emailContent = document.createElement('div');
emailContent.setAttribute('slot', 'email');
emailContent.textContent = 'Email configuration options';

buttonSection.appendChild(emailContent);
buttonSection.addEventListener('pwc-change', (event) => {
  console.log('Selected section:', event.detail);
});

document.body.appendChild(buttonSection);

Usage Patterns

  • Conditional Forms - Show different form fields based on user selections like account types, subscription plans, or service options

  • Multi-path Workflows - Guide users through different configuration paths based on their initial choices and requirements

  • Feature Toggles - Enable/disable specific features with related configuration options that appear only when features are active

  • Category-specific Settings - Organize related settings and preferences into logical groups that appear based on category selection

Best Practices

Content Strategy Guidelines

  • Logical Grouping - Organize options and their related content in intuitive, mutually exclusive categories

  • Clear Labeling - Use descriptive labels for both button options and the content sections they reveal

  • Progressive Complexity - Start with simple options and reveal more complex configurations as needed

  • Consistent Structure - Maintain similar field organization and layout patterns across all content sections

Performance Optimization

  • Lazy Loading - Only render content sections when they become active to improve initial load performance

  • State Caching - Cache form data across section switches to prevent user input loss

  • Efficient Updates - Minimize re-renders by updating only the active content section when selections change

  • Memory Management - Properly clean up event listeners and unused content when sections are deactivated

Integration Architecture

  • Form Validation - Implement validation rules that adapt based on the selected section and its specific requirements

  • Data Structure - Design form data models that accommodate all possible section configurations and field combinations

  • Accessibility Support - Ensure screen readers announce section changes and maintain focus management

  • Responsive Design - Adapt layout and spacing for mobile devices while maintaining usability across all sections

Common Use Cases

Account Setup

  • User registration forms with different field requirements for personal versus business accounts

  • Subscription configuration with plan-specific options and billing information

  • Profile setup wizards with role-based fields and permissions

Configuration Interfaces

  • Application settings with category-specific preference panels and advanced options

  • Integration setup forms with service-specific authentication and configuration fields

  • Feature enablement interfaces with related settings that appear when features are activated

Data Entry Forms

  • Invoice creation with different field sets for various billing types and tax requirements

  • Product configuration with variant-specific attributes and pricing options

  • Survey forms with conditional questions based on previous responses and user selections

Troubleshooting

Common Issues

Actions Not Triggering

Symptoms: Button section selections don't update content areas or fire change events

Solutions:

  • Verify slot names match the option values exactly

  • Check that pwc-change event listeners are properly bound

  • Ensure content sections are properly slotted with correct slot attributes

Actions Not Visible

Symptoms: Content sections don't appear when options are selected

Solutions:

  • Confirm slot elements are direct children of the button section component

  • Check CSS display properties aren't hiding slotted content

  • Verify option values correspond to existing slot names

Layout Issues

Symptoms: Content sections appear with incorrect spacing or alignment

Solutions:

  • Check parent container styling affecting flex layout properties

  • Ensure consistent gap and padding values across all content sections

  • Verify responsive design breakpoints don't conflict with section layouts

Icon Problems

Symptoms: Button group icons or content section indicators don't display correctly

Solutions:

  • Confirm icon system is loaded and available for button group selections

  • Check color tokens and theming for proper icon visibility

  • Ensure content section headers use consistent iconography patterns

Implementation Support

  • Form Architecture - Pattern guidance for complex form structures with conditional sections and validation

  • State Management - Best practices for handling section-specific data and user input persistence

  • Accessibility Compliance - WCAG implementation for dynamic content changes and focus management

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.