Hooks
useNumformatter
Hook for formatting numbers with currency and ordinal notation support
Overview
useNumformatter is a custom hook that provides a number formatting function with built-in support for currency display, ordinal notation, and decimal formatting. It wraps the formatNumber and formatOrdinal utilities with additional features like currency symbols. By deafult it formats numbers with the Nigerian Naira (₦) symbol, but it can be configured to use any currency prefix eg say with global state or local storage or api calls
Installation
npx shadcn@latest add https://foodease-dev-registry.cap.reachcinema.io/r/v1/use-numformatter.jsonUsage
Basic Usage
import useNumformatter from "@/hooks/useNumformatter"
export default function PriceDisplay() {
const { formatNum } = useNumformatter()
return (
<div>
<p>{formatNum({ number: 1234.56 })}</p>
{/* Output: ₦1,234.56 */}
</div>
)
}Format as Currency
import useNumformatter from "@/hooks/useNumformatter"
export default function Product({ price }: { price: number }) {
const { formatNum } = useNumformatter()
return (
<div className="product-card">
<h3>Product Name</h3>
<p className="price">
{formatNum({ number: price, asCurrency: true })}
</p>
</div>
)
}Format as Ordinal
import useNumformatter from "@/hooks/useNumformatter"
export default function Metrics() {
const { formatNum } = useNumformatter()
return (
<div>
<p>Users: {formatNum({ number: 1500000, asOrdinal: true, asCurrency:false })}</p>
{/* Output: 2M */}
<p>Views: {formatNum({ number: 2500, asOrdinal: true, asCurrency:false })}</p>
{/* Output: 3K */}
</div>
)
}Custom Prefix
import useNumformatter from "@/hooks/useNumformatter"
export default function MultiCurrency() {
const { formatNum } = useNumformatter()
return (
<div>
<p>{formatNum({ number: 100, prefix: "$",asCurrency:false })}</p>
{/* Output: $100.00 */}
</div>
)
}API Reference
useNumformatter
const { formatNum } = useNumformatter()Returns:
| Property | Type | Description |
|---|---|---|
formatNum | (config: Config) => string | Function to format numbers |
formatNum Config
interface Config {
number: number | string // The value to format
asCurrency?: boolean // Add currency symbol (₦)
prefix?: string // Custom prefix, to make it override default currency, pass asCurrency: false
asOrdinal?: boolean // Format as K/M/G/T/P/E
forceDecimal?: boolean // Always show decimal places
}Examples
Price List
import useNumformatter from "@/hooks/useNumformatter"
export default function PriceList({ items }) {
const { formatNum } = useNumformatter()
return (
<ul>
{items.map(item => (
<li key={item.id}>
<span>{item.name}</span>
<span>{formatNum({ number: item.price })}</span>
</li>
))}
</ul>
)
}Dashboard Stats
import useNumformatter from "@/hooks/useNumformatter"
export default function Dashboard({ stats }) {
const { formatNum } = useNumformatter()
return (
<div className="grid grid-cols-3 gap-4">
<div className="stat-card">
<h3>Total Users</h3>
<p className="text-2xl">
{formatNum({ number: stats.users, asOrdinal: true, asCurrency:false })}
</p>
</div>
<div className="stat-card">
<h3>Revenue</h3>
<p className="text-2xl">
{formatNum({ number: stats.revenue })}
</p>
</div>
<div className="stat-card">
<h3>Page Views</h3>
<p className="text-2xl">
{formatNum({ number: stats.views, asOrdinal: true, asCurrency:false })}
</p>
</div>
</div>
)
}Invoice Generator
import useNumformatter from "@/hooks/useNumformatter"
export default function Invoice({ items }) {
const { formatNum } = useNumformatter()
const subtotal = items.reduce((sum, item) => sum + item.price, 0)
const tax = subtotal * 0.1
const total = subtotal + tax
return (
<div className="invoice">
<table>
<tbody>
{items.map(item => (
<tr key={item.id}>
<td>{item.name}</td>
<td>{formatNum({ number: item.price })}</td>
</tr>
))}
</tbody>
<tfoot>
<tr>
<td>Subtotal</td>
<td>{formatNum({ number: subtotal, })}</td>
</tr>
<tr>
<td>Tax (10%)</td>
<td>{formatNum({ number: tax, })}</td>
</tr>
<tr className="font-bold">
<td>Total</td>
<td>{formatNum({ number: total, })}</td>
</tr>
</tfoot>
</table>
</div>
)
}Social Media Counts
import useNumformatter from "@/hooks/useNumformatter"
export default function SocialStats({ followers, likes, views }) {
const { formatNum } = useNumformatter()
return (
<div className="flex gap-6">
<div>
<p className="text-sm text-gray-500">Followers</p>
<p className="text-xl font-semibold">
{formatNum({ number: followers, asOrdinal: true, asCurrency:false })}
</p>
</div>
<div>
<p className="text-sm text-gray-500">Likes</p>
<p className="text-xl font-semibold">
{formatNum({ number: likes, asOrdinal: true, asCurrency:false })}
</p>
</div>
<div>
<p className="text-sm text-gray-500">Views</p>
<p className="text-xl font-semibold">
{formatNum({ number: views, asOrdinal: true, asCurrency:false })}
</p>
</div>
</div>
)
}Shopping Cart Total
import useNumformatter from "@/hooks/useNumformatter"
export default function CartSummary({ items }) {
const { formatNum } = useNumformatter()
const total = items.reduce((sum, item) => sum + item.price * item.quantity, 0)
return (
<div className="cart-summary">
{items.map(item => (
<div key={item.id} className="flex justify-between">
<span>{item.name} × {item.quantity}</span>
<span>{formatNum({ number: item.price * item.quantity, })}</span>
</div>
))}
<div className="border-t pt-4 flex justify-between font-bold">
<span>Total</span>
<span>{formatNum({ number: total})}</span>
</div>
</div>
)
}Percentage Display
import useNumformatter from "@/hooks/useNumformatter"
export default function ProgressBar({ value, max }) {
const { formatNum } = useNumformatter()
const percentage = (value / max) * 100
return (
<div>
<div className="flex justify-between mb-2">
<span>Progress</span>
<span>{formatNum({ number: percentage, asCurrency:false, suffix: "%" })}</span>
</div>
<div className="h-2 bg-gray-200 rounded">
<div
className="h-full bg-blue-500 rounded"
style={{ width: `${percentage}%` }}
/>
</div>
</div>
)
}Dynamic Currency Selector
import useNumformatter from "@/hooks/useNumformatter"
import { useState } from "react"
export default function CurrencyConverter() {
const { formatNum } = useNumformatter()
const [amount] = useState(100)
const [currency, setCurrency] = useState("$")
return (
<div>
<select value={currency} onChange={(e) => setCurrency(e.target.value)}>
<option value="$">USD</option>
<option value="€">EUR</option>
<option value="£">GBP</option>
<option value="₦">NGN</option>
</select>
<p className="text-2xl">
{formatNum({ number: amount, prefix: currency, asCurrency:false })}
</p>
</div>
)
}File Size Formatter
import useNumformatter from "@/hooks/useNumformatter"
export default function FileInfo({ bytes, name }) {
const { formatNum } = useNumformatter()
return (
<div className="file-item">
<span>{name}</span>
<span className="text-gray-500">
{formatNum({ number: bytes, asOrdinal: true, asCurrency:false })}B
</span>
</div>
)
}
// Usage
<FileInfo name="document.pdf" bytes={2500000} />
// Shows: document.pdf 3MBConfiguration
Default Currency
The hook defaults to the Nigerian Naira (₦) symbol. To change the default currency:
// In the hook file (registry/v1/hooks/useNumformatter.tsx)
const currency = "$" // Change from "₦" to your preferred symbolNotes
- Default currency symbol is ₦ (Nigerian Naira)
asCurrencyoption adds ₦ prefix automaticallyprefixoption overrides will combine currency and prefix unlessasCurrencyis false, then it overrides itasOrdinalformats as K/M/G/T/P/E
Type Definition
interface Config {
number: number | string
asCurrency?: boolean
prefix?: string
asOrdinal?: boolean
forceDecimal?: boolean
}
function useNumformatter(): {
formatNum: (config: Config) => string
}Dependencies
@/lib/helpers/numberHelpers(formatNumber, formatOrdinal)- React (
useCallback)