diff --git a/frontend/src/components/AMMComponents.tsx b/frontend/src/components/AMMComponents.tsx index ab6156cb..08199dd7 100644 --- a/frontend/src/components/AMMComponents.tsx +++ b/frontend/src/components/AMMComponents.tsx @@ -15,7 +15,11 @@ export function AMMPoolCard({ poolId, onSelect }: PoolCardProps) { if (!pool) return
Pool not found
; return ( -
onSelect(poolId)}> +
- + ); } diff --git a/frontend/src/components/AuditLogViewer.tsx b/frontend/src/components/AuditLogViewer.tsx index 9cfb8d1e..c08576b4 100644 --- a/frontend/src/components/AuditLogViewer.tsx +++ b/frontend/src/components/AuditLogViewer.tsx @@ -173,16 +173,37 @@ export function AuditLogViewer({ auditLogger, pageSize = 20 }: AuditLogViewerPro - - - diff --git a/frontend/src/components/ChartLegend.tsx b/frontend/src/components/ChartLegend.tsx index a896ae99..45255e55 100644 --- a/frontend/src/components/ChartLegend.tsx +++ b/frontend/src/components/ChartLegend.tsx @@ -61,6 +61,10 @@ export function TechnicalIndicatorLegend({ key={indicator.name} className="indicator-item" onClick={() => onToggleIndicator?.(indicator.name)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggleIndicator?.(indicator.name); } }} + role="button" + tabIndex={onToggleIndicator ? 0 : undefined} + aria-label={`Toggle indicator ${indicator.name}`} >
{indicator.color && ( diff --git a/frontend/src/components/DisputeCard.tsx b/frontend/src/components/DisputeCard.tsx index be52dda9..5449f6cf 100644 --- a/frontend/src/components/DisputeCard.tsx +++ b/frontend/src/components/DisputeCard.tsx @@ -46,6 +46,10 @@ export function DisputeCard({
setExpanded(!expanded)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpanded(!expanded); } }} + role="button" + tabIndex={0} + aria-expanded={expanded} >
diff --git a/frontend/src/components/DrawingToolsPanel.tsx b/frontend/src/components/DrawingToolsPanel.tsx index 91dd6de9..f86111bc 100644 --- a/frontend/src/components/DrawingToolsPanel.tsx +++ b/frontend/src/components/DrawingToolsPanel.tsx @@ -72,6 +72,10 @@ export function DrawingToolsPanel({ onClick={() => setExpandedToolId(expandedToolId === tool.id ? null : tool.id) } + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpandedToolId(expandedToolId === tool.id ? null : tool.id); } }} + role="button" + tabIndex={0} + aria-expanded={expandedToolId === tool.id} >
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpandedIndicator(expandedIndicator === indicator.name ? null : indicator.name); } }} + role="button" + tabIndex={0} + aria-expanded={expandedIndicator === indicator.name} >
( -
onSelect(category.value)} - className={`px-4 py-2 cursor-pointer hover:bg-neutral-100 dark:hover:bg-neutral-800 ${ + className={`w-full text-left px-4 py-2 cursor-pointer hover:bg-neutral-100 dark:hover:bg-neutral-800 ${ isSelected ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400' : '' }`} > {category.icon} {category.label} -
+ )); interface SortOptionItemProps { @@ -63,16 +64,17 @@ interface SortOptionItemProps { } const SortOptionItem = memo(({ option, isSelected, onSelect }: SortOptionItemProps) => ( -
onSelect(option.value)} - className={`px-4 py-2 cursor-pointer hover:bg-neutral-100 dark:hover:bg-neutral-800 ${ + className={`w-full text-left px-4 py-2 cursor-pointer hover:bg-neutral-100 dark:hover:bg-neutral-800 ${ isSelected ? 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400' : '' }`} > {option.label} -
+ )); export function MarketFilter({ diff --git a/frontend/src/components/MobileBottomSheet.tsx b/frontend/src/components/MobileBottomSheet.tsx index 5fa68ef4..b4dc1a55 100644 --- a/frontend/src/components/MobileBottomSheet.tsx +++ b/frontend/src/components/MobileBottomSheet.tsx @@ -39,6 +39,9 @@ export function MobileBottomSheet({
{ if (e.key === 'Escape') onClose(); }} + role="presentation" + tabIndex={-1} />
{ if (e.key === 'Escape') onClose(); }} + role="presentation" + tabIndex={-1} />
{ if (e.key === 'Escape') onCancel(); }} + role="presentation" + tabIndex={-1} /> {/* Dialog */} diff --git a/frontend/src/components/OracleCard.tsx b/frontend/src/components/OracleCard.tsx index 08024066..4fd6adcf 100644 --- a/frontend/src/components/OracleCard.tsx +++ b/frontend/src/components/OracleCard.tsx @@ -30,6 +30,10 @@ const OracleCardBase = ({ oracle, onSelect, compact = false }: OracleCardProps)
onSelect?.(oracle.address)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect?.(oracle.address); } }} + role="button" + tabIndex={onSelect ? 0 : undefined} + aria-label={`Select oracle ${oracle.address}`} >
@@ -50,6 +54,10 @@ const OracleCardBase = ({ oracle, onSelect, compact = false }: OracleCardProps)
onSelect?.(oracle.address)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect?.(oracle.address); } }} + role="button" + tabIndex={onSelect ? 0 : undefined} + aria-label={`Select oracle ${oracle.address}`} > {/* Header */}
diff --git a/frontend/src/components/OracleHealthDashboard.tsx b/frontend/src/components/OracleHealthDashboard.tsx index c3ea161b..0df47aeb 100644 --- a/frontend/src/components/OracleHealthDashboard.tsx +++ b/frontend/src/components/OracleHealthDashboard.tsx @@ -140,6 +140,10 @@ export const OracleHealthDashboard: React.FC = ({ key={stat.provider} className={`border p-4 rounded-lg cursor-pointer transition ${getStatusColor(stat)}`} onClick={() => setSelectedProvider(stat.provider)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setSelectedProvider(stat.provider); } }} + role="button" + tabIndex={0} + aria-label={`View details for oracle provider ${stat.provider}`} >

{stat.provider}

diff --git a/frontend/src/components/ProposalCard.tsx b/frontend/src/components/ProposalCard.tsx index 3c864cfe..9f4681a6 100644 --- a/frontend/src/components/ProposalCard.tsx +++ b/frontend/src/components/ProposalCard.tsx @@ -53,6 +53,10 @@ export function ProposalCard({ return (
onSelect(proposal)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onSelect(proposal); } }} + role="button" + tabIndex={0} + aria-label={`View proposal: ${proposal.title}`} style={{ backgroundColor: '#0A0A0A', border: '1px solid #1F1F1F', diff --git a/frontend/src/components/ResponsiveChart.tsx b/frontend/src/components/ResponsiveChart.tsx index 5e897931..d4358c1f 100644 --- a/frontend/src/components/ResponsiveChart.tsx +++ b/frontend/src/components/ResponsiveChart.tsx @@ -191,14 +191,15 @@ export function CompactIndicatorPanel({
{indicators.slice(0, 3).map(indicator => ( -
onShowDetails?.(indicator.name)} > {indicator.name} {indicator.value.toFixed(2)} -
+ ))} {indicators.length > 3 && (
diff --git a/frontend/src/components/RoleManagementDashboard.tsx b/frontend/src/components/RoleManagementDashboard.tsx index 6a2e0a85..8752ff0c 100644 --- a/frontend/src/components/RoleManagementDashboard.tsx +++ b/frontend/src/components/RoleManagementDashboard.tsx @@ -65,6 +65,10 @@ export function RoleManagementDashboard({ key={role.id} className={`role-card ${selectedRoleId === role.id ? 'selected' : ''}`} onClick={() => handleRoleSelect(role.id)} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleRoleSelect(role.id); } }} + role="button" + tabIndex={0} + aria-pressed={selectedRoleId === role.id} >

{role.name}

diff --git a/frontend/src/components/WizardProgress.tsx b/frontend/src/components/WizardProgress.tsx index eaf54a68..07c4b9f3 100644 --- a/frontend/src/components/WizardProgress.tsx +++ b/frontend/src/components/WizardProgress.tsx @@ -108,8 +108,16 @@ export function WizardProgress({ key={index} style={stepStyle(index)} onClick={() => onStepClick?.(index)} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + onStepClick?.(index); + } + }} role="button" - tabIndex={0} + tabIndex={onStepClick ? 0 : -1} + aria-label={`Step ${index + 1}: ${label}`} + aria-current={index === currentStep ? 'step' : undefined} >
{index < currentStep ? '✓' : index + 1} diff --git a/frontend/src/examples/RBACExamples.tsx b/frontend/src/examples/RBACExamples.tsx index 4b2e0935..520b51a0 100644 --- a/frontend/src/examples/RBACExamples.tsx +++ b/frontend/src/examples/RBACExamples.tsx @@ -118,7 +118,15 @@ export function APIServiceExample() { } } - return
performOperation()}>Perform Operation
; + return ( + + ); } export function ResourceAccessExample() { @@ -183,5 +191,13 @@ export function ValidationExample() { }; } - return
validateSetup()}>Validate System
; + return ( + + ); } diff --git a/frontend/src/pages/GovernancePage.tsx b/frontend/src/pages/GovernancePage.tsx index 9a64c581..8c179416 100644 --- a/frontend/src/pages/GovernancePage.tsx +++ b/frontend/src/pages/GovernancePage.tsx @@ -721,8 +721,19 @@ export function GovernancePage() { {/* Proposal Detail Modal */} {selectedProposal && ( -
setSelectedProposal(null)}> -
e.stopPropagation()}> +
setSelectedProposal(null)} + onKeyDown={(e) => { if (e.key === 'Escape') setSelectedProposal(null); }} + role="presentation" + > +
e.stopPropagation()} + role="dialog" + aria-modal="true" + aria-label={selectedProposal.title} + > @@ -906,8 +917,19 @@ export function GovernancePage() { {/* Delegate Modal */} {showDelegateModal && ( -
setShowDelegateModal(false)}> -
e.stopPropagation()}> +
setShowDelegateModal(false)} + onKeyDown={(e) => { if (e.key === 'Escape') setShowDelegateModal(false); }} + role="presentation" + > +
e.stopPropagation()} + role="dialog" + aria-modal="true" + aria-label="Delegate Voting Power" + >
handleSort('timestamp')} className="sortable"> + handleSort('timestamp')} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleSort('timestamp'); } }} + className="sortable" + tabIndex={0} + role="columnheader" + aria-sort={sortBy === 'timestamp' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} + > Timestamp {sortBy === 'timestamp' && (sortOrder === 'asc' ? '↑' : '↓')} User ID handleSort('action')} className="sortable"> + handleSort('action')} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleSort('action'); } }} + className="sortable" + tabIndex={0} + role="columnheader" + aria-sort={sortBy === 'action' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} + > Action {sortBy === 'action' && (sortOrder === 'asc' ? '↑' : '↓')} Resource Resource ID handleSort('status')} className="sortable"> + handleSort('status')} + onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); handleSort('status'); } }} + className="sortable" + tabIndex={0} + role="columnheader" + aria-sort={sortBy === 'status' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} + > Status {sortBy === 'status' && (sortOrder === 'asc' ? '↑' : '↓')} Details