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
63 changes: 33 additions & 30 deletions src/components/AddressDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Copy01Icon, Tick01Icon } from "@hugeicons/core-free-icons";
import { HugeiconsIcon } from "@hugeicons/react";
import { useState } from "react";

import { Tooltip } from "@/components/ui/Tooltip";
import { cn } from "@/lib/utils";
import { truncateAddress } from "@/lib/utils";

Expand Down Expand Up @@ -58,36 +59,38 @@ export function AddressDisplay({

const addressSpan = (
<div className="flex items-center gap-2 group">
<span
data-address
className={cn(
"break-all leading-relaxed",
text,
mono && "font-mono",
showFull && "select-all",
)}
title={address}
>
{display}
</span>
<button
onClick={copy}
aria-label={copied ? "Address copied" : "Copy address"}
className={cn(
"shrink-0 p-1 rounded-md transition-all",
copied
? "text-green bg-success-dim"
: "text-ink-3 hover:text-ink-2 hover:bg-surface-2 opacity-50 hover:opacity-100",
)}
title={copied ? "Copied!" : "Copy address"}
>
<HugeiconsIcon
icon={copied ? Tick01Icon : Copy01Icon}
size={iconSize}
color="currentColor"
strokeWidth={2}
/>
</button>
<Tooltip content={address}>
<span
data-address
className={cn(
"break-all leading-relaxed",
text,
mono && "font-mono",
showFull && "select-all",
)}
>
{display}
</span>
</Tooltip>
<Tooltip content={copied ? "Copied!" : "Copy address"}>
<button
onClick={copy}
aria-label={copied ? "Address copied" : "Copy address"}
className={cn(
"shrink-0 p-1 rounded-md transition-all",
copied
? "text-green bg-success-dim"
: "text-ink-3 hover:text-ink-2 hover:bg-surface-2 opacity-50 hover:opacity-100",
)}
>
<HugeiconsIcon
icon={copied ? Tick01Icon : Copy01Icon}
size={iconSize}
color="currentColor"
strokeWidth={2}
/>
</button>
</Tooltip>
</div>
);

Expand Down
2 changes: 1 addition & 1 deletion src/components/AssetFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,6 @@ function AssetFilter({
);
}

export { AssetFilter, AssetFilterSkeleton };
export { AssetFilter };
export type { AssetItem, AssetMeta, SortKey, VerifiedFilter };

4 changes: 2 additions & 2 deletions src/components/FeeEstimator.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ describe("FeeEstimator", () => {
// Wait for initial load to complete
await waitFor(() => expect(screen.getByText("100")).toBeInTheDocument());

const refreshButton = screen.getByTitle("Refresh");
const refreshButton = screen.getByRole("button", { name: "Refresh fee estimate" });
fireEvent.click(refreshButton);

await waitFor(() => expect(estimateFee).toHaveBeenCalledTimes(2));
Expand All @@ -87,7 +87,7 @@ describe("FeeEstimator", () => {
} as unknown as SorokitClient);

render(<FeeEstimator />);
const refreshButton = screen.getByTitle("Refresh");
const refreshButton = screen.getByRole("button", { name: "Refresh fee estimate" });
expect(refreshButton).toBeDisabled();
});

Expand Down
32 changes: 17 additions & 15 deletions src/components/FeeEstimator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { HugeiconsIcon } from "@hugeicons/react";
import { useCallback, useEffect, useState } from "react";

import { Badge } from "@/components/ui/Badge";
import { Tooltip } from "@/components/ui/Tooltip";
import { getClient } from "@/lib/client";
import { cn } from "@/lib/utils";

Expand Down Expand Up @@ -102,21 +103,22 @@ export function FeeEstimator({
Current Stellar base fee estimate
</p>
</div>
<button
onClick={() => void load()}
disabled={loading}
className="p-1.5 rounded-lg hover:bg-surface-2 text-ink-3 hover:text-ink-2 transition-colors disabled:opacity-40"
title="Refresh"
aria-label="Refresh fee estimate"
>
<HugeiconsIcon
icon={Refresh01Icon}
size={14}
color="currentColor"
strokeWidth={1.5}
className={loading ? "animate-spin" : ""}
/>
</button>
<Tooltip content="Refresh">
<button
onClick={() => void load()}
disabled={loading}
className="p-1.5 rounded-lg hover:bg-surface-2 text-ink-3 hover:text-ink-2 transition-colors disabled:opacity-40"
aria-label="Refresh fee estimate"
>
<HugeiconsIcon
icon={Refresh01Icon}
size={14}
color="currentColor"
strokeWidth={1.5}
className={loading ? "animate-spin" : ""}
/>
</button>
</Tooltip>
</div>

<div className="px-5 py-4" aria-live="polite" aria-atomic="true">
Expand Down
56 changes: 31 additions & 25 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,41 @@
@import "tailwindcss";

/* ─────────────────────────────────────────────────────────
BRAND & DESIGN TOKENS
Design Token Reference
Design Token Reference & Usage Context

Edit values here — they propagate to every component.
Components reference these as: bg-brand, text-ink, border-line, etc.

## Design Tokens

Naming convention: `--color-<group>[-<step>]`. Lower step numbers (or no
suffix) are the most prominent/high-contrast value in a group; higher
numbers step down in emphasis. Utility classes mirror the token name
1:1 (e.g. `--color-ink-3` → `.text-ink-3`), so when adding a component
prefer an existing token/utility pair over a one-off hex value — that
keeps the palette (and the light-theme override below) authoritative.
| Token | Default Value | Intended Usage Context |
| :--- | :--- | :--- |
| `--color-brand` | `#55852b` | Primary brand/action color for buttons, active tabs, primary highlights |
| `--color-brand-hover` | `#426625` | Hover and active pressed states for primary brand buttons |
| `--color-brand-dim` | `#17260d` | Subtle background tint for brand highlighted elements |
| `--color-base` | `#0d0d0d` | Main application page background |
| `--color-surface` | `#141414` | Primary container surfaces: cards, sidebars, topbar header |
| `--color-surface-2` | `#1c1c1c` | Secondary surfaces: input backgrounds, button hover states, tooltips, dropdowns |
| `--color-surface-3` | `#1e1e1e` | Tertiary surfaces: active navigation items, subtle card sub-sections |
| `--color-line` | `#2a2a2a` | Default border for cards, inputs, and layout dividers |
| `--color-line-2` | `#333333` | Stronger border variant for hover states, focus states, scrollbars, active outlines |
| `--color-ink` | `#ebebeb` | Primary high-contrast text and primary icons |
| `--color-ink-2` | `#999999` | Secondary text for labels, descriptions, and address monospace text |
| `--color-ink-3` | `#555555` | Muted text for subtle hints, disabled states, and metadata |
| `--color-ink-4` | `#3a3a3a` | Very muted text for section headers, inactive indicators, and subtle dividers |
| `--color-green` | `#22c55e` | Success status accent, positive balance changes |
| `--color-orange` | `#f97316` | Warning status accent, pending transactions |
| `--color-red` | `#ef4444` | Error status accent, negative alerts, destructive actions |
| `--color-teal` | `#14b8a6` | Info accent, contract event indicators |
| `--color-purple` | `#a855f7` | Special status accent, governance badges |
| `--color-success-bg` | `rgba(34, 197, 94, 0.1)` | Tinted success banner/card background |
| `--color-error-bg` | `rgba(239, 68, 68, 0.1)` | Tinted error banner/card background |
| `--color-qr-canvas-bg` | `#ffffff` | Fixed light background for QR code canvas contrast |
| `--color-qr-canvas-fg` | `#0d0d0d` | Fixed dark foreground for QR code canvas contrast |
───────────────────────────────────────────────────────── */
:root {
color-scheme: dark;

Token groups:
- Brand (`--color-brand*`) e.g. --color-brand: #55852b
Primary action color — buttons, links, active states.
- Surfaces (`--color-base`, `--color-surface*`) e.g. --color-surface: #141414
Background layers, darkest (base) to lightest (surface-3).
- Borders (`--color-line*`) e.g. --color-line: #2a2a2a
Dividers and outlines; `-2` is the stronger/active variant.
- Text (`--color-ink*`) e.g. --color-ink: #ebebeb
Foreground text, from primary (`ink`) to most muted (`ink-4`).
- Semantic (`--color-green|orange|red|teal|purple`)
Status accents used for badges, icons, and inline indicators.
- State bg/border (`--color-success-*`, `--color-error-*`)
Tinted backgrounds/borders for success and error UI (banners, inputs).
- QR canvas (`--color-qr-canvas-*`)
Fixed light-on-dark colors for the QR code canvas; not part of the
dark/light palette swap since QR codes need consistent contrast.
/* ── Brand ── */lette swap since QR codes need consistent contrast.
───────────────────────────────────────────────────────── */
:root {
/* ── Brand ── */
Expand Down
Loading