import { forwardRef, useState } from 'react' import Stepper from '../Stepper' import { StepperType, StepState } from '../types' import { stepperAccessibilityReport } from './StepperAccessibilityReport' import { generateAccessibilityReport, downloadReport, getMimeType, getFileExtension, type ReportFormat, } from '../../shared/accessibility/reportGenerator' import { Download as DownloadIcon } from 'lucide-react' import { Button, ButtonType, ButtonSize } from '../../Button' export type StepperAccessibilityProps = { className?: string } const StepperAccessibility = forwardRef< HTMLDivElement, StepperAccessibilityProps >(({ className }, ref) => { const [selectedFormat, setSelectedFormat] = useState('markdown') const [includeTestResults, setIncludeTestResults] = useState(true) const [includeRecommendations, setIncludeRecommendations] = useState(true) const [reportHtmlContent, setReportHtmlContent] = useState( null ) const [showFullReport, setShowFullReport] = useState(false) const handleDownload = () => { try { const content = generateAccessibilityReport( stepperAccessibilityReport, { format: selectedFormat, includeTestResults, includeRecommendations, } ) const filename = `stepper-accessibility-report-${stepperAccessibilityReport.reportDate}.${getFileExtension(selectedFormat)}` const mimeType = getMimeType(selectedFormat) downloadReport(content, filename, mimeType) } catch (error) { console.error('Error generating report:', error) alert('Failed to generate report. Please try again.') } } const handleViewReport = () => { try { const htmlContent = generateAccessibilityReport( stepperAccessibilityReport, { format: 'html', includeTestResults, includeRecommendations, } ) setReportHtmlContent(htmlContent) setShowFullReport(true) } catch (error) { console.error('Error generating report:', error) alert('Failed to generate report. Please try again.') } } const report = stepperAccessibilityReport const compliantCount = report.criteria.filter( (c) => c.status === 'compliant' ).length const nonCompliantCount = report.criteria.filter( (c) => c.status === 'non-compliant' ).length const unsureCount = report.criteria.filter( (c) => c.status === 'unsure' ).length const totalApplicable = report.criteria.filter( (c) => c.status !== 'not-applicable' ).length const complianceRate = totalApplicable > 0 ? Math.round((compliantCount / totalApplicable) * 100) : 0 // Example step data const horizontalSteps = [ { id: 1, title: 'Step 1', status: StepState.COMPLETED, }, { id: 2, title: 'Step 2', status: StepState.CURRENT, }, { id: 3, title: 'Step 3', status: StepState.PENDING, }, ] const verticalSteps = [ { id: 1, title: 'Step 1', status: StepState.COMPLETED, description: 'First step description', }, { id: 2, title: 'Step 2', status: StepState.CURRENT, description: 'Second step description', }, { id: 3, title: 'Step 3', status: StepState.PENDING, }, ] const stepsWithSubsteps = [ { id: 1, title: 'Step 1', status: StepState.COMPLETED, substeps: [ { id: 1, title: 'Substep 1.1' }, { id: 2, title: 'Substep 1.2' }, ], isExpanded: true, }, { id: 2, title: 'Step 2', status: StepState.CURRENT, }, ] const clickableSteps = [ { id: 1, title: 'Step 1', status: StepState.COMPLETED, }, { id: 2, title: 'Step 2', status: StepState.CURRENT, }, { id: 3, title: 'Step 3', status: StepState.PENDING, }, ] return (

Stepper Component Accessibility

WCAG {report.wcagVersion} • {report.conformanceLevel} • {report.reportDate}
Evaluates: WCAG 2.0, 2.1, 2.2

Download Report

{compliantCount}
Compliant ✅
Verified & tested
{nonCompliantCount}
Non-Compliant ❌
Issues found
{unsureCount}
Unsure ⚠️
Needs verification
{complianceRate}%
Compliance Rate
Based on verified items
{unsureCount > 0 && (
⚠️

Manual Verification Required

{unsureCount} criterion/criteria marked as "unsure" require manual verification. These items need testing with contrast checkers, screen readers, or depend on application context.

)}

Summary

{report.summary}

Quick Stats

Total Criteria: {report.criteria.length}
Level A: { report.criteria.filter( (c) => c.level === 'A' ).length }
Level AA: { report.criteria.filter( (c) => c.level === 'AA' ).length }
Level AAA: { report.criteria.filter( (c) => c.level === 'AAA' ).length }
{showFullReport && reportHtmlContent && (

Full Accessibility Report

)}

WCAG Criteria Breakdown

{report.criteria.map((criterion) => (
{criterion.id}:{' '} {criterion.title} Level {criterion.level} {criterion.status === 'compliant' ? '✅ Compliant' : criterion.status === 'non-compliant' ? '❌ Non-Compliant' : criterion.status === 'unsure' ? '⚠️ Unsure' : 'N/A'}

{criterion.description}

Implementation:

{criterion.implementation}

{criterion.testResults && (
Test Results:

{criterion.testResults}

)} {criterion.notes && (
Notes:

{criterion.notes}

)}
))}

Strengths

    {report.strengths.map((strength, index) => (
  • {strength}
  • ))}
{report.recommendations.length > 0 && (

Recommendations

    {report.recommendations.map( (recommendation, index) => (
  • {recommendation}
  • ) )}
)}

Component Examples

Horizontal Stepper

Basic horizontal stepper with three steps showing completed, current, and pending states.

Vertical Stepper

Vertical stepper with step descriptions and proper semantic structure.

Stepper with Substeps

Vertical stepper with expandable substeps. Substeps are properly grouped and accessible via keyboard navigation.

Clickable Stepper

{ console.log('Step clicked:', index) }} stepperType={StepperType.HORIZONTAL} />

Clickable horizontal stepper. Steps can be activated via mouse click, Enter, or Space key. Arrow keys navigate between steps.

Keyboard Navigation

Horizontal Stepper:
  • ArrowLeft/ArrowRight: Navigate between steps
  • Home: Navigate to first step
  • End: Navigate to last step
  • Tab: Navigate to interactive elements
  • Enter/Space: Activate step (when clickable)
Vertical Stepper:
  • ArrowUp/ArrowDown: Navigate between steps
  • ArrowRight: Expand substeps or move into substeps
  • ArrowLeft: Move back to parent step from substeps
  • Home: Navigate to first step
  • End: Navigate to last step
  • Tab: Navigate to interactive elements
  • Enter/Space: Activate step or substep (when clickable)
) }) StepperAccessibility.displayName = 'StepperAccessibility' export default StepperAccessibility