Display Rupiah Values Beautifully with formatCompact()
Ever noticed how Instagram shows "1.2M likes" instead of "1,200,000 likes"? That's compact formatting - and your Indonesian apps need it too.
Large numbers like Rp 1.500.000.000 take up too much space and are hard to read at a glance. That's why I built formatCompact() in @indodev/toolkit - it formats Rupiah using Indonesian units: ribu, juta, miliar, triliun.
Installation
npm install @indodev/toolkit
Basic Usage
import { formatCompact } from '@indodev/toolkit';
formatCompact(1500000);
// → 'Rp 1,5 juta'
formatCompact(1000000);
// → 'Rp 1 juta' // Note: proper Indonesian grammar!
Notice how it outputs "1 juta" not "1,0 juta"? That's proper Indonesian grammar built-in.
Real-World Use Cases
1. Dashboard Statistics
Perfect for KPI cards and metrics:
const stats = {
revenue: 125000000,
users: 450000,
transactions: 1500000000
};
console.log(`Revenue: ${formatCompact(stats.revenue)}`);
console.log(`Active Users: ${formatCompact(stats.users)}`);
console.log(`GMV: ${formatCompact(stats.transactions)}`);
// Output:
// Revenue: Rp 125 juta
// Active Users: Rp 450 ribu
// GMV: Rp 1,5 miliar
Much cleaner than "Rp 125.000.000", right?
2. Social Media Posts
Show funding announcements or milestones:
const announcements = [
{ company: 'Tokopedia', funding: 1500000000000 },
{ company: 'Gojek', funding: 3000000000000 },
{ company: 'Bukalapak', funding: 850000000000 }
];
announcements.forEach(a => {
console.log(`${a.company} raised ${formatCompact(a.funding)}! 🚀`);
});
// Output:
// Tokopedia raised Rp 1,5 triliun! 🚀
// Gojek raised Rp 3 triliun! 🚀
// Bukalapak raised Rp 850 miliar! 🚀
3. E-commerce Product Listings
When space is limited (mobile cards, grids):
const products = [
{ name: 'iPhone 15 Pro', price: 18000000 },
{ name: 'MacBook Air M2', price: 16500000 },
{ name: 'AirPods Pro', price: 3500000 }
];
// Mobile card view
products.forEach(p => {
console.log(`${p.name}\n${formatCompact(p.price)}\n`);
});
// Output:
// iPhone 15 Pro
// Rp 18 juta
//
// MacBook Air M2
// Rp 16,5 juta
//
// AirPods Pro
// Rp 3,5 juta
4. Real Estate Listings
Property prices with clean display:
const properties = [
{ type: 'Apartment', price: 850000000 },
{ type: 'House', price: 2500000000 },
{ type: 'Villa', price: 5200000000 }
];
properties.forEach(p => {
console.log(`${p.type}: ${formatCompact(p.price)}`);
});
// Output:
// Apartment: Rp 850 juta
// House: Rp 2,5 miliar
// Villa: Rp 5,2 miliar
5. Chart Labels
Keep your charts readable:
const monthlyRevenue = [
{ month: 'Jan', revenue: 450000000 },
{ month: 'Feb', revenue: 520000000 },
{ month: 'Mar', revenue: 680000000 },
{ month: 'Apr', revenue: 1200000000 }
];
// For chart Y-axis labels
const chartData = monthlyRevenue.map(data => ({
x: data.month,
y: data.revenue,
label: formatCompact(data.revenue)
}));
console.log(chartData);
// Output:
// [
// { x: 'Jan', y: 450000000, label: 'Rp 450 juta' },
// { x: 'Feb', y: 520000000, label: 'Rp 520 juta' },
// { x: 'Mar', y: 680000000, label: 'Rp 680 juta' },
// { x: 'Apr', y: 1200000000, label: 'Rp 1,2 miliar' }
// ]
6. Financial News App
Display market cap, volume, etc:
const stockInfo = {
company: 'Bank BCA',
marketCap: 985000000000000,
volume: 125000000000
};
console.log(`${stockInfo.company}`);
console.log(`Market Cap: ${formatCompact(stockInfo.marketCap)}`);
console.log(`Volume: ${formatCompact(stockInfo.volume)}`);
// Output:
// Bank BCA
// Market Cap: Rp 985 triliun
// Volume: Rp 125 miliar
7. Startup Pitch Decks
Show traction metrics cleanly:
const metrics = {
arr: 12000000000, // Annual Recurring Revenue
mrr: 1000000000, // Monthly Recurring Revenue
runway: 24000000000 // Cash runway
};
console.log('📊 Key Metrics');
console.log(`ARR: ${formatCompact(metrics.arr)}`);
console.log(`MRR: ${formatCompact(metrics.mrr)}`);
console.log(`Runway: ${formatCompact(metrics.runway)}`);
// Output:
// 📊 Key Metrics
// ARR: Rp 12 miliar
// MRR: Rp 1 miliar
// Runway: Rp 24 miliar
8. Handling Edge Cases
The function smartly handles different ranges:
// Trillions
formatCompact(1500000000000); // → 'Rp 1,5 triliun'
// Billions
formatCompact(2500000000); // → 'Rp 2,5 miliar'
// Millions
formatCompact(3500000); // → 'Rp 3,5 juta'
// Hundreds of thousands (uses 'ribu')
formatCompact(500000); // → 'Rp 500 ribu'
// Below 100k (standard format, not compact)
formatCompact(85000); // → 'Rp 85.000'
formatCompact(1500); // → 'Rp 1.500'
// Negative values
formatCompact(-1500000); // → '-Rp 1,5 juta'
When to Use formatCompact vs formatRupiah
Use formatCompact() when:
- Space is limited (mobile cards, tooltips)
- Quick scanning is important (dashboards, charts)
- Exact values don't matter (social media, announcements)
Use formatRupiah() when:
- Exact amounts matter (invoices, receipts)
- Official documents (contracts, reports)
- Payment screens (checkout, transfers)
Example: Hybrid Approach
import { formatCompact, formatRupiah } from '@indodev/toolkit';
// Product card (compact)
const cardPrice = formatCompact(15000000); // 'Rp 15 juta'
// Checkout page (exact)
const checkoutPrice = formatRupiah(15000000); // 'Rp 15.000.000'
// Tooltip (both!)
const tooltip = `${cardPrice} (${formatRupiah(15000000, { symbol: false })})`;
// 'Rp 15 juta (15.000.000)'
Indonesian Grammar Rules Built-In
The function follows proper Indonesian grammar:
- ✅ "1 juta" not "1,0 juta"
- ✅ "1,5 juta" for 1.5 million
- ✅ Uses comma (,) for decimals
- ✅ Automatically rounds to 1 decimal place
TypeScript Support
import { formatCompact } from '@indodev/toolkit';
// Fully typed
const formatted: string = formatCompact(1500000);
// Works with computed values
const total = prices.reduce((sum, p) => sum + p, 0);
const display = formatCompact(total);
Why Use This?
- ✅ Zero dependencies - just 30KB total
- ✅ Proper Indonesian - follows local grammar rules
- ✅ Smart rounding - removes unnecessary decimals
- ✅ Wide range support - from thousands to trillions
- ✅ Battle-tested - 95%+ test coverage
What's Next?
Explore other utilities in @indodev/toolkit:
-
formatRupiah()- Full Rupiah formatting with options -
validateNIK()- Validate Indonesian National ID -
validatePhoneNumber()- Phone number validation
Get started:
npm install @indodev/toolkit
- 📦 NPM: npmjs.com/package/@indodev/toolkit
- 📖 Docs: toolkit.adamm.cloud
- ⭐ GitHub: github.com/choiruladamm/indo-dev-utils
Make your UI cleaner today! 🚀
Top comments (0)