Skip to content

Commit 2d7b30d

Browse files
webview: six terminal polish fixes (market chrome, SOL mark, tier colors, iCloud picker, context readout) (#199)
* webview: market header and chrome join the terminal idiom Pre-terminal drift on the market screen, trued up: - The connected RPC chip was a rounded Tailwind-green pill with a bare gear button, directly under the Add Helius key banner that already speaks the terminal idiom. Now the same an-bracket bar as its sibling (term green tokens, mono uppercase network, corner ticks), and the whole row taps through to the key form instead of a tiny gear target. - The SKILL and WORKFLOW browse tabs gain their kana subs, matching the profile view's AGENT and COMMUNITY tabs. - The header balance becomes a control: it shows the real Solana mark (the three-bar logotype, replacing the circled-ring lookalike) and taps through to your own agent profile. The skills readout shares the mark; balance and Publish center on the header axis. * webview: hairline under the agent tab section headings The tiny uppercase labels on the profile agent tab (Verified work, Skills) floated over their content with nothing anchoring them. Each gets the existing hairline (var(--an-line)). The community tab and the skill detail already carry their own terminal section headers, so they are untouched. * webview: the agent card tier badge reads the tier ramp The card's STAR_TIERS table already declares the shared an-tier tokens so the tier reads the same on the card and the profile, but the badge painted the wallet accent instead: BRONZE could be pink. It now takes its tier's token (copper, silver, gold, violet), matching the profile gauge and the VS Code directory. Everything else on the card keeps the wallet accent. * webview: tap the context ring for the numbers behind it The ring's data lived in a title tooltip, which touch never sees and mouse users rarely find. Tapping the ring now opens a small terminal readout (tokens / window, percent in the ring's color, compacting state), tap away to close. The hover tooltip stays. * webview: one Solana mark for every SOL amount The SOL amounts wore a circled-ring lookalike (the 9678 dingbat) in the agent card EARNED footer, the SD card price chip, and the buy receipt, while the market header had just gained the real three-bar mark. The mark moves into the shared icons module as SolIcon (currentColor, sized for inline text) and every SOL amount now uses it. * webview: offer iCloud Drive in the storage picker on macOS The core has shipped the icloud backend all along (icloudStorage: a folder in the user's iCloud Drive that macOS syncs itself, no OAuth, no tokens), the VS Code surface labels it, and connectCloud accepts the kind. But the react picker offered only device / Google Drive / custom, so a Mac user already mirroring to iCloud saw a picker with no active row and no way to choose their actual backend. The option renders only when the host UA says Macintosh (Tauri, a Mac browser, VS Code on a Mac), so Android and Windows never see a folder they cannot have. One tap connects: no input, no OAuth, matching how the backend works. Strings carry the ko and ru translations like the rest of the picker; the storage row now names iCloud Drive when it is active. --------- Co-authored-by: RemilioNubilio <275382225+RemilioNubilio@users.noreply.github.com> Co-authored-by: sumin <dwckey5356@gmail.com>
1 parent 6e1da1c commit 2d7b30d

9 files changed

Lines changed: 124 additions & 22 deletions

File tree

surfaces/webview/src/chat/Composer.tsx

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,21 @@ import { CHAT_SLASH_COMMANDS } from "@iqlabs-official/agent-sdk/chat/slashComman
1010

1111
// ── Context dot (compact donut circle for mobile, mirrors Claude Code's meter) ──
1212
// Colors: green < 60 %, amber < 85 %, red ≥ 85 %. Orange pulse while compacting.
13+
// Tapping it opens a small readout of the numbers behind the ring: the title
14+
// tooltip only exists for mouse hover, which touch (and most desktop users)
15+
// never see.
1316
function CtxDot({ tokens, window: win, compacting }: { tokens: number; window: number; compacting?: boolean }) {
17+
const [open, setOpen] = useState(false);
18+
const rootRef = useRef<HTMLSpanElement>(null);
19+
// Tap-away closes: listen only while open, the same pattern the pickers use.
20+
useEffect(() => {
21+
if (!open) return;
22+
const close = (e: PointerEvent) => {
23+
if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);
24+
};
25+
document.addEventListener("pointerdown", close);
26+
return () => document.removeEventListener("pointerdown", close);
27+
}, [open]);
1428
const frac = Math.min(1, tokens / win);
1529
const pct = Math.round(frac * 100);
1630
const color = compacting
@@ -21,10 +35,37 @@ function CtxDot({ tokens, window: win, compacting }: { tokens: number; window: n
2135
const fmtK = (n: number) => n >= 1000 ? Math.round(n / 1000) + "k" : String(n);
2236
return (
2337
<span
24-
className="ml-auto flex items-center"
38+
ref={rootRef}
39+
className="ml-auto relative flex items-center"
2540
title={compacting ? "Compacting context…" : `Context: ${tokens.toLocaleString()} / ${win.toLocaleString()} tokens (${pct}%)\n${fmtK(tokens)} / ${fmtK(win)} ctx`}
26-
style={{ cursor: "default" }}
2741
>
42+
{open && (
43+
<div
44+
className="an-term-mono absolute bottom-full right-0 z-30 mb-2 whitespace-nowrap px-3 py-2.5 text-[10px] font-bold tracking-wider"
45+
style={{ background: "var(--an-bg-1)", border: "1px solid var(--an-line)", color: "var(--an-fg-dim)", boxShadow: "0 10px 30px rgba(0,0,0,0.5)" }}
46+
>
47+
<div className="mb-1 uppercase" style={{ color: "var(--an-fg-mute)" }}>Context</div>
48+
{compacting ? (
49+
<div style={{ color: "var(--an-orange, #f80)" }}>COMPACTING…</div>
50+
) : (
51+
<>
52+
<div style={{ color: "var(--an-fg)" }}>{tokens.toLocaleString()} / {win.toLocaleString()} tk</div>
53+
<div className="mt-0.5 flex items-center gap-1.5">
54+
<span style={{ color }}>{pct}%</span>
55+
<span style={{ color: "var(--an-fg-mute)" }}>used · compacts near full</span>
56+
</div>
57+
</>
58+
)}
59+
</div>
60+
)}
61+
<button
62+
type="button"
63+
aria-label="Context usage"
64+
aria-expanded={open}
65+
onClick={() => setOpen((v) => !v)}
66+
className="flex items-center active:opacity-80"
67+
style={{ background: "none", border: 0, padding: 0 }}
68+
>
2869
<svg width="18" height="18" viewBox="0 0 18 18" style={{ display: "block" }}>
2970
<circle cx="9" cy="9" r={r} fill="none" stroke="var(--an-line, #333)" strokeWidth="2.5" />
3071
<circle
@@ -38,6 +79,7 @@ function CtxDot({ tokens, window: win, compacting }: { tokens: number; window: n
3879
style={compacting ? { transformBox: "fill-box", transformOrigin: "center", animation: "ctxspin 1s linear infinite" } : undefined}
3980
/>
4081
</svg>
82+
</button>
4183
{compacting && <style>{`@keyframes ctxspin { from { transform: rotate(-90deg); } to { transform: rotate(270deg); } }`}</style>}
4284
</span>
4385
);

surfaces/webview/src/chat/Sessions.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ function StorageOption({ active, title, subtitle, onClick }: { active: boolean;
135135

136136
type SettingsMode = "list" | "configure" | "wallet" | "connect" | "gdrive" | "custom" | "helius" | "github" | "engines" | "language";
137137

138+
// The server runs on the host this page came from, so its OS decides whether an
139+
// iCloud Drive folder can exist. Every macOS host webview (Tauri WKWebView, a
140+
// browser on the Mac, VS Code's webview) carries Macintosh in the UA; Android
141+
// and Windows do not.
142+
const IS_MAC = typeof navigator !== "undefined" && /Macintosh/.test(navigator.userAgent);
143+
138144
export function Sessions({
139145
onClose,
140146
embedded = false,
@@ -523,7 +529,7 @@ export function Sessions({
523529
unlocked={!!state.walletAddress}
524530
onUnlocked={() => setSettingsMode("connect")}
525531
label={t(M.settings.storage)}
526-
subtitle={cloudConnected ? `${info?.account ?? (info?.kind === "gdrive" ? "Google Drive" : t(M.settings.customCloud))}${cloudSync ? ` · ${cloudSync.ok ? t(M.settings.synced) : t(M.settings.syncError)}` : ""}` : t(M.settings.localOnly)}
532+
subtitle={cloudConnected ? `${info?.account ?? (info?.kind === "gdrive" ? "Google Drive" : info?.kind === "icloud" ? "iCloud Drive" : t(M.settings.customCloud))}${cloudSync ? ` · ${cloudSync.ok ? t(M.settings.synced) : t(M.settings.syncError)}` : ""}` : t(M.settings.localOnly)}
527533
icon={<svg width="22" height="22" viewBox="0 0 22 22" fill="none" stroke="currentColor" strokeWidth="1.55" strokeLinecap="round" strokeLinejoin="round"><path d="M4 7.5c0-1.4 3.1-2.5 7-2.5s7 1.1 7 2.5S14.9 10 11 10 4 8.9 4 7.5Z" /><path d="M4 7.5v7c0 1.4 3.1 2.5 7 2.5s7-1.1 7-2.5v-7" /><path d="M4 11c0 1.4 3.1 2.5 7 2.5s7-1.1 7-2.5" /></svg>}
528534
/>
529535
{!state.walletAddress && (
@@ -809,6 +815,23 @@ export function Sessions({
809815
setSettingsMode("configure");
810816
}}
811817
/>
818+
{/* iCloud = a folder macOS syncs (core icloudStorage, decided with zo): one tap,
819+
no OAuth. Only offered where that folder can exist, so Android never sees it. */}
820+
{IS_MAC && (
821+
<StorageOption
822+
active={info?.kind === "icloud" && !!info?.connected}
823+
title="iCloud Drive"
824+
subtitle={
825+
info?.kind === "icloud" && info?.connected
826+
? `${t(M.storagePicker.connected)}${info.location ? ` · ${info.location}` : ""}`
827+
: t(M.storagePicker.icloudSub)
828+
}
829+
onClick={() => {
830+
send({ type: "connectCloud", kind: "icloud" });
831+
setSettingsMode("configure");
832+
}}
833+
/>
834+
)}
812835
<StorageOption
813836
active={info?.kind === "gdrive" && !!info?.connected}
814837
title="Google Drive"

surfaces/webview/src/i18n/messages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ export const M = {
287287
thisDeviceSub: m("Sessions stay local. No cloud mirror.", "세션이 로컬에만 저장됩니다. 클라우드 미러 없음.", "Сессии остаются локально. Без облачного зеркала."),
288288
connected: m("Connected", "연결됨", "Подключено"),
289289
gdriveSub: m("Mirror sessions to your own Google account", "내 Google 계정으로 세션 미러링", "Зеркалить сессии в ваш Google аккаунт"),
290+
icloudSub: m("Mirror to your iCloud Drive folder. No sign in.", "iCloud Drive 폴더로 미러링. 로그인 불필요.", "Зеркалить в папку iCloud Drive. Без входа."),
290291
customStorage: m("Custom Storage", "커스텀 저장소", "Своё Хранилище"),
291292
customStorageSub: m("Mirror to an S3 / WebDAV / HTTP endpoint", "S3 / WebDAV / HTTP 엔드포인트로 미러링", "Зеркалить в S3 / WebDAV / HTTP endpoint"),
292293
done: m("Done", "완료", "Готово"),

surfaces/webview/src/icons.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,15 @@ export function CollectionIcon(props: IconProps) {
179179
</svg>
180180
);
181181
}
182+
183+
// The Solana mark (the official three slanted bars), sized for inline text
184+
// use next to SOL amounts. currentColor so it inherits the amount's tone.
185+
export function SolIcon(props: IconProps) {
186+
return (
187+
<svg width="10" height="8" viewBox="0 0 398 312" fill="currentColor" style={{ display: "inline-block", verticalAlign: "-0.5px" }} aria-label="SOL" {...props}>
188+
<path d="M64.6 237.9c2.4-2.4 5.7-3.8 9.2-3.8h317.4c5.8 0 8.7 7 4.6 11.1l-62.7 62.7c-2.4 2.4-5.7 3.8-9.2 3.8H6.5c-5.8 0-8.7-7-4.6-11.1l62.7-62.7z"/>
189+
<path d="M64.6 3.8C67.1 1.4 70.4 0 73.8 0h317.4c5.8 0 8.7 7 4.6 11.1l-62.7 62.7c-2.4 2.4-5.7 3.8-9.2 3.8H6.5c-5.8 0-8.7-7-4.6-11.1L64.6 3.8z"/>
190+
<path d="M333.1 120.9c-2.4-2.4-5.7-3.8-9.2-3.8H6.5c-5.8 0-8.7 7-4.6 11.1l62.7 62.7c2.4 2.4 5.7 3.8 9.2 3.8h317.4c5.8 0 8.7-7 4.6-11.1l-62.7-62.7z"/>
191+
</svg>
192+
);
193+
}

surfaces/webview/src/market/AgentDirectory.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { walletAvatarSvg, walletBandColor } from "./walletAvatar";
55
import { AgentListSkeleton } from "./Skeletons";
66
import type { Reputation } from "../transport/protocol";
77
import { LockedGate } from "../unlock/UnlockProvider";
8-
import { LockIcon } from "../icons";
8+
import { LockIcon, SolIcon } from "../icons";
99

1010
// The card's single accent — the avatar's own hue, normalized to one chic mid-tone so it reads
1111
// the same as a tag fill / gauge fill whatever the avatar's exact shade. The colour avatar is the
@@ -88,7 +88,10 @@ function AgentCard({ agent, self, onOpen }: { agent: Reputation; self?: boolean;
8888
<div className="an-ac-access">
8989
アクセス / ACCESS
9090
<br />
91-
<span className={`an-ac-tier ${tier ? "" : "unranked"}`}>{tierName}</span>
91+
{/* The badge reads the tier ramp, not the wallet accent: BRONZE is copper
92+
everywhere (card, profile gauge, VS Code directory), per the shared
93+
an-tier tokens this file already declares for exactly that reason. */}
94+
<span className={`an-ac-tier ${tier ? "" : "unranked"}`} style={tier ? { background: `var(${tier.token})` } : undefined}>{tierName}</span>
9295
</div>
9396
</div>
9497
<div className="an-ac-body">
@@ -114,7 +117,7 @@ function AgentCard({ agent, self, onOpen }: { agent: Reputation; self?: boolean;
114117
</div>
115118
<div className="an-ac-foot">
116119
<span className="an-ac-box" />
117-
<span>&gt;EARNED <span className="earn">{earned}&#9678;</span></span>
120+
<span>&gt;EARNED <span className="earn">{earned} <SolIcon width={8} height={6.5} /></span></span>
118121
<span className="an-ac-box" />
119122
</div>
120123
</div>

surfaces/webview/src/market/AgentProfileView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ export function AgentProfileView({ profile, onBack, onOpenSkill }: Props) {
883883
{/* WORK — verified repos as tall terminal-folders in a horizontal swipe row */}
884884
{verifiedRepos.length > 0 && (
885885
<div>
886-
<p className="mb-2 text-[11px] uppercase tracking-wide" style={{ color: "var(--an-fg-mute)" }}>Verified work</p>
886+
<p className="mb-2 border-b pb-1.5 text-[11px] uppercase tracking-wide" style={{ color: "var(--an-fg-mute)", borderColor: "var(--an-line)" }}>Verified work</p>
887887
<div className="an-workrow flex snap-x gap-3 overflow-x-auto pb-1 [-webkit-overflow-scrolling:touch]">
888888
{sortedRepos.map((r) => (
889889
<WorkCard key={`${r.owner}/${r.name}`} repo={r} skillById={skillById} onOpenSkill={onOpenSkill} onAllSkills={setRepoSkills} />
@@ -895,7 +895,7 @@ export function AgentProfileView({ profile, onBack, onOpenSkill }: Props) {
895895
{/* SKILLS — SD-card collectibles (colour = category, sigil generated from the name) */}
896896
{allSkills.length > 0 && (
897897
<div>
898-
<p className="mb-2 text-[11px] uppercase tracking-wide" style={{ color: "var(--an-fg-mute)" }}>Skills</p>
898+
<p className="mb-2 border-b pb-1.5 text-[11px] uppercase tracking-wide" style={{ color: "var(--an-fg-mute)", borderColor: "var(--an-line)" }}>Skills</p>
899899
<div className="an-cardgrid grid grid-cols-3 gap-3.5">
900900
{allSkills.map((card) => (
901901
<SkillSdCard

surfaces/webview/src/market/MarketScreen.tsx

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { SkillCard } from "../transport/protocol";
99
import { HeliusSetupPanel } from "../settings/HeliusKeyForm";
1010
import { SkillDetailSkeleton, MarketListSkeleton, AgentProfileSkeleton } from "./Skeletons";
1111
import { LockedGate, useUnlock } from "../unlock/UnlockProvider";
12-
import { LockIcon } from "../icons";
12+
import { LockIcon, SolIcon } from "../icons";
1313
import { AlertCard } from "../Alert";
1414
import { haptics } from "../haptics";
1515

@@ -223,14 +223,24 @@ export function MarketScreen({ tab, onBack, onGoMarket }: { tab: ShellTab; onBac
223223
{/* SKILLS: SOL balance + owned-count readout (stacked, right-aligned) */}
224224
{isSkills && (
225225
<div className="shrink-0 text-right">
226-
{balanceSol && <div className="an-term-mono text-[13px] font-bold leading-none" style={{ color: "var(--an-term-fg-2)", letterSpacing: "0.5px" }}>{balanceSol} </div>}
226+
{balanceSol && <div className="an-term-mono flex items-center justify-end gap-1.5 text-[13px] font-bold leading-none" style={{ color: "var(--an-term-fg-2)", letterSpacing: "0.5px" }}>{balanceSol} <SolIcon /></div>}
227227
<div className="an-term-mono text-[8px] font-bold tracking-wider" style={{ color: "var(--an-term-fg-7)", marginTop: "5px" }}>[ {state.marketOwned.length} OWNED ]</div>
228228
</div>
229229
)}
230-
{/* MARKET: SOL balance + publish */}
231-
{isMarket && balanceSol && <span className="an-term-mono shrink-0 text-xs font-bold" style={{ color: "var(--an-term-fg-2)", letterSpacing: "0.5px" }}>{balanceSol}</span>}
230+
{/* MARKET: SOL balance (taps through to your own agent profile) + publish */}
231+
{isMarket && balanceSol && (
232+
<button
233+
onClick={() => { if (state.walletAddress) send({ type: "getAgentProfile", wallet: state.walletAddress }); }}
234+
disabled={!state.walletAddress}
235+
aria-label="Your agent profile"
236+
className="an-term-mono flex shrink-0 items-center gap-1.5 self-center text-xs font-bold active:opacity-80"
237+
style={{ color: "var(--an-term-fg-2)", letterSpacing: "0.5px" }}
238+
>
239+
{balanceSol} <SolIcon />
240+
</button>
241+
)}
232242
{isMarket && (
233-
<LockedGate reason="publish" onUnlocked={() => setView("publish")} className="shrink-0" badge={false}>
243+
<LockedGate reason="publish" onUnlocked={() => setView("publish")} className="shrink-0 self-center" badge={false}>
234244
<button
235245
onClick={() => setView("publish")}
236246
className="an-term-mono text-[10px] font-bold uppercase tracking-wider active:opacity-80"
@@ -273,11 +283,17 @@ export function MarketScreen({ tab, onBack, onGoMarket }: { tab: ShellTab; onBac
273283
</button>
274284
)}
275285
{isMarket && state.rpcStatus?.hasKey && (
276-
<div className="mx-3 mt-2 shrink-0 flex items-center gap-1.5 rounded-lg border border-green-800/40 bg-green-900/10 px-3 py-1.5 text-[11px] text-green-500">
277-
<span></span>
278-
<span>{state.rpcStatus.network} · {state.rpcStatus.masked}</span>
279-
<button onClick={() => setView("helius")} className="ml-auto text-zinc-600 hover:text-zinc-400"></button>
280-
</div>
286+
<button
287+
onClick={() => setView("helius")}
288+
className="an-bracket mx-3.5 mt-2.5 shrink-0 flex items-center gap-2.5 px-3 py-2.5 active:opacity-80"
289+
style={{ border: "1px solid var(--an-term-green-line)", color: "var(--an-term-green)", "--ts": "8px", "--bk": "var(--an-term-green-bg)", "--tk": "var(--an-term-green-line)" } as CSSProperties}
290+
>
291+
<span style={{ fontSize: "8px" }}></span>
292+
<span className="an-term-mono flex-1 text-left text-[10px] font-bold tracking-wide">
293+
<span className="uppercase">{state.rpcStatus.network}</span> · {state.rpcStatus.masked}
294+
</span>
295+
<span className="an-term-mono font-bold"></span>
296+
</button>
281297
)}
282298

283299
{/* Browse tabs (market only): skill / workflow — agents moved to their own Agent tab */}
@@ -294,7 +310,10 @@ export function MarketScreen({ tab, onBack, onGoMarket }: { tab: ShellTab; onBac
294310
: "border-transparent text-zinc-500 active:text-zinc-300",
295311
].join(" ")}
296312
>
297-
{t}s
313+
<div>{t}s</div>
314+
<div style={{ fontFamily: "'Noto Sans JP', sans-serif", fontWeight: 500, fontSize: "8px", marginTop: "3px", color: view === "browse" && state.marketTab === t ? "var(--an-term-fg-7)" : "var(--an-term-line-3)" }}>
315+
{t === "skill" ? "スキル" : "ワークフロー"}
316+
</div>
298317
</button>
299318
))}
300319
{/* HIDE OWNED filter — on by default so the grid surfaces NEW skills */}

surfaces/webview/src/market/SkillReceiptOverlay.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useMemo } from "react";
2+
import { SolIcon } from "../icons";
23
import type { SkillCard } from "../transport/protocol";
34
import { skillSigilSvg } from "./skillSigil";
45

@@ -11,7 +12,7 @@ const SCANLINES = "repeating-linear-gradient(0deg, rgba(0,0,0,0.22) 0, rgba(0,0,
1112

1213
export function SkillReceiptOverlay({ card, onClick }: { card: SkillCard; onClick?: () => void }) {
1314
const sigil = useMemo(() => skillSigilSvg(card.name, card.category), [card.name, card.category]);
14-
const paid = card.price && card.price !== "0" ? `${(Number(card.price) / 1e9).toFixed(2)} ◎` : "FREE";
15+
const paidSol = card.price && card.price !== "0" ? (Number(card.price) / 1e9).toFixed(2) : null;
1516
const mint = card.id ? `${card.id.slice(0, 4)}${card.id.slice(-4)}` : "-";
1617
const kindLabel = card.type === "workflow" ? "Workflow" : "Skill";
1718

@@ -34,7 +35,7 @@ export function SkillReceiptOverlay({ card, onClick }: { card: SkillCard; onClic
3435
<div className="flex min-w-0 flex-1 flex-col gap-2 pt-0.5">
3536
<span className="an-rcpt-k">{kindLabel}</span>
3637
<p className="an-rcpt-name">&gt;{card.name}<span className="unlock-cursor">_</span></p>
37-
<div className="an-rcpt-row"><span className="an-rcpt-k">Paid</span><span>{paid}</span></div>
38+
<div className="an-rcpt-row"><span className="an-rcpt-k">Paid</span><span>{paidSol ? <>{paidSol} <SolIcon width={8} height={6.5} /></> : "FREE"}</span></div>
3839
<div className="an-rcpt-row"><span className="an-rcpt-k">Mint</span><span style={{ color: "var(--an-green)" }}>{mint}</span></div>
3940
<div className="mt-auto flex flex-col gap-1.5">
4041
<span className="an-rcpt-k">Sync</span>

surfaces/webview/src/market/SkillSdCard.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useMemo } from "react";
2+
import { SolIcon } from "../icons";
23
import type { SkillCard } from "../transport/protocol";
34
import { skillSigilSvg } from "./skillSigil";
45
import { mediaUrl } from "./mediaUrl";
@@ -48,7 +49,7 @@ export function SkillSdCard({ card, owned, disposed, firing, dim, onOpen }: Prop
4849
{/* the data chip: copies big, price + state stacked small */}
4950
<div className="an-sd-chip">
5051
<span className="an-sd-big">{card.supply ?? "—"}</span>
51-
<span className="an-sd-meta">{priceSol ? `${priceSol}◎` : "FREE"}<br />{state}</span>
52+
<span className="an-sd-meta">{priceSol ? <>{priceSol}<SolIcon width={7} height={5.5} /></> : "FREE"}<br />{state}</span>
5253
</div>
5354
{/* 2a gold star grade: summed GitHub stars of repos using this skill (issue #89), corner
5455
brackets on the right axis under the mark. Hidden at 0 so plain skills stay clean. */}

0 commit comments

Comments
 (0)