diff --git a/components/dashboard/ContributeDialog.tsx b/components/dashboard/ContributeDialog.tsx index d04173c..fa01f69 100644 --- a/components/dashboard/ContributeDialog.tsx +++ b/components/dashboard/ContributeDialog.tsx @@ -1,5 +1,6 @@ "use client"; +import React from "react"; import { GitBranch, Star, ExternalLink, Code2 } from "lucide-react"; import { Dialog, @@ -40,7 +41,7 @@ export function ContributeDialog({
{/* Issue label */} -
+
High Complexity Issue Stellar Drips Eligible
diff --git a/components/dashboard/EventFeedTable.test.tsx b/components/dashboard/EventFeedTable.test.tsx new file mode 100644 index 0000000..240dd14 --- /dev/null +++ b/components/dashboard/EventFeedTable.test.tsx @@ -0,0 +1,71 @@ +import React from "react"; +import { render } from "@testing-library/react"; +import { describe, it, expect, vi } from "vitest"; +import { axe } from "vitest-axe"; +import { EventFeedTable } from "./EventFeedTable"; + +vi.mock("react-syntax-highlighter", () => ({ + Prism: () =>
+})); + +describe("EventFeedTable Accessibility", () => { + it("should have no accessibility violations", async () => { + const mockEvents = [ + { + status: "translated" as const, + description: "Transferred 100 XLM to Bob", + eventType: "transfer", + raw: { + id: "1", + type: "contract", + ledger: 123456, + ledgerClosedAt: "2026-06-17T17:11:21Z", + contractId: "CAAA...D2KM", + pagingToken: "token", + txHash: "hash123", + topics: ["topic1"], + data: "data123", + timestamp: Date.now() / 1000 - 3600, + }, + }, + { + status: "cryptic" as const, + description: "", + eventType: "", + raw: { + id: "2", + type: "contract", + ledger: 123456, + ledgerClosedAt: "2026-06-17T17:11:21Z", + contractId: "CAAA...D2KM", + pagingToken: "token", + txHash: "hash456", + topics: ["topic2"], + data: "data456", + timestamp: Date.now() / 1000 - 7200, + }, + }, + ]; + + const columns = { + status: true, + time: true, + description: true, + contract: true, + actions: true, + }; + + const { container } = render( + + ); + + const results = await axe(container); + expect(results).toHaveNoViolations(); + }); +}); diff --git a/components/dashboard/EventFeedTable.tsx b/components/dashboard/EventFeedTable.tsx index ffeb731..e286929 100644 --- a/components/dashboard/EventFeedTable.tsx +++ b/components/dashboard/EventFeedTable.tsx @@ -47,7 +47,8 @@ function StatusBadge({ status }: { status: TranslatedEvent["status"] }): React.J if (status === "translated") { return ( - + ); @@ -55,14 +56,16 @@ function StatusBadge({ status }: { status: TranslatedEvent["status"] }): React.J if (status === "pending") { return ( - + ); } return ( - + ); @@ -97,6 +100,22 @@ export function EventFeedTable({ /** txHash of the event whose execution DAG is being viewed, or null. */ const [dagTxHash, setDagTxHash] = useState(null); + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.target instanceof HTMLElement && e.target.tagName === "TR") { + const currentRow = e.target as HTMLTableRowElement; + + if (e.key === "ArrowDown" || e.key === "j" || e.key === "J") { + e.preventDefault(); + const nextRow = currentRow.nextElementSibling as HTMLTableRowElement; + if (nextRow) nextRow.focus(); + } else if (e.key === "ArrowUp" || e.key === "k" || e.key === "K") { + e.preventDefault(); + const prevRow = currentRow.previousElementSibling as HTMLTableRowElement; + if (prevRow) prevRow.focus(); + } + } + }; + const cellPadding = density === "compact" ? "py-1.5" : "py-3"; const visibleColCount = Object.values(columns).filter(Boolean).length; @@ -173,7 +192,7 @@ export function EventFeedTable({ )} - + {isLoading ? Array.from({ length: 5 }).map(function (_, i) { return ; @@ -184,7 +203,9 @@ export function EventFeedTable({ return ( - {copied ? : } + + {copied ? "Copied" : ""} + + {copied ?