Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions frontend/src/components/AMMComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { AMMPool, SwapQuote } from '@/types/amm';

Check failure on line 2 in frontend/src/components/AMMComponents.tsx

View workflow job for this annotation

GitHub Actions / lint-performance

'SwapQuote' is defined but never used
import { useAMMPool, useSwapQuote } from '@/hooks/useAMM';

interface PoolCardProps {
Expand All @@ -15,7 +15,11 @@
if (!pool) return <div className="p-4">Pool not found</div>;

return (
<div className="border rounded-lg p-4 cursor-pointer hover:bg-gray-50" onClick={() => onSelect(poolId)}>
<button
type="button"
className="border rounded-lg p-4 cursor-pointer hover:bg-gray-50 w-full text-left"
onClick={() => onSelect(poolId)}
>
<div className="flex justify-between mb-2">
<span className="font-semibold">
{pool.tokenA} / {pool.tokenB}
Expand All @@ -32,7 +36,7 @@
<div className="font-mono">{Number(pool.reserveB) / 1e12}</div>
</div>
</div>
</div>
</button>
);
}

Expand Down
27 changes: 24 additions & 3 deletions frontend/src/components/AuditLogViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -173,16 +173,37 @@ export function AuditLogViewer({ auditLogger, pageSize = 20 }: AuditLogViewerPro
<table className="logs-table">
<thead>
<tr>
<th onClick={() => handleSort('timestamp')} className="sortable">
<th
onClick={() => 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' ? '↑' : '↓')}
</th>
<th>User ID</th>
<th onClick={() => handleSort('action')} className="sortable">
<th
onClick={() => 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' ? '↑' : '↓')}
</th>
<th>Resource</th>
<th>Resource ID</th>
<th onClick={() => handleSort('status')} className="sortable">
<th
onClick={() => 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' ? '↑' : '↓')}
</th>
<th>Details</th>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/ChartLegend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}`}
>
<div className="indicator-header">
{indicator.color && (
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/DisputeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ export function DisputeCard({
<div
className="p-4 cursor-pointer hover:bg-gray-700/30 transition-colors"
onClick={() => setExpanded(!expanded)}
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpanded(!expanded); } }}
role="button"
tabIndex={0}
aria-expanded={expanded}
>
<div className="flex items-center justify-between">
<div className="flex items-center gap-3">
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/DrawingToolsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
>
<div className="tool-info">
<input
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/IndicatorPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ export function IndicatorPanel({
expandedIndicator === indicator.name ? null : indicator.name
)
}
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); setExpandedIndicator(expandedIndicator === indicator.name ? null : indicator.name); } }}
role="button"
tabIndex={0}
aria-expanded={expandedIndicator === indicator.name}
>
<div className="indicator-title">
<input
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/components/MarketFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,18 @@ interface CategoryOptionProps {
}

const CategoryOption = memo(({ category, isSelected, onSelect }: CategoryOptionProps) => (
<div
<button
type="button"
role="option"
aria-selected={isSelected}
onClick={() => 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' : ''
}`}
>
<span className="mr-2">{category.icon}</span>
{category.label}
</div>
</button>
));

interface SortOptionItemProps {
Expand All @@ -63,16 +64,17 @@ interface SortOptionItemProps {
}

const SortOptionItem = memo(({ option, isSelected, onSelect }: SortOptionItemProps) => (
<div
<button
type="button"
role="option"
aria-selected={isSelected}
onClick={() => 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}
</div>
</button>
));

export function MarketFilter({
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MobileBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ export function MobileBottomSheet({
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={onClose}
onKeyDown={(e) => { if (e.key === 'Escape') onClose(); }}
role="presentation"
tabIndex={-1}
/>

<div
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/MobileModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export function MobileModal({
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={onClose}
onKeyDown={(e) => { if (e.key === 'Escape') onClose(); }}
role="presentation"
tabIndex={-1}
/>

<div
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/components/NetworkSwitchDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ export function NetworkSwitchDialog({
<div
className="absolute inset-0 bg-black/70 backdrop-blur-sm"
onClick={onCancel}
onKeyDown={(e) => { if (e.key === 'Escape') onCancel(); }}
role="presentation"
tabIndex={-1}
/>

{/* Dialog */}
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/components/OracleCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const OracleCardBase = ({ oracle, onSelect, compact = false }: OracleCardProps)
<div
className="flex items-center justify-between p-3 bg-gray-800/50 rounded-lg border border-gray-700 hover:border-purple-500/50 transition-colors cursor-pointer"
onClick={() => 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}`}
>
<div className="flex items-center gap-3">
<div className={`w-2 h-2 rounded-full ${oracle.isRegistered ? 'bg-green-500' : 'bg-gray-500'}`} />
Expand All @@ -50,6 +54,10 @@ const OracleCardBase = ({ oracle, onSelect, compact = false }: OracleCardProps)
<div
className="bg-gray-800/50 rounded-xl p-5 border border-gray-700 hover:border-purple-500/50 transition-colors cursor-pointer"
onClick={() => 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 */}
<div className="flex items-start justify-between mb-4">
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/OracleHealthDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ export const OracleHealthDashboard: React.FC<HealthDashboardProps> = ({
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}`}
>
<div className="flex items-center justify-between mb-3">
<h3 className="font-semibold text-gray-900">{stat.provider}</h3>
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/ProposalCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export function ProposalCard({
return (
<div
onClick={() => 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',
Expand Down
5 changes: 3 additions & 2 deletions frontend/src/components/ResponsiveChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,14 +191,15 @@ export function CompactIndicatorPanel({
<div className="compact-indicator-panel">
<div className="indicators-summary">
{indicators.slice(0, 3).map(indicator => (
<div
<button
key={indicator.name}
type="button"
className="indicator-badge"
onClick={() => onShowDetails?.(indicator.name)}
>
<span className="name">{indicator.name}</span>
<span className="value">{indicator.value.toFixed(2)}</span>
</div>
</button>
))}
{indicators.length > 3 && (
<div className="more-indicators">
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/RoleManagementDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
>
<div className="role-header">
<h4>{role.name}</h4>
Expand Down
10 changes: 9 additions & 1 deletion frontend/src/components/WizardProgress.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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}
>
<div style={stepCircleStyle(index)}>
{index < currentStep ? '✓' : index + 1}
Expand Down
20 changes: 18 additions & 2 deletions frontend/src/examples/RBACExamples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,15 @@ export function APIServiceExample() {
}
}

return <div onClick={() => performOperation()}>Perform Operation</div>;
return (
<button
type="button"
onClick={() => performOperation()}
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}
>
Perform Operation
</button>
);
}

export function ResourceAccessExample() {
Expand Down Expand Up @@ -183,5 +191,13 @@ export function ValidationExample() {
};
}

return <div onClick={() => validateSetup()}>Validate System</div>;
return (
<button
type="button"
onClick={() => validateSetup()}
style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 0 }}
>
Validate System
</button>
);
}
30 changes: 26 additions & 4 deletions frontend/src/pages/GovernancePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -721,8 +721,19 @@ export function GovernancePage() {

{/* Proposal Detail Modal */}
{selectedProposal && (
<div style={modalOverlayStyle} onClick={() => setSelectedProposal(null)}>
<div style={{ ...modalStyle, position: 'relative' }} onClick={e => e.stopPropagation()}>
<div
style={modalOverlayStyle}
onClick={() => setSelectedProposal(null)}
onKeyDown={(e) => { if (e.key === 'Escape') setSelectedProposal(null); }}
role="presentation"
>
<div
style={{ ...modalStyle, position: 'relative' }}
onClick={e => e.stopPropagation()}
role="dialog"
aria-modal="true"
aria-label={selectedProposal.title}
>
<button style={closeButtonStyle} onClick={() => setSelectedProposal(null)}>
×
</button>
Expand Down Expand Up @@ -906,8 +917,19 @@ export function GovernancePage() {

{/* Delegate Modal */}
{showDelegateModal && (
<div style={modalOverlayStyle} onClick={() => setShowDelegateModal(false)}>
<div style={{ ...modalStyle, position: 'relative', maxWidth: '500px' }} onClick={e => e.stopPropagation()}>
<div
style={modalOverlayStyle}
onClick={() => setShowDelegateModal(false)}
onKeyDown={(e) => { if (e.key === 'Escape') setShowDelegateModal(false); }}
role="presentation"
>
<div
style={{ ...modalStyle, position: 'relative', maxWidth: '500px' }}
onClick={e => e.stopPropagation()}
role="dialog"
aria-modal="true"
aria-label="Delegate Voting Power"
>
<button style={closeButtonStyle} onClick={() => setShowDelegateModal(false)}>
×
</button>
Expand Down
Loading