fix(ui): disambiguate annual tier labels

"$50/yr" was ambiguous — could mean the $5 tier in annual mode or the
$50 tier in monthly mode. On /join the dropdown now shows both prices
("$5/mo → $50/yr") in annual mode. On the account page TierPicker
gains a subtitle slot; annual mode shows "$N/mo tier" beneath the
annual price so members recognize which tier they're on.
This commit is contained in:
Jennie Robinson Faber 2026-04-18 22:06:38 +01:00
parent 8ceaebb268
commit fd9ce5bc2c
3 changed files with 28 additions and 8 deletions

View file

@ -8,6 +8,7 @@
@click="$emit('update:modelValue', tier.amount)"
>
<span class="tier-amount">{{ tier.display }}</span>
<span v-if="tier.subtitle" class="tier-subtitle">{{ tier.subtitle }}</span>
</div>
</div>
</template>
@ -78,6 +79,15 @@ defineEmits(["update:modelValue"]);
color: var(--candle);
}
.tier-subtitle {
display: block;
margin-top: 4px;
font-size: 11px;
color: var(--text-dim);
font-family: "Commit Mono", monospace;
letter-spacing: 0.02em;
}
@media (max-width: 768px) {
.tier-picker {
flex-wrap: wrap;

View file

@ -467,14 +467,19 @@ const paymentToken = ref(null);
const circleOptions = getCircleOptions();
// Minimal labels for the dropdown reactive to cadence.
// In annual mode, show both monthly and annual price so $50/yr (the $5 tier annual)
// is visually distinct from $500/yr (the $50 tier annual).
const contributionItems = computed(() => {
return Object.values(CONTRIBUTION_TIERS).map((tier) => {
const base = tier.amount;
if (base === 0) return { value: tier.value, label: "$0" };
const amt = getTierAmount(tier, cadence.value);
const suffix = cadence.value === "annual" ? "/yr" : "/mo";
const hint = tier.value === "15" && cadence.value !== "annual" ? " (suggested)" : "";
return { value: tier.value, label: `$${amt}${suffix}${hint}` };
const monthlyLabel = `$${base}/mo`;
const priceLabel =
cadence.value === "annual"
? `${monthlyLabel}$${getTierAmount(tier, "annual")}/yr`
: monthlyLabel;
const hint = tier.value === "15" ? " (suggested)" : "";
return { value: tier.value, label: `${priceLabel}${hint}` };
});
});

View file

@ -239,10 +239,15 @@ const BASE_TIERS = [
const tiers = computed(() => {
const cadence = memberData.value?.billingCadence || 'monthly';
return BASE_TIERS.map((t) => ({
return BASE_TIERS.map((t) => {
if (t.amount === 0) return { ...t, display: '$0' };
const suffix = cadence === 'annual' ? '/yr' : '/mo';
return {
...t,
display: t.amount === 0 ? '$0' : `$${getTierAmount(t, cadence)}`,
}));
display: `$${getTierAmount(t, cadence)}${suffix}`,
subtitle: cadence === 'annual' ? `$${t.amount}/mo tier` : null,
};
});
});
const currentContributionLabel = computed(() => {