refactor(converter): split converter card into modular section components

This commit is contained in:
2026-03-30 19:26:18 +02:00
parent a45393ac00
commit 24f21d25bc
11 changed files with 1075 additions and 755 deletions

View File

@@ -0,0 +1,82 @@
"use client";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
interface ConverterCardAmountInputProps {
amountInput: string;
amountPrefix?: string;
amountInputPaddingLeft?: string;
amountError: string | null;
quickAmounts: readonly number[];
activeQuickAmount: number | null;
onAmountChange: (nextValue: string) => void;
onQuickAmountSelect: (value: number) => void;
}
export function ConverterCardAmountInput({
amountInput,
amountPrefix,
amountInputPaddingLeft,
amountError,
quickAmounts,
activeQuickAmount,
onAmountChange,
onQuickAmountSelect,
}: ConverterCardAmountInputProps) {
return (
<div className="space-y-2">
<label
htmlFor="amount"
className="text-xs uppercase tracking-[0.14em] text-muted-foreground"
>
Amount
</label>
<div className="relative">
{amountPrefix ? (
<span className="pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-sm text-muted-foreground/80">
{amountPrefix}
</span>
) : null}
<Input
id="amount"
type="text"
inputMode="decimal"
value={amountInput}
onChange={(event) => onAmountChange(event.target.value)}
placeholder="Enter amount"
className="h-14 rounded-xl bg-background/70 px-4 text-lg"
style={amountInputPaddingLeft ? { paddingLeft: amountInputPaddingLeft } : undefined}
aria-invalid={Boolean(amountError)}
aria-describedby={amountError ? "amount-error" : undefined}
/>
</div>
<div className="flex flex-wrap items-center gap-2 pt-1">
{quickAmounts.map((quickAmount) => (
<Button
key={quickAmount}
type="button"
variant="outline"
size="sm"
onClick={() => onQuickAmountSelect(quickAmount)}
className={cn(
"h-7 rounded-full border-border/70 px-3 text-xs text-muted-foreground transition-colors hover:text-foreground",
activeQuickAmount === quickAmount
? "border-cyan-300/50 bg-cyan-500/15 text-cyan-100"
: "",
)}
aria-label={`Set amount to ${quickAmount}`}
>
{quickAmount}
</Button>
))}
</div>
{amountError ? (
<p id="amount-error" className="text-sm text-red-300">
{amountError}
</p>
) : null}
</div>
);
}