Show USD-equivalent value in cosmetic info tooltip (#4571)

## Summary

fixes #4171

The question-mark info tooltip on store cosmetics now shows the item's
equivalent USD value, but only when both:

1. The item has **no product** (i.e. it can't be purchased directly with
money), and
2. It **is purchasable with plutonium** (`priceHard`) — caps-only items
show nothing.

The value is computed at the fixed rate of 20 plutonium = $1.00 (same
rate as the custom currency card) and rendered as e.g. `Value: $2.50`.

## Changes

- `CosmeticButton.ts` — compute `usdValue` (`priceHard / 20`) when the
item has no product and has a plutonium price; pass it to
`<cosmetic-info>`
- `CosmeticInfo.ts` — new optional `usdValue` property rendered as a
tooltip line between the ad-free and color lines
- `en.json` — new `cosmetics.usd_value` key with a `{usd}` placeholder
so translators can position the amount

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Evan
2026-07-10 15:40:09 -07:00
committed by GitHub
parent 8405c8e896
commit a794eca4d6
3 changed files with 18 additions and 1 deletions
+2 -1
View File
@@ -398,7 +398,8 @@
"per_day": "/day",
"rare": "Rare",
"soft": "Caps",
"uncommon": "Uncommon"
"uncommon": "Uncommon",
"usd_value": "Value: {usd}"
},
"difficulty": {
"difficulty": "Nation difficulty",
+5
View File
@@ -306,6 +306,10 @@ export class CosmeticButton extends LitElement {
const isSkin = type === "skin";
const isOwnedSubscription =
type === "subscription" && active.relationship === "owned";
// Equivalent USD value at 20 plutonium = $1.00, shown only for items that
// can't be bought directly with money but can be bought with plutonium.
const usdValue =
!c?.product && priceHard !== undefined ? priceHard / 20 : undefined;
// Switching tiers shows "Switch"; a first-time subscribe shows price only.
const dollarLabelKey =
type === "subscription" && this.userHasSubscription
@@ -357,6 +361,7 @@ export class CosmeticButton extends LitElement {
.rarity=${c!.rarity}
.colorPalette=${active.colorPalette?.name}
.showAdFree=${isPurchasable}
.usdValue=${usdValue}
></cosmetic-info>`
: nothing}
+11
View File
@@ -25,6 +25,10 @@ export class CosmeticInfo extends LitElement {
@property({ type: Boolean })
showAdFree: boolean = false;
/** Equivalent USD value; only set for plutonium-only items. */
@property({ type: Number })
usdValue?: number;
createRenderRoot() {
return this;
}
@@ -61,6 +65,13 @@ export class CosmeticInfo extends LitElement {
${translateText("cosmetics.adfree")}
</div>`
: nothing}
${this.usdValue !== undefined
? html`<div>
${translateText("cosmetics.usd_value", {
usd: `$${this.usdValue.toFixed(2)}`,
})}
</div>`
: nothing}
${this.colorPalette
? html`<div>
${translateText("cosmetics.color_label")}