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.