{quoting ? (
-
+
{t("swap.to.quoteLoading")}
) : (
@@ -365,7 +478,9 @@ export function SwapCard({
{t("swap.destination.label")}
-
+
{dstAddressError && (
-
{dstAddressError}
+
+ {dstAddressError}
+
)}
+ {/* Slippage */}
+
+ {t("swap.slippage.minOut", { amount: minOut, token: dstToken.symbol })}
+
+ )}
+
{/* Quote details */}
{quote && srcAmount && (
- {([
- ["swap.quote.solver", quote.solver],
- ["swap.quote.fillTime", t("swap.quote.fillTimeValue", { seconds: quote.fillTimeSeconds })],
- ["swap.quote.priceImpact", t("swap.quote.priceImpactValue", {
- percent: quote.priceImpactPct < 0.01
- ? t("swap.quote.priceImpactBelowMin")
- : quote.priceImpactPct.toFixed(2),
- })],
- ["swap.quote.protocolFee", t("swap.quote.protocolFeeValue", { percent: quote.protocolFeePct.toFixed(2) })],
- ["swap.quote.rate", quote.rate],
- ] as const).map(([labelKey, value]) => (
+ {(
+ [
+ ["swap.quote.solver", quote.solver, null],
+ [
+ "swap.quote.fillTime",
+ t("swap.quote.fillTimeValue", { seconds: quote.fillTimeSeconds }),
+ "swap.quote.fillTime.tooltip",
+ ],
+ [
+ "swap.quote.priceImpact",
+ t("swap.quote.priceImpactValue", {
+ percent:
+ quote.priceImpactPct < 0.01
+ ? t("swap.quote.priceImpactBelowMin")
+ : quote.priceImpactPct.toFixed(2),
+ }),
+ "swap.quote.priceImpact.tooltip",
+ ],
+ [
+ "swap.quote.protocolFee",
+ t("swap.quote.protocolFeeValue", {
+ percent: quote.protocolFeePct.toFixed(2),
+ }),
+ "swap.quote.protocolFee.tooltip",
+ ],
+ ["swap.quote.rate", quote.rate, null],
+ ] as const
+ ).map(([labelKey, value, tooltipKey]) => (
-
{t(labelKey)}
+ {tooltipKey ? (
+
+
+ {t(labelKey)}
+
+
+ ) : (
+
{t(labelKey)}
+ )}
{submission.error}
+
+ {submission.error}
+
)}
{/* Submit */}
@@ -449,8 +614,21 @@ export function SwapCard({
>
{isSubmitting ? (
-
@@ -458,8 +636,21 @@ export function SwapCard({
t("swap.submit.success")
) : quoting ? (
-
-
+
+
{t("swap.submit.findingRoute")}
@@ -474,9 +665,7 @@ export function SwapCard({
)}
-
- {t("swap.disclaimer")}
-
+ {t("swap.disclaimer")}
);
diff --git a/src/components/Tooltip.stories.tsx b/src/components/Tooltip.stories.tsx
new file mode 100644
index 0000000..78cea58
--- /dev/null
+++ b/src/components/Tooltip.stories.tsx
@@ -0,0 +1,98 @@
+import type { Meta, StoryObj } from "@storybook/nextjs-vite";
+import { Tooltip } from "./Tooltip";
+
+const meta = {
+ title: "Components/Tooltip",
+ component: Tooltip,
+ tags: ["autodocs"],
+ parameters: {
+ layout: "centered",
+ docs: {
+ description: {
+ component:
+ "Accessible WAI-ARIA tooltip. Shown on hover and keyboard focus, " +
+ "dismissed with Escape. Associated to its trigger via `aria-describedby`. " +
+ "Tap-to-toggle on touch devices.",
+ },
+ },
+ },
+} satisfies Meta