From 1144e89cb17c5ab9926ae317116a7a1448c7dcd9 Mon Sep 17 00:00:00 2001 From: ROHAN <123131rkorohan@gmail.com> Date: Sat, 30 May 2026 10:28:01 +0530 Subject: [PATCH] feat: improve accessibility, modal stories and UI balance --- frontend/src/app/page.tsx | 8 +- .../components/marketplace/OrderListTable.tsx | 13 +- .../components/swap/SwapModals.stories.tsx | 137 ++++++++++++++++++ .../transactions/TransactionDetailModal.tsx | 8 +- frontend/src/components/ui/button.tsx | 4 +- 5 files changed, 158 insertions(+), 12 deletions(-) create mode 100644 frontend/src/components/swap/SwapModals.stories.tsx diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index ff9d2bed..791c3139 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -141,7 +141,7 @@ export default function Home() { function SwapPreviewPanel() { return ( - +
@@ -156,8 +156,8 @@ function SwapPreviewPanel() {

From

-
- XLM +
+ XLM

Stellar

@@ -238,7 +238,7 @@ function FeatureCard({ return (
{icon} diff --git a/frontend/src/components/marketplace/OrderListTable.tsx b/frontend/src/components/marketplace/OrderListTable.tsx index cc770cd9..5b29afd3 100644 --- a/frontend/src/components/marketplace/OrderListTable.tsx +++ b/frontend/src/components/marketplace/OrderListTable.tsx @@ -240,10 +240,19 @@ export function OrderListTable({ (isSortable ? onSort(column.sortKey!) : undefined)} + role={isSortable ? "button" : undefined} + tabIndex={isSortable ? 0 : undefined} + aria-sort={isActiveSort ? (sortDirection === "asc" ? "ascending" : "descending") : undefined} + onKeyDown={(e) => { + if (isSortable && (e.key === "Enter" || e.key === " ")) { + e.preventDefault(); + onSort(column.sortKey!); + } + }} className={cn( - "text-xs font-bold uppercase tracking-wider text-text-muted", + "text-xs font-bold uppercase tracking-wider text-text-muted select-none", column.className, - isSortable && "cursor-pointer hover:text-text-primary transition-colors" + isSortable && "cursor-pointer hover:text-text-primary transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 rounded" )} >
diff --git a/frontend/src/components/swap/SwapModals.stories.tsx b/frontend/src/components/swap/SwapModals.stories.tsx new file mode 100644 index 00000000..063efc06 --- /dev/null +++ b/frontend/src/components/swap/SwapModals.stories.tsx @@ -0,0 +1,137 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { SwapReviewModal } from "./SwapReviewModal"; +import { SwapSigningModal } from "./SwapSigningModal"; +import { useState } from "react"; +import { TransactionLifecycle } from "@/types"; + +const meta: Meta = { + title: "Swap/Modals", + parameters: { + layout: "centered", + }, +}; + +export default meta; + +// Dummy Payload for the modals +const mockSwapDetails = { + fromAsset: "XLM", + fromChain: "stellar", + fromAmount: "100.5", + toAsset: "BTC", + toChain: "bitcoin", + toAmount: "0.0021", + estimatedFees: "0.00001 XLM", + timelockHours: 24, + route: "Stellar → Bitcoin", + slippage: 0.5, + expirationMinutes: 30, +}; + +// ========================================== +// Swap Review Modal Stories +// ========================================== + +export const ReviewState: StoryObj = { + render: () => { + return ( + {}} + onConfirm={() => {}} + isConfirming={false} + swapDetails={mockSwapDetails} + /> + ); + }, +}; + +export const ReviewStateConfirming: StoryObj = { + render: () => { + return ( + {}} + onConfirm={() => {}} + isConfirming={true} + swapDetails={mockSwapDetails} + /> + ); + }, +}; + +// ========================================== +// Swap Signing Modal Stories +// ========================================== + +const mockLifecycleInProgress: TransactionLifecycle = { + currentStep: "sign", + retryable: false, + steps: [ + { key: "init", status: "completed", label: "Initialize Swap", description: "Creating swap request" }, + { key: "sign", status: "active", label: "Sign Transaction", description: "Waiting for wallet signature" }, + { key: "submit", status: "idle", label: "Submit to Network", description: "Broadcasting to network" }, + ], +}; + +const mockLifecycleFailed: TransactionLifecycle = { + currentStep: "sign", + retryable: true, + steps: [ + { key: "init", status: "completed", label: "Initialize Swap", description: "Creating swap request" }, + { key: "sign", status: "error", label: "Sign Transaction", description: "User rejected request", errorMessage: "User rejected request" }, + { key: "submit", status: "idle", label: "Submit to Network", description: "Broadcasting to network" }, + ], +}; + +const mockLifecycleCompleted: TransactionLifecycle = { + currentStep: "submit", + retryable: false, + steps: [ + { key: "init", status: "completed", label: "Initialize Swap", description: "Creating swap request" }, + { key: "sign", status: "completed", label: "Sign Transaction", description: "Waiting for wallet signature" }, + { key: "submit", status: "completed", label: "Submit to Network", description: "Broadcasting to network" }, + ], +}; + +export const SigningInProgress: StoryObj = { + render: () => { + return ( + {}} + onCancel={() => {}} + onRetry={() => {}} + lifecycle={mockLifecycleInProgress} + /> + ); + }, +}; + +export const SigningFailed: StoryObj = { + render: () => { + return ( + {}} + onCancel={() => {}} + onRetry={() => {}} + lifecycle={mockLifecycleFailed} + /> + ); + }, +}; + +export const SigningComplete: StoryObj = { + render: () => { + return ( + {}} + onCancel={() => {}} + onRetry={() => {}} + lifecycle={mockLifecycleCompleted} + /> + ); + }, +}; diff --git a/frontend/src/components/transactions/TransactionDetailModal.tsx b/frontend/src/components/transactions/TransactionDetailModal.tsx index 4f4f354d..970deee3 100644 --- a/frontend/src/components/transactions/TransactionDetailModal.tsx +++ b/frontend/src/components/transactions/TransactionDetailModal.tsx @@ -202,11 +202,11 @@ export function TransactionDetailModal({ tx, onClose, onRetry }: TransactionDeta View on Explorer - -
diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx index 909d7e55..7000342a 100644 --- a/frontend/src/components/ui/button.tsx +++ b/frontend/src/components/ui/button.tsx @@ -85,9 +85,9 @@ export const Button = forwardRef( {...props} > {loading ? ( - +