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: 4 additions & 4 deletions frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export default function Home() {

function SwapPreviewPanel() {
return (
<Card variant="raised" className="overflow-hidden shadow-glow-sm">
<Card variant="raised" className="overflow-hidden">
<div className="border-b border-border bg-surface-overlay/60 px-4 py-3 flex items-center justify-between">
<div className="flex items-center gap-2">
<ArrowRightLeft className="h-4 w-4 text-brand-500" />
Expand All @@ -156,8 +156,8 @@ function SwapPreviewPanel() {
<p className="text-[10px] font-medium uppercase tracking-widest text-text-muted mb-2">From</p>
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<div className="h-7 w-7 rounded-full bg-brand-500/20 flex items-center justify-center">
<span className="text-[10px] font-bold text-brand-500">XLM</span>
<div className="h-7 w-7 rounded-full bg-surface-raised flex items-center justify-center border border-border">
<span className="text-[10px] font-bold text-text-primary">XLM</span>
</div>
<div>
<p className="text-sm font-semibold text-text-primary">Stellar</p>
Expand Down Expand Up @@ -238,7 +238,7 @@ function FeatureCard({
return (
<Card
variant="glass"
className="p-8 transition-all hover:border-brand-500/50 hover:shadow-glow-sm"
className="p-8 transition-all hover:bg-surface-overlay/50 hover:border-border/80"
>
<div className="mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-surface-overlay border border-border">
{icon}
Expand Down
13 changes: 11 additions & 2 deletions frontend/src/components/marketplace/OrderListTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,19 @@ export function OrderListTable({
<th
key={column.key}
onClick={() => (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"
)}
>
<div className="flex items-center gap-2">
Expand Down
137 changes: 137 additions & 0 deletions frontend/src/components/swap/SwapModals.stories.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof SwapReviewModal> = {
render: () => {
return (
<SwapReviewModal
open={true}
onClose={() => {}}
onConfirm={() => {}}
isConfirming={false}
swapDetails={mockSwapDetails}
/>
);
},
};

export const ReviewStateConfirming: StoryObj<typeof SwapReviewModal> = {
render: () => {
return (
<SwapReviewModal
open={true}
onClose={() => {}}
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<typeof SwapSigningModal> = {
render: () => {
return (
<SwapSigningModal
open={true}
onClose={() => {}}
onCancel={() => {}}
onRetry={() => {}}
lifecycle={mockLifecycleInProgress}
/>
);
},
};

export const SigningFailed: StoryObj<typeof SwapSigningModal> = {
render: () => {
return (
<SwapSigningModal
open={true}
onClose={() => {}}
onCancel={() => {}}
onRetry={() => {}}
lifecycle={mockLifecycleFailed}
/>
);
},
};

export const SigningComplete: StoryObj<typeof SwapSigningModal> = {
render: () => {
return (
<SwapSigningModal
open={true}
onClose={() => {}}
onCancel={() => {}}
onRetry={() => {}}
lifecycle={mockLifecycleCompleted}
/>
);
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,11 @@ export function TransactionDetailModal({ tx, onClose, onRetry }: TransactionDeta
View on Explorer <ExternalLink className="h-4 w-4" />
</Button>
</a>
<Button variant="secondary" size="icon" className="rounded-xl h-11 w-11 shadow-sm">
<Download className="h-5 w-5" />
<Button variant="secondary" size="icon" className="rounded-xl h-11 w-11 shadow-sm" aria-label="Download receipt">
<Download className="h-5 w-5" aria-hidden="true" />
</Button>
<Button variant="secondary" size="icon" className="rounded-xl h-11 w-11 shadow-sm">
<Share2 className="h-5 w-5" />
<Button variant="secondary" size="icon" className="rounded-xl h-11 w-11 shadow-sm" aria-label="Share transaction">
<Share2 className="h-5 w-5" aria-hidden="true" />
</Button>
</div>
</Card>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,9 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
{...props}
>
{loading ? (
<Loader2 className="h-4 w-4 animate-spin shrink-0" />
<Loader2 className="h-4 w-4 animate-spin shrink-0" aria-hidden="true" />
) : (
icon && <span className="shrink-0">{icon}</span>
icon && <span className="shrink-0" aria-hidden="true">{icon}</span>
)}
{children}
</button>
Expand Down
Loading