DEV Community

Cover image for Display Rupiah Values Beautifully with formatCompact()
Adamm
Adamm

Posted on • Edited on

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
Enter fullscreen mode Exit fullscreen mode

Basic Usage

import { formatCompact } from '@indodev/toolkit';

formatCompact(1500000);
// β†’ 'Rp 1,5 juta'

formatCompact(1000000);
// β†’ 'Rp 1 juta'  // Note: proper Indonesian grammar!
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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! πŸš€
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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' }
// ]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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)'
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Make your UI cleaner today! πŸš€

Top comments (0)