Pending Review
Pending Review from User Experience (UX)
Checkbox Component
Overview
The PWC Checkbox component provides a binary selection interface for forms and user preferences. Built with Lit web components, it offers full accessibility support, validation integration, and consistent visual feedback for checked and unchecked states.
Core Capabilities
-
Binary Selection - True/false selection with clear visual indication of checked and unchecked states
-
Form Integration - Native form field behavior with validation, required state, and error message display
-
Accessibility Focus - Full keyboard navigation with proper ARIA attributes and screen reader compatibility
-
Visual Feedback - Checkmark icon display with inverse color styling for selected state indication
-
Loading States - Skeleton loading animation during form loading and async operations
-
Validation Support - Built-in validation with required field checking and custom validation message display
When to use Checkbox:
-
Binary choices where users need to opt-in or opt-out of specific options or features
-
Terms and conditions acceptance, newsletter subscriptions, and preference settings
-
Multi-selection scenarios where users can choose multiple independent options
-
Form fields requiring explicit user confirmation before proceeding with actions
When not to use Checkbox:
-
Single-choice selections where only one option should be active - use radio buttons instead
-
Toggle switches for immediate state changes that don't require form submission
-
Navigation or action triggers that should use buttons or links for better semantics
Basic Implementation
import { PwcCheckbox } from "@progress-i360/pwc-react";
function MyComponent() {
const handleAcceptTerms = (event) => {
console.log('Terms accepted:', event.detail);
};
return (
<>
<PwcCheckbox
label="I accept the terms and conditions"
name="acceptTerms"
required
onChange={handleAcceptTerms}
/>
<PwcCheckbox
label="Subscribe to newsletter"
name="newsletter"
hint="Receive updates and promotions"
/>
</>
);
}
import { useEffect, useRef, useState } from 'react';
import '@progress-i360/progress-web-components/body';
import '@progress-i360/progress-web-components/checkbox';
type CheckboxElement = HTMLElement & { value?: boolean; disabled?: boolean };
type PreferenceState = { notifications: boolean; terms: boolean; newsletter: boolean };
function PreferenceSettings() {
const notificationsRef = useRef<CheckboxElement | null>(null);
const termsRef = useRef<CheckboxElement | null>(null);
const newsletterRef = useRef<CheckboxElement | null>(null);
const [preferences, setPreferences] = useState<PreferenceState>({
notifications: false,
terms: false,
newsletter: false
});
useEffect(() => {
const notificationsElement = notificationsRef.current;
const termsElement = termsRef.current;
const newsletterElement = newsletterRef.current;
if (!notificationsElement || !termsElement || !newsletterElement) {
return;
}
const handleNotifications = (event: Event) => {
const detail = (event as CustomEvent<boolean>).detail;
setPreferences((prev) => {
const next = { ...prev, notifications: detail };
if (!detail) {
next.newsletter = false;
}
return next;
});
};
const handleTerms = (event: Event) => {
const detail = (event as CustomEvent<boolean>).detail;
setPreferences((prev) => ({ ...prev, terms: detail }));
};
const handleNewsletter = (event: Event) => {
const detail = (event as CustomEvent<boolean>).detail;
setPreferences((prev) => ({ ...prev, newsletter: detail }));
};
notificationsElement.addEventListener('pwc-change', handleNotifications);
termsElement.addEventListener('pwc-change', handleTerms);
newsletterElement.addEventListener('pwc-change', handleNewsletter);
return () => {
notificationsElement.removeEventListener('pwc-change', handleNotifications);
termsElement.removeEventListener('pwc-change', handleTerms);
newsletterElement.removeEventListener('pwc-change', handleNewsletter);
};
}, []);
useEffect(() => {
if (notificationsRef.current) {
notificationsRef.current.value = preferences.notifications;
}
if (termsRef.current) {
termsRef.current.value = preferences.terms;
}
if (newsletterRef.current) {
newsletterRef.current.value = preferences.newsletter;
newsletterRef.current.disabled = !preferences.notifications;
}
}, [preferences]);
const selectedCount = Object.values(preferences).filter(Boolean).length;
return (
<div>
<pwc-checkbox
ref={notificationsRef}
label="Enable notifications"
name="notifications"
></pwc-checkbox>
<pwc-checkbox
ref={termsRef}
label="Accept terms and conditions"
name="terms"
required
></pwc-checkbox>
<pwc-checkbox
ref={newsletterRef}
label="Subscribe to newsletter"
name="newsletter"
hint="Receive updates and promotions"
></pwc-checkbox>
<pwc-body
content={`Selected: ${selectedCount}/3`}
color="subtle"
size="xs"
></pwc-body>
</div>
);
}
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/checkbox";
import "@progress-i360/progress-web-components/flex";
import "@progress-i360/progress-web-components/heading";
@Component({
selector: 'checkbox-demo',
template: `
<pwc-flex direction="column" gap="m" padding="m">
<pwc-heading content="User Preferences" size="l"></pwc-heading>
<pwc-flex direction="column" gap="s">
<pwc-checkbox
label="Enable notifications"
[value]="notificationsEnabled"
(pwc-change)="handleNotificationChange($event)">
</pwc-checkbox>
<pwc-checkbox
label="Accept terms and conditions"
[value]="termsAccepted"
[required]="true"
(pwc-change)="handleTermsChange($event)">
</pwc-checkbox>
<pwc-checkbox
label="Subscribe to newsletter"
[value]="newsletterSubscribed"
[disabled]="!notificationsEnabled"
(pwc-change)="handleNewsletterChange($event)">
</pwc-checkbox>
</pwc-flex>
<pwc-flex gap="s">
<pwc-button label="Select All" variant="outline" (pwc-click)="selectAll()"></pwc-button>
<pwc-button label="Clear All" variant="clear" (pwc-click)="clearAll()"></pwc-button>
<pwc-button label="Submit" variant="primary" [disabled]="!canSubmit()" (pwc-click)="submit()"></pwc-button>
</pwc-flex>
<pwc-body [content]="getStatusText()" color="subtle" size="xs"></pwc-body>
</pwc-flex>
`,
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class CheckboxDemo {
notificationsEnabled = false;
termsAccepted = false;
newsletterSubscribed = false;
submissionCount = 0;
handleNotificationChange(e: Event) {
const ce = (e as CustomEvent);
this.notificationsEnabled = ce.detail;
// Auto-disable newsletter if notifications are disabled
if (!this.notificationsEnabled) {
this.newsletterSubscribed = false;
}
}
handleTermsChange(e: Event) {
const ce = (e as CustomEvent);
this.termsAccepted = ce.detail;
}
handleNewsletterChange(e: Event) {
const ce = (e as CustomEvent);
this.newsletterSubscribed = ce.detail;
}
selectAll() {
this.notificationsEnabled = true;
this.termsAccepted = true;
this.newsletterSubscribed = true;
}
clearAll() {
this.notificationsEnabled = false;
this.termsAccepted = false;
this.newsletterSubscribed = false;
}
canSubmit() {
return this.termsAccepted; // Terms are required
}
submit() {
if (this.canSubmit()) {
this.submissionCount++;
}
}
getStatusText() {
const selected = [this.notificationsEnabled, this.termsAccepted, this.newsletterSubscribed].filter(Boolean).length;
return `Selected: ${selected}/3, Submissions: ${this.submissionCount}, Valid: ${this.canSubmit() ? 'Yes' : 'No'}`;
}
}
import '@progress-i360/progress-web-components/checkbox';
const checkbox = document.createElement('pwc-checkbox');
checkbox.setAttribute('label', 'Accept terms and conditions');
checkbox.setAttribute('name', 'terms');
checkbox.required = true;
checkbox.addEventListener('pwc-change', (event) => {
console.log('Checkbox checked:', event.detail);
});
document.body.appendChild(checkbox);
Usage Patterns
-
Form Agreements - Terms of service, privacy policy acceptance, and legal compliance checkboxes with required validation
-
User Preferences - Settings and configuration options that users can enable or disable independently
-
Multi-Selection Lists - Allow users to select multiple items from a list where each option is independent
-
Feature Toggles - Enable or disable specific application features and functionality within forms and settings
Best Practices
Content Strategy Guidelines
-
Clear Labels - Use descriptive, action-oriented labels that clearly state what the user is agreeing to or enabling
-
Helpful Hints - Provide additional context through hint text to clarify the impact of checkbox selections
-
Logical Grouping - Group related checkboxes together and use consistent labeling patterns
-
Required Indicators - Clearly mark required checkboxes and explain why they are necessary
Performance Optimization
-
Event Handling - Use efficient event delegation patterns for multiple checkboxes to reduce memory usage
-
State Management - Implement proper state management to avoid unnecessary re-renders on checkbox changes
-
Validation Timing - Validate checkboxes on appropriate events (blur, change) rather than on every input
-
Loading States - Show skeleton loaders during form initialization to improve perceived performance
Integration Architecture
-
Form Context - Leverage form integration for validation, submission handling, and error state management
-
Accessibility Standards - Ensure proper keyboard navigation, focus management, and screen reader support
-
Design System - Use consistent spacing, colors, and typography tokens from the design system
-
Data Binding - Implement efficient two-way data binding patterns for checkbox state management
Common Use Cases
Legal Compliance
-
Terms of service acceptance for account registration and service usage
-
Privacy policy acknowledgment for data collection and processing consent
-
Cookie policy acceptance for website tracking and analytics permissions
User Preferences
-
Notification settings for emails, push notifications, and in-app alerts
-
Display preferences for themes, language selection, and interface customization
-
Privacy settings for profile visibility, data sharing, and communication preferences
Feature Configuration
-
Optional feature enablement for advanced functionality and beta features
-
Integration settings for third-party services and external application connections
-
Backup and sync preferences for data storage and cross-device synchronization
Troubleshooting
Common Issues
Actions Not Triggering
Symptoms: Checkbox clicks don't update values or fire change events
Solutions:
-
Verify pwc-change event listeners are properly attached to checkbox elements
-
Check if checkbox is disabled or form is in loading state preventing interactions
-
Ensure proper event propagation and that parent elements aren't intercepting events
Actions Not Visible
Symptoms: Checkboxes don't appear or visual states don't update correctly
Solutions:
-
Confirm checkbox component is imported and registered correctly in the application
-
Check CSS styling and z-index values that might be hiding checkbox elements
-
Verify design tokens are loaded for proper background and border colors
Layout Issues
Symptoms: Checkboxes appear misaligned or with incorrect spacing relative to labels
Solutions:
-
Check parent container flex properties and alignment settings
-
Ensure proper margin and padding values are applied consistently
-
Verify label container styling doesn't conflict with checkbox positioning
Icon Problems
Symptoms: Checkmark icons don't appear in checked state or display with wrong colors
Solutions:
-
Confirm icon system is properly loaded and checkmark icon is available
-
Check color token values for inverse and disabled icon states
-
Verify checkbox checked state styling applies proper background colors
Implementation Support
-
Form Integration - Pattern guidance for validation, error handling, and submission workflows with checkbox fields
-
Accessibility Compliance - WCAG implementation strategies and screen reader optimization for checkbox interactions
-
Design System Integration - Token usage, theming, and consistent styling across checkbox implementations
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.