diff --git a/src/lib/format.test.ts b/src/lib/format.test.ts index 49eb7b5..3f67ece 100644 --- a/src/lib/format.test.ts +++ b/src/lib/format.test.ts @@ -9,12 +9,16 @@ describe('formatCompactStars', () => { }); it('formats four-to-six digit counts with k', () => { - expect(formatCompactStars(1_000)).toBe('1.0k'); + expect(formatCompactStars(1_000)).toBe('1k'); expect(formatCompactStars(12_345)).toBe('12.3k'); }); + it('rounds counts in the 999.5k+ window up to M instead of producing 1000k', () => { + expect(formatCompactStars(999_999)).toBe('1M'); + }); + it('formats seven-digit counts with M', () => { - expect(formatCompactStars(1_000_000)).toBe('1.0M'); + expect(formatCompactStars(1_000_000)).toBe('1M'); expect(formatCompactStars(1_500_000)).toBe('1.5M'); }); }); diff --git a/src/lib/format.ts b/src/lib/format.ts index e9b57af..bd95c3a 100644 --- a/src/lib/format.ts +++ b/src/lib/format.ts @@ -1,5 +1,11 @@ +const COMPACT_FORMATTER = new Intl.NumberFormat('en', { + notation: 'compact', + maximumFractionDigits: 1, +}); + +// Intl emits "K" for thousands; the design uses lowercase k while keeping M. +// Use a global regex so future locale or ICU variants that produce more than +// one "K" still get normalized. export function formatCompactStars(count: number): string { - if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`; - if (count >= 1_000) return `${(count / 1_000).toFixed(1)}k`; - return count.toString(); + return COMPACT_FORMATTER.format(count).replace(/K/g, 'k'); }