Money, dates and numbers
Format prices, dates and digits the way the store and the page language expect, with useMoney, useDate and useNumber.
1250 is not what a shopper should read. On this store's Arabic pages a price is written with two decimals, Arabic-Indic digits and the riyal sign, and a date reads "16 سبتمبر 2026" rather than "2026-09-16". Three hooks do this for you, following the page language and the store's settings:
useMoney()formats prices;useDate()formats dates, and "3 hours ago";useNumber()writes counts and other numbers with the digits the store chose.
All three on one line
Change the quantity, then switch the ar / en pill (top bar, or the ☰ menu on a phone). This store turned Arabic numbers on, so watch which values change digits in English, and read the last row carefully.
useArabicNumerals- false (a store setting)
'Total: ' + format(total)- Total: [object Object]
import { useDate, useNumber } from '@salla.sa/twilight-theme-engine/hooks';
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';
export function OrderLine({ quantity, unitPrice, orderedAt }: {
quantity: number;
unitPrice: number;
orderedAt: string;
}) {
const { format } = useMoney();
const { format: formatNumber } = useNumber();
const { format: formatDate } = useDate();
return (
<div className="order-line">
<span>× {formatNumber(quantity)}</span>
<strong>{format(unitPrice * quantity)}</strong>
<small>{formatDate(orderedAt, 'long')}</small>
</div>
);
}
Prices: useMoney
1,250.00
- isValid(amount)
- true
- parse('1,250.50 SAR')
- 1250.5
import { useMoney } from '@salla.sa/twilight-theme-engine/hooks/useMoney';
export function Price() {
const { format } = useMoney();
return <span className="price">{format(1250)}</span>;
}
- Always two decimal places, grouped the way the language groups thousands.
- The currency defaults to SAR, whatever the store's currency is. Pass
{ currency }when you show another one. - Arabic-Indic digits appear only for riyals, only on Arabic pages, and only when the store turned Arabic numbers on.
Dates: useDate
import { useDate, useIsClient } from '@salla.sa/twilight-theme-engine/hooks';
export function PostDate({ publishedAt = '2024-12-31T10:30:00' }: { publishedAt?: string }) {
const { format, ago } = useDate();
const isClient = useIsClient(); // relative time depends on the clock: render it after hydration
return (
<p>
<time dateTime={publishedAt}>{format(publishedAt)}</time>
{isClient && <span> · {ago(publishedAt)}</span>}
</p>
);
}
format(date, 'full' | 'long' | 'medium' | 'short' | 'time') accepts a date string, a timestamp, a Date, or the { date, timezone } objects some Salla responses use. ago(date) says how long ago in words.
Numbers: useNumber
- useArabicNumerals
- false
- format(value)
- Order #1250, 3 items
- toArabic(value)
- Order #١٢٥٠, ٣ items
import { useNumber } from '@salla.sa/twilight-theme-engine/hooks';
export function OrderLabel() {
const { format } = useNumber();
return <span>{format('Order #1250, 3 items')}</span>;
}
In engine terms
useMoneyhas its own subpath,@salla.sa/twilight-theme-engine/hooks/useMoney;useDateanduseNumberare exported only from the/hooksbarrel.useMoney().formatusesIntl.NumberFormat(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 }), cached per locale and options, then swaps the digits whenstore.settings.arabic_numbers_enabledis on and the locale starts withar. SAR returns a fragment with ansicon-saricon; any other code is formatted again withstyle: 'currency', which skips the digit swap (src/hooks/useMoney.tsx).- An empty amount returns
'-'only fortype: 'product'whenstore.settings.product.show_price_as_dashis on, otherwise''. useNumber().formatignores the language: it swaps digits whenever the store setting is on, and adds no thousands separator (src/hooks/useNumber.ts).useDateusesIntl.DateTimeFormatwith no time zone, so the server formats in UTC and the browser in the shopper's zone: a time close to midnight can land on different days in the two renders.ago()andnowread the clock. Render any of those after hydration, withuseIsClient().- Reference: useMoney, useDate, useNumber.